AWS IoT Greengrass Coreにシークレットをデプロイしてみた

2019.08.06

はじめに

おはようございます、加藤です。AWS IoT Greengrass Core(以降、Greengrass)でシークレットを扱いたい際に、最も単純な方法はハードコートを行う事です。とはいえ、ハードコートは行いたくないですよね...
Greengrassは、AWS Secret Mangaer(以降、Secrets Manger)と連携する事が可能です。これを利用すると、ハードコートを回避できます!!

環境

  • pipenv, version 2018.11.26
  • Python, 3.7.4
  • jq, jq-1.6
  • aws-cli, aws-cli/1.16.191 Python/3.7.4 Darwin/18.7.0 botocore/1.12.181

やってみた

シークレットの作成

  1. Secrets Manager コンソールにサインインします。
  2. [新しいシークレットを保存する] を選択します。
  3. [シークレットの種類を選択][その他のシークレット] を選択します。
    • Greengrassで利用したいシークレットが他の種類である場合は、それを選択します。
  4. [このシークレットに格納するキーと値のペアを指定します] で以下の操作を行います。
    1. シークレットキー/値を表の通り入力します。
シークレットキー
test abcdefghi
  1. 暗号化キーに [DefaultEncryptionKey] を選択してから、 [次へ] を選択します。
  2. [シークレット名に] 「greengrass-TestSecret」 と入力し、 [次へ] を選択します。
  3. 今回、ローテーションは不要なので、 [自動ローテーションを無効にする] を選択し、 [次へ] を選択します。
  4. レビューページで、設定を確認し、 [保存] を選択します。

Greengrass グループにローカルシークレットリソースを追加する

  1. AWS IoT コンソールにサインインし、 [Greengrass][グループ] の順に選択します。
  2. シークレットをデプロイするグループを選択します。
  3. [リソース][シークレット] の順に選択します。
  4. [シークレットリソースの追加] を選択します。
  5. [選択][greengrass-TestSecret] の順に選択します。
  6. ラベルの選択(オプション)ページで、 [次へ] を選択します。
  7. シークレットリソースに名前を付けるページで、設定を確認し、 [保存] を選択します。

Greengrass用のLambda関数のデプロイパッケージ作成

  1. Pipenvを利用して環境をセットアップします。
    mkdir -p src
    pipenv --python 3.7.4
    pipenv install greengrasssdk
    
  2. サンプルアプリケーションを作成します。

    src/secret_test.py

    import greengrasssdk
    
    secrets_client = greengrasssdk.client('secretsmanager')
    message_client = greengrasssdk.client('iot-data')
    message = ''
    
    def function_handler(event, context):
        response = secrets_client.get_secret_value(SecretId='greengrass-TestSecret')
        secret_value = response.get('SecretString')
        if secret_value is None:
            message = 'Failed to retrieve secret.'
        else:
            message = secret_value
        
        message_client.publish(topic='secrets/output', payload=message)
        print('published: ' + message)
    
  3. 依存するパッケージを含めて、ソースコードをZIP化します。
    pipenv lock -r | pip install -r /dev/stdin -t src/
    cd src
    zip -r ../secret_test_python.zip *
    cd ../
    

Greengrass用のLambda関数のデプロイ

  1. IAMロールの信頼されたエンティティにLambdaを設定する為の、JSONを作成する。

    deploy/trusted_policy_for_lambda.json

    {
        "Statement": {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    }
    
  2. パラメータを環境変数に設定する。
    LAMBDA_FUNCTION_NAME='SecretTest'
    LAMBDA_ROLE_NAME='secret-test-python'
    
  3. IAMロールを作成する。
    LAMBDA_ROLE_ARN=$(aws iam create-role \
          --role-name ${LAMBDA_ROLE_NAME} \
          --assume-role-policy-document file://deploy/trusted_policy_for_lambda.json \
          | jq -r '.Role.Arn')
    aws iam attach-role-policy \
      --role-name ${LAMBDA_ROLE_NAME} \
      --policy-arn 'arn:aws:iam::aws:policy/AWSLambdaExecute'
    
  4. Lambda関数を作成し、バージョンとエイリアスを作成する。
    aws lambda create-function \
      --function-name ${LAMBDA_FUNCTION_NAME} \
      --role ${LAMBDA_ROLE_ARN} \
      --runtime 'python3.7' \
      --handler 'secret_test.function_handler' \
      --zip-file fileb://secret_test_python.zip
    LAMBDA_VERSION=$(aws lambda publish-version \
      --function-name ${LAMBDA_FUNCTION_NAME} \
      --description '1' \
      | jq -r '.Version')
    aws lambda create-alias \
      --name 'RELEASE' \
      --function-name ${LAMBDA_FUNCTION_NAME} \
      --function-version ${LAMBDA_VERSION}
    

Lambda 関数を Greengrass グループに追加する

  1. AWS IoT コンソールにサインインし、 [Greengrass][グループ] の順に選択します。
  2. シークレットをデプロイするグループを選択します。
  3. [Lambda][Lambdaの追加] の順に選択します。
  4. [既存のLambdaの使用] を選択します。
    • 同じボタンが2つありますが、どちらを選択しても大丈夫です。
  5. [SecretTest][次へ] を選択します。
  6. [エイリアス: RELEASE][完了] を選択します。

シークレットリソースを Lambda 関数にアタッチする

  1. グループページで、[Lambda][SecretTest] の順に選択します。
  2. [リソース][シークレット][シークレットリソースのアタッチ] の順に選択します。
  3. [シークレットリソースの選択] を選択します。
  4. [MyTestSecret][保存] の順に選択します。

サブスクリプションを Greengrass グループに追加する

  1. グループページで、[サブスクリプション][サブスクリプションの追加] の順に選択します。
  2. [ソースとターゲットの選択] で以下の操作を行います。
    1. ソースの選択/ターゲットの選択を表の通り入力します。
ソースの選択 ターゲットの選択
IoT Cloud SecretTest
  1. [次へ] を選択します。

    1. [トピックフィルター][secrets/input] と入力し、 [次へ] を選択します。
    2. [完了] を選択します。

続けて、逆方向も追加します。

  1. グループページで、[サブスクリプション][サブスクリプションの追加] の順に選択します。
  2. [ソースとターゲットの選択] で以下の操作を行います。
    1. ソースの選択/ターゲットの選択を表の通り入力します。
ソースの選択 ターゲットの選択
SecretTest IoT Cloud
  1. [次へ] を選択します。

    1. [トピックフィルター][secrets/output] と入力し、 [次へ] を選択します。
    2. [完了] を選択します。

Greengrass のデプロイ

  1. グループページで、[アクション][デプロイ] の順に選択します。
  2. [自動検出] を選択します。

シークレットの確認

  1. AWS IoT コンソールにサインインし、 [テスト] を選択します。
  2. [トピックのサブスクリプション][secrets/output] と入力し、 [トピックへのサブスクライブ] を選択します。
  3. [トピックへサブスクライブする] を選択し、 [トピックのサブスクリプション][secrets/input] と入力し、 [トピックへのサブスクライブ] を選択します。
  4. [secrets/input][トピックに発行] の順に選択します。
    1. 画像では secret に なっていますが、 secrets が正しいです
  5. [secrets/output] を選択します。
    1. シークレットが表示されます。(数秒かかる場合があります)

シークレットのローテーション

シークレットを変更します。

  1. Secrets Manager コンソールにサインインします。
  2. [greengrass-TestSecret] を選択します。
  3. [シークレットの値を取得する] 、 編集するの順に選択します。
  4. シークレットの値を [123456] に変更します。

シークレットの確認の手順を実行します。
シークレットは変更前のままです。シークレットの更新を行った後は再度デプロイを行う必要があります。

Greengrass のデプロイの手順を実行します。 再度、シークレットの確認の手順を実行します。
シークレットが変更されている事を確認できました。

自動化したい場合は、Secrets MangaerのローテーションLambda関数を使用して、ローテーション後にデプロイを行うように実装すれば良さそうです。

あとがき

最近、業務でGreengrassを扱っているので、Greengrassのブログを書いてみました。
ローテーションに再デプロイが必要ですが、簡単・安全にシークレットを管理できて、とても便利ですね。