💨

AWS Parameters and Secrets Lambda Extensionを使ってLambda実行時の環境変数を取得する

2023/08/10に公開

記事の内容

Lambdaコード内で環境変数やシークレットを使用したケースがよくあると思います。
Lambdaには環境変数設定で直接値を設定することができますが、簡易的な機能ですので暗号化もありませんし、厳密に管理するには心許ないです。
AWSには環境変数やシークレットの管理を目的とした、Paramter StoreやSecrets Manegerというサービスがあるのでぜひ活用したいです。
今回はSecrets Manegerで管理しているシークレットをLambda実行時に取得して参照する方法をまとめました。

関係する技術・ツール

  • Node.js 18
  • AWS Lambda
  • AWS Secrets Manager
  • AWS Parameters and Secrets Lambda Extension

作業の流れ

  1. シークレット作成
  2. Lambda作成
  3. 拡張機能(Lambda Layer)をLambdaに追加
  4. Lambda実行ロール編集
  5. Lambda実行

※全て東京リージョンで作業

1. シークレット作成

secrets managerコンソールから作成します。
とりあえず下記の入力で作成します。

シークレット名 シークレット(Key・・・Value)
test-secrets name・・・saito
country・・・japan

2. Lambda作成

次にLambdaを作成します。
下記の最小限だけ入力します。

関数名 runtime
test-get-secrets Node.js18

作成したLambdaのコードを以下のように変更します。

import { encode } from "querystring"

export const handler = async (event) => {
  const queryparams = encode({
    secretId: "<1で作成したsecrets managerのARN>"
  });

  const secrets = await fetch("http://localhost:2773/secretsmanager/get?" + queryparams,{
    headers: {
      "X-Aws-Parameters-Secrets-Token": process.env.AWS_SESSION_TOKEN
    }
  })
  .then(res => res.json())
  .then(res => res)
  .catch(err => console.error(err));
  
  console.log(JSON.parse(secrets.SecretString));
  
  const response = {
    statusCode: 200,
    body: JSON.parse(secrets.SecretString),
  };
  return response;
};

ポイントとしては下記になるかと思います。

  • エンドポイントはGETでhttp://localhost:2773/secretsmanager/get
  • リクエストヘッダに、X-Aws-Parameters-Secrets-Token: AWS_SESSION_TOKEN(AWS定義済み環境変数)を含める。含めないと401で未認証エラーになります。

3. 拡張機能(Lambda Layer)をLambdaに追加

secrets managerからシークレットを取得する仕組みですが、awsから提供されている拡張機能を使うことでsecrets managerへのエンドポイントが作成されるため、これによりアクセスできるようになります。
どうやらこの拡張機能の実態はlambda layerのようです。したがって関数にlambda layerを追加します。

2で作成したLambdaの詳細画面にあるレイヤー欄から「レイヤーの追加」を選択します。
「ARNを指定」を選択して入力欄に下記を入力します。

arn:aws:lambda:ap-northeast-1:133490724326:layer:AWS-Parameters-and-Secrets-Lambda-Extension:4

4. Lambda実行ロール編集

Lambdaがsecrets managerにアクセスするには実行ロールにポリシーが必要です。
「設定」->「アクセス権限」->実行ロールにある「ロール名」のリンクからロールのポリシーを編集します。
ポリシーには下記を追加します。

{
	"Effect": "Allow",
	"Action": [
		"secretsmanager:GetSecretValue"
	],
	"Resource": "*"
}

5. Lambda実行

ここまで出てきたらLambdaを実行してみます。
拡張機能にはデバッグも用意されているため確認のため使ってみます。デフォルトではOFFなのでONにしてみます。環境変数に下記を設定します。

キー
PARAMETERS_SECRETS_EXTENSION_LOG_LEVEL debug

「test」をクリックするとLambdaが実行されます。
レスポンスに設定してシークレットが含まれていれば無事取得できていると思います。

ちなみにシークレットはデフォルトで300秒間キャッシュされます。したがって、キャッシュを利用することで実行たびに取得することがないため、パフォーマンス面も考慮されていますのでうれしいですね。
デバッグをONにしているとキャッシュから取得しているか否か確認できます。
Returning secret with key /secretsmanager/get?secretId=<ARN> from cache
となっているとキャッシュから取得されています。

キャッシュの他、拡張機能の設定は下記のLambdaの環境変数を設定することで変更できます。
https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/retrieving-secrets_lambda.html#retrieving-secrets_lambda_env-var

以上になります。
これで無事、Lambdaからsecrets managerからシークレットを取得してLambdaを実行できました。

NCDCエンジニアブログ

Discussion