【AWS】lambdaでKMSを用いて環境変数の暗号化・復号化【Python】


概要

lambda使っててAPIを叩きたい時にシークレットキーなどの情報を環境変数に平文で置きたくないですよね.
その時に用いるサービスがKMS(Key Management Service)です.

この記事ではKMSを用いてlambda_functionの中で使用する環境変数の暗号化からプログラム中で復号化するところまでご紹介します(私自身AWS初心者で嵌ってしまったポイントがあるので記事にしました).

lambdaで使用する言語はPythonで,コンソール上で操作を行います.

流れ

ざっくりした流れは以下のようになります.

  1. KMSのカスタマー管理型キーの作成
  2. 対象のLambda関数に KMS:Decrypt 権限を与える
  3. 環境変数の作成・暗号化
  4. 関数上で暗号化された環境変数の復号化

1. KMSのカスタマー管理型キーの作成

KMSの管理コンソールへ行き,キーの作成を行います.
キーのタイプの選択がありますが,対称でいいと思います.

今回は「user/kms-test」というエイリアスをつけました.
説明やタグは適当に設定しましょう.

次のキーの管理アクセス許可の定義キーの使用アクセス許可の定義は各々の設定に合わせます.
ここでlambda関数にのみ権限を与えるのが本来いいとは思います(が面倒なので私はAdminに設定しました).
たとえばこちらの記事ではこの時点でlambda関数にロールを設定しています.

2. 対象のLambda関数に KMS:Decrypt 権限を与える

まず実行ロールの設定します.IAMコンソールのこちらのページにアクセスしてポリシーの作成を行います.

下の図のように設定を行います.サービスにKMS,アクションにDecypt,リソースに先程作成したKMSのカスタマー管理キーのARNを記述します.

名前はlambda-kms-decrypt-policyとしました.

次にlambda関数に今作成したポリシーをアタッチします.
こちらのページにアクセスして対象のlambda関数のロールを選択します.するとポリシーをアタッチしますというボタンがあると思うのでクリックしてください.そこで先程作成したポリシーを選択します.

3. 環境変数の作成・暗号化

続いてlambdaでの作業になります.コンソールのlambdaのページから対象の関数のところに行きます.
設定→環境変数で環境変数の作成をクリックします.

今回はTEST_ENCRYPTという環境変数を試しに作ってみます.
暗号化の設定のところで転送時の暗号化に使用するヘルパーの有効化にチェックを入れると暗号化できるようになります.

そこで先程作成したKMSキーを選択します.すると下の図のように値が暗号化されました.

これで環境変数の設定は以上です.

4. 関数上で暗号化された環境変数の復号化

lambda_functionの例を示します.
以下のコードをテストするとログに暗号化された文字列と復号化された文字列が表示されるはずです.

lambda_function.py
import json

import boto3,os
from base64 import b64decode

def lambda_handler(event, context):

    ENCRYPTED = os.environ['TEST_ENCRYPT']
    print(ENCRYPTED)
    DECRYPTED = boto3.client('kms').decrypt(CiphertextBlob=b64decode(ENCRYPTED),EncryptionContext={'LambdaFunctionName': os.environ['AWS_LAMBDA_FUNCTION_NAME']})['Plaintext'].decode('utf-8')
    print(DECRYPTED)

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

最後に

私もAWS初心者のためこれで正しいのか正直わかりません.有識者の方,助言などぜひよろしくお願いします.
あと,転送時の暗号化に使用するヘルパーの有効化についてですが,こちらはCDKからは操作できないのでしょうか?コンソール上だけからの設定だと面倒くさいなと思いました...

参考

https://dev.classmethod.jp/articles/decrypt-sensitive-data-with-kms-on-lambda-invocation/
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-intro-execution-role.html#permissions-executionrole-console
https://aws.amazon.com/jp/premiumsupport/knowledge-center/kms-invalidciphertextexception/