[AWS IoT Greengrass V2] コンポーネントからシークレットマネージャにアクセスしてみました

2021.08.15

1 はじめに

IoT事業部の平内(SIN)です。

前回、AWS IoT Greengrass Core interprocess communication (IPC) を使用して、IoT Coreのメッセージブローカーにアクセスしてみました。

今回は、IPCでシークレットマネージャーの情報取得を試してみました。
参考:Retrieve secret values

2 Secret Manager

最初に取得の対象となるシークレット情報をAWS Secret Managerのコンソールから下記の内容で作成しました。

  • シークレットの名前: MySecret
  • シークレットキー: my-secret-key
  • シークレットの値: my-secret-value
  • シークレットのARN: arn:aws:secretsmanager:ap-northeast-1:XXXXXXXXXXX:secret:MySecret-ohlslJ

3 ポリシー

Greengrassでは、AWSのリソースへのパーミションは、ロールエリアス経由で利用されているロール(GreengrassV2TokenExchangeRole)に設定することができます。

今回は、Secret ManagerのREAD権を付与した、ポリシー(MySecretPolicy)を作成し、ロールに追加しました。

MySecretPolicy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "secretsmanager:GetSecretValue"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:secretsmanager:ap-northeast-1:XXXXXXXXXXXX:secret:MySecret-ohlslJ"
        }
    ]
}

GreengrassV2TokenExchangeRoleに追加

4 aws.greengrass.SecretManager

コンポーネントからSecret Managerにアクセスするためには、パブリックコンポーネントの1つであるaws.greengrass.SecretManagerが必要です。

依存関係でインストールすることも可能ですが、aws.greengrass.SecretManagerの設定に、アクセス先のシークレットのARNの指定が必要なため、ここでは、クラウド側からデプロイします。

デブロイ設定で、aws.greengrass.SecretManagerを追加し、コンポーネントの設定をクリックします。

マージを設定のところに下記の設定を追加します。

{
  "cloudSecrets": [
    {
      "arn": "arn:aws:secretsmanager:ap-northeast-1:XXXXXXXXXXX:secret:MySecret-ohlslJ"
    }
  ]
}

デプロイが完了すると、Greengrass CLIで設定が反映されている事を確認できます。

$ sudo /greengrass/v2/bin/greengrass-cli component list

・・・略・・・

Component Name: aws.greengrass.SecretManager
    Version: 2.0.9
    State: RUNNING
    Configuration: {"cloudSecrets":[{"arn":"arn:aws:secretsmanager:ap-northeast-1:XXXXXXXXXXXX:secret:MySecret-ohlslJ"}]}

・・・略・・・

5 recipe

レシピは、以下のようになっています。

accessControlでは、aws.greengrass.SecretManagerで、aws.greengrass#GetSecretValueが付与されています。

また、これは、必須ではありませんが、スクリプトのパラメータにシークレットのARNを渡しています。

com.example.GetSecret-1.0.0.yaml

---
RecipeFormatVersion: 2020-01-25
ComponentName: com.example.GetSecret
ComponentVersion: '1.0.0'
ComponentDependencies:
  aws.greengrass.SecretManager:
    VersionRequirement: "^2.0.0"
    DependencyType: HARD
ComponentConfiguration:
  DefaultConfiguration:
    SecretArn: arn:aws:secretsmanager:ap-northeast-1:439028474478:secret:MySecret-ohlslJ
    accessControl:
      aws.greengrass.SecretManager:
        com.example.GetSecret:secrets:1:
          policyDescription: Allows access to a secret.
          operations:
            - aws.greengrass#GetSecretValue
          resources:
            - "*"
Manifests:
  - Platform:
      os: linux
    Lifecycle:
      Install: pip3 install awsiotsdk
      Run: python3 -u {artifacts:path}/get_secret.py '{configuration:/SecretArn}'

6 artifact

Pythonコードは、下記を参考に作成しました。
https://docs.aws.amazon.com/greengrass/v2/developerguide/ipc-secret-manager.html#ipc-secret-manager-example-print-secret-python-recipe

GetSecretValueRequest()に、パラメータで受け取ったシークレットのARNを指定してアクセスしています。

get_secret.py

import json
import sys

import awsiot.greengrasscoreipc
from awsiot.greengrasscoreipc.model import (
    GetSecretValueRequest
)

secret_id = sys.argv[1] # SecretのARN

TIMEOUT = 10

ipc_client = awsiot.greengrasscoreipc.connect()

request = GetSecretValueRequest()
request.secret_id = secret_id

operation = ipc_client.new_get_secret_value()
operation.activate(request)
futureResponse = operation.get_response()

response = futureResponse.result(TIMEOUT)
secret_json = json.loads(response.secret_value.secret_string)
print('😍 Secret value: ' + str(secret_json))

7 動作確認

ログを確認すると、シークレット情報が取得できている事を確認できます。

  • 確認しやすいように一部編集しています
    $ sudo tail -f /greengrass/v2/logs/com.example.GetSecret.log
    com.example.GetSecret: shell-runner-start. {scriptName=services.com.example.GetSecret.lifecycle.Run, serviceName=com.example.GetSecret, currentState=STARTING, command=["python3 -u /greengrass/v2/packages/artifacts/com.example.GetSecret/1.0.0/get_s..."]}
    com.example.GetSecret: stdout. 😍 Secret value: {'my-secret-key': 'my-secret-value'}. {scriptName=services.com.example.GetSecret.lifecycle.Run, serviceName=com.example.GetSecret, currentState=RUNNING}
    com.example.GetSecret: Run script exited. {exitCode=0, serviceName=com.example.GetSecret, currentState=RUNNING}

8 最後に

今回は、IPCでシークレットマネージャーの情報取得を試してみました。

コンポーネントからは、aws.greengrass.SecretManagercloudSecretsに設定されたシークレットしか見えません。また、cloudSecretsは、ロールでアクセス可能になっているものしか設定できません。

本記事に紹介した順序通りに作業すると上手くいくと思います。

9 参考リンク


[AWS IoT Greengrass V2] RaspberryPIにインストールしてみました
[AWS IoT Greengrass V2] RaspberryPIでコンポーネントを作成してみました
[AWS IoT Greengrass V2] クラウド側から複数のコアデバイスにコンポーネントをデプロイしてみました
[AWS IoT Greengrass V2] クラウド側からコンポーネントを削除してみました
[AWS IoT Greengrass V2] ローカルデバッグコンソール(aws.greengrass.LocalDebugConsole)を使用してみました
[AWS IoT Greengrass V2] Lambda関数(コンポーネント)をデプロイしてみました
[AWS IoT Greengrass V2] コンポーネントからIoT CoreのメッセージブローカーにPublish/Subscribeしてみました