実は結構色々な選択肢があるのですが、今回は一番シンプルな方法を説明します。
AWS CDKでLambdaで環境変数を扱う場合、ハードコードできないものはSecrets ManagerとParameter Storeを使う。
Parameter Storeで通常の情報を管理し、Secrets Managerで秘匿情報を管理する。
AWS CDKからCloudFormationに対して、クラウド内でSecrets ManagerやParameter Storeを参照するように指示する。
create parameter
ボタンから、パラメータを作成する(スクリーンショット2)
const someHandler = new lambda.Function(this, 'someHandler', {
runtime: lambda.Runtime.NODEJS_16_X,
code: lambda.Code.fromAsset('../backend/dist/handler'),
environment: {
SOME_ENV_VAR: 'hard-coded',
ENVIRONMENT:
// Parameter Store
ssm.StringParameter.fromStringParameterAttributes(this, 'SomeHandlerParam1', {
parameterName: 'someApp/backend/ENVIRONMENT'
}).stringValue,
SOME_CREDENTIAL:
// Secrets Manager
secretsmanager.Secret.fromSecretNameV2(this, 'SomeHandlerParam2', 'someApp/backend/credentials')
.secretValue.toString()
},
handler: 'handler.handler',
memorySize: 1024
})
※動作するプロダクションコードを上記スクリーンショットに合わせて手直ししております。もしスクリーンショットとの矛盾に気づかれましたら、ご指摘ください。
CDKを実行しているマシン上で、実際のSecrets ManagerやParameter Store上の値を取得しようとすることは望ましくない。
このようにしてLambdaに環境変数を設定すると、CloudFormationテンプレート上に値が出てしまい、CloudFormationを参照できるIAMはそうした値を知ることができてしまい、セキュリティリスクにつながる。(公式より)
この記事で説明しているコードは、望ましい設計となっている。先述のアーキテクチャ図にあるとおり、CloudFormationの動的参照機能を活用しており、ローカルマシン上で値を取得しないためである。
secretsmanager.Secret.fromSecretNameV2(this, 'SomeHandlerParam2', 'someApp/backend/credentials')
.secretValueFromJson('someKey').toString()
Parameter StoreやSecrets Manager上で環境変数を変更しても、Lambdaに反映されるわけではない点は注意が必要である。 少々手間だが、以下2点の方法で環境変数を変更可能である。
cdk deploy
は生成されたCloudFormationテンプレートに差分が違いがないとデプロイされないことに注意。-f
オプションをつけることで強制的にデプロイが可能。設定値の取り扱いとして、望ましくないパターンが次の2パターンである。
1.は自明として、2.のパターンについて解説する。
AWS CDKでLambdaをデプロイしたときの挙動は、環境変数は全て削除され、設定し直されるイメージになる。
つまり、
だけでなく、
ということである。
したがって、ハードコードできない環境変数は、全てParameter StoreやSecrets Managerに保存し、CloudFormationの動的参照でデプロイ時にLambdaに設定する必要がある。
Secrets Managerのシークレットは、AWS上で暗号化されてストレージに保存される。
AWS CDKはParameter Storeの暗号化機能に対応していないため、秘匿情報はSecrets Managerに保存する必要がある。(2022年7月時点)
Parameter StoreにもSecureStringという機能があり、値を暗号化してAWS上に保存することができる。
しかし、CloudFormationは、Lambdaの環境変数としてParameter StoreのSecureStringを動的参照指定できない。(ごく僅かなサービスしか対応していない)
したがって、AWS CDKでLambdaの環境変数に設定したい秘匿情報を保存するためには、Parameter Storeを利用することができない。
AWS CDKを使うにあたって、Parameter StoreとSecrets Managerのセキュリティに関する違いは、AWSのストレージ上に値が暗号化された状態で保存されるかどうかである。
この記事では、ストレージ上に暗号化されるべき値を秘匿情報と表現している。
AWSのストレージ上に値が暗号化されずに保存される状況が「セキュアでない」かどうかは、組織のポリシーの依るところが大きいと考える。
例えばクレデンシャルなどの情報も暗号化されて保存される必要がなければ、全てParamter Storeに保存しても問題ない。
認証周りが億劫で、LambdaにデプロイしているWebアプリにFirebase Authenticationを導入しました。(フロントエンドNuxt3 SSR on Lambda、バックエンドExpress on Lambda)
バックエンドでアクセストークンをverifyするために、Firebaseサービスアカウントのキーを環境変数に設定しようとしたところ、デプロイのたびにバックエンドが壊れて困ったので、この記事を書きました。
今までDynamoDBのテーブルや、CORS設定のためのフロントエンドのドメインなど、AWS CDK上で解決できる値が多かったので、初めて困ったかもしれません。
調べているうちにLambdaに環境変数を動的に設定する様々な方法と、そのメリデメに詳しくなってしまったので、(ニッチですが)どこかで記事にするかもしれません。