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
  1. サンプルアプリケーションを作成します。

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)
  1. 依存するパッケージを含めて、ソースコードを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"
    }
}
  1. パラメータを環境変数に設定する。
LAMBDA_FUNCTION_NAME='SecretTest'
LAMBDA_ROLE_NAME='secret-test-python'
  1. 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'
  1. 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. [ソースとターゲットの選択] で以下の操作を行います。
  3. ソースの選択/ターゲットの選択を表の通り入力します。
ソースの選択 ターゲットの選択
IoT Cloud SecretTest
  1. [次へ] を選択します。
  2. [トピックフィルター][secrets/input] と入力し、 [次へ] を選択します。
  3. [完了] を選択します。

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

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

Greengrass のデプロイ

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

シークレットの確認

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

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

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

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

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

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

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

あとがき

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