🖥

AWS Lambda ( Node.js 18.x ) で AWS System Manager (SSM) パラメータストアのSecure

2023/09/15に公開

公式

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ps-integration-lambda-extensions.html

SSM ( AWS Systems Manager ) のパラメータを作成しておく

ここでは

testparam

というキー名で登録する

Lambda関数を作成する

AWS上のlocalhostの固定のポートにGETリクエストするという仕組みのようだ

  • URLパラメータとしてSSMのパラメータ名を渡す name=testparam
  • 秘密値のDecryptのために withDecryption=true をURLパラメータとして渡す

リクエストヘッダに AWS_SESSION_TOKEN を付与する必要があるが
これはLambda実行ではデフォルトで設定される環境変数のようだ
なので自分で何かを設定する必要はない

コード例

index.mjs

export const handler = async (event) => {
  console.log("START");

  const response = await fetch(
    "http://localhost:2773/systemsmanager/parameters/get?name=testparam&withDecryption=true",
    {
      headers: {
      "X-Aws-Parameters-Secrets-Token": process.env.AWS_SESSION_TOKEN,
      }
    }
  )
  const json = await response.json()
  console.log("VALUE IS ...")
  console.log(json["Parameter"]["Value"])
};

実行権限の付与

Lambda実行の権限に以下を付与する必要がある

  • ssm:GetParameter — Parameter Store からパラメータの取得に必要
  • kms:Decrypt — Parameter Store から SecureString パラメータを取得するために必要

Lambdaの実行ロールは Lambda関数の 設定 > アクセス権限から確認できるのでこのロールに権限を付与する

以下はLambda関数を作成した時のデフォルトの権限に ssm / ksm の権限を付与したもの

{
	"Statement": [
		{
			"Action": [
				"logs:CreateLogGroup"
			],
			"Effect": "Allow",
			"Resource": "arn:aws:logs:<REGION>:<ACCOUNT_ID>:*"
		},
		{
			"Action": [
				"ssm:GetParameter"
			],
			"Effect": "Allow",
			"Resource": "arn:aws:ssm:<REGION>:<ACCOUNT_ID>:*"
		},
		{
			"Action": [
				"kms:Decrypt",
				"kms:*"
			],
			"Effect": "Allow",
			"Resource": "arn:aws:ksm:<REGION>:<ACCOUNT_ID>:*"
		},
		{
			"Action": [
				"logs:CreateLogStream",
				"logs:PutLogEvents"
			],
			"Effect": "Allow",
			"Resource": [
				"arn:aws:logs:<REGION>:<ACCOUNT_ID>:log-group:/aws/lambda/<LAMBDA_NAME>:*"
			]
		}
	],
	"Version": "2012-10-17"
}

パラメータのキー単位で権限を絞ることもできるようなので必要ならばそうする

Lambda関数にレイヤーを追加する

この機能は拡張なのでレイヤー追加が必要のようだ

<img width="804" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/60b2474e-70c3-4389-a5c8-6037b3b65d2e">

実行例

レスポンスとして以下のようなJSONが得られるのでこれをparseして利用すればOK
["Parameter"]["Value"] に値が入っている

{
  "Parameter": {
    "ARN": "arn:aws:ssm:<REGION>:<ACCOUNT_ID>:parameter/testparam",
    "DataType": "text",
    "LastModifiedDate": "2023-09-08T04:07:03.546Z",
    "Name": "testparam",
    "Selector": null,
    "SourceResult": null,
    "Type": "SecureString",
    "Value": "xxx",
    "Version": 1
  },
  "ResultMetadata": {}
}

実行時のエラー

bad session token or header key

リクエストヘッダのSESSION_KEYが間違っている

AccessDeniedException - ssm:GetParameter on resource

Lambdaの実行ロールにssm:GetParameterの権限がない場合に起こる

[AWS Parameters and Secrets Lambda Extension] 2023/09/08 05:01:38 ERROR GetParameter request encountered an error: operation error SSM: GetParameter, https response error StatusCode: 400, RequestID: *********, api error
AccessDeniedException: User: arn:aws:sts::
:assumed-role/example-role/xxx is not authorized to perform:ssm:GetParameter on resource: arn:aws:ssm:ap-northeast-1:
:parameter/testparam because no identity-based policy allows the ssm:GetParameter action

今回ここで少しはまった

原因は(当たり前だが)正しく権限付与が出来ていなかったことだった

Lambdaのデフォルトのポリシーに ssm:GetParameter を追加しようと思ってつい "Resource": "arn:aws:logs の方に許可を追加してしまっていたが
こちらはlogs用のリソース指定なので ssm の許可をしても意味がなかtgた

{
	"Statement": [
		{
			"Action": [
				"logs:CreateLogGroup",
				"kms:Decrypt",
				"kms:*"
			],
			"Effect": "Allow",
			"Resource": "arn:aws:logs:<REGION>:<ACCOUNT_ID>:*"
		}
	]
}

前述の通りResource / Action を正しく指定することで実行可能になった

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ

Twitter

https://twitter.com/YumaInaura

公開日時

2023-09-08

Discussion