Terraformで構築したAWS LambdaがAWS KMSキーポリシーでエラーとなった話
はじめに
本記事ではAurora S3エクスポートをLambda経由で実行するシステムを、Terraformで構築した時に詰まった話をご紹介します。
状況
構築したシステムの概要図は上記の通りです。
1. Auroraがスナップショット作成完了イベントを発砲する。
2. EventBridgeが1のイベントをキャッチし、Step Functionsを実行する。
3. Step Functionsの中のLambdaが実行される。
4. Lambda経由でAuroraスナップショットをS3にエクスポートする。
上記概要図のシステムをコンソールより構築した時は想定通りの動作結果を得られました。
しかし、Terraformにて同じものを再現し、実行したところ下記のエラーが発生しました。
{ "errorMessage": "An error occurred (KMSKeyNotAccessibleFault) when calling the StartExportTask operation: The specified KMS key [arn:aws:kms:ap-northeast-1:*********:key/************] does not exist, is not enabled or you do not have permissions to access it.", "errorType": "KMSKeyNotAccessibleFault", "requestId": "fbaadd00-98b8-4fa9-9f16-a1515b603d02", "stackTrace": [.....
エラーの原因としてはAuroraのStartExportTaskを実行するIAMロールに対してKMSのキーポリシーの権限が足りていなかったことです。
コンソールからキーポリシーを設定した時と同様にキーポリシーを設定していたので、どこで不備があったのかわかりませんでした。
エラーを解決するために順に行ったことを説明します。
試したこと
①S3 Exportを実行するロールに対してKMSの権限を付与した
KMSKeyNotAccessibleFaultとあったためKMSを利用する権限がS3エクスポートを実行するロールに対して付与されていないことを推測しました。
LambdaはRDSのstart_export_taskをPassRoleによって実行する実装としていました。
KMSのキーポリシーにはLambdaを実行するロールに対しては権限を付与していたものの、PassRoleで引き受けるロールに対しては許可していませんでした。
そのため、PassRoleで引き受けるロールに対して同じキーポリシーを追加しました。
追加した権限は以下の5つです。
"kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:Encrypt", "kms:DescribeKey", "kms:Decrypt"
こちらの対応を実施してもエラーは解消されませんでした。
Boto3 1.34.26 documentation – RDS / Client / start_export_task
②KMSのポリシーを確認した
次に既存で実行できている環境とKMSの差分を確認しました。
KMSのキーポリシーを確認したところ内容が異なっていることを確認しました。
上記で許可したKMSキーポリシーに加えて以下の3つの権限が追加されていました。
"kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant"
マネジメントコンソールでキーユーザーに設定した際には上記3つと①の権限を合わせて、8つの権限が割り当てられます。
今回Terraformに書き起こす際、AWS公式が提供しているkms moduleを使いましたが、そのオプションの中でkey_usersというものがあったため同様のものと想定して書いていました。
kms moduleのGitHubを確認したところ上記3つの権限は追加されず構築されてしまうことが確認できました。
kmsモジュールを使用したTerraformは以下の通り記載し実行していました。
module "kms" { source = "terraform-aws-modules/kms/aws" description = "use for Aurora S3 export." key_usage = "ENCRYPT_DECRYPT" # Policy key_users = [aws_iam_role.storage_transfer_role.arn, aws_iam_role.lambda_export_role.arn] # Aliases aliases = ["${var.project_name}-${var.env}-key"] }
3つの権限を追加できるように以下のようにTerraformを修正しました。
修正後、実行を試したところ、無事にS3エクスポートが実行開始されました。
PassRoleで引き受ける際には元のIAMロールからCreateGrantでKMS権限を付与する必要がありますが、そのための権限がkms moduleを使って構築するとアタッチされないようでした。
resource "aws_kms_key" "s3export" { description = "use for Aurora S3 export." key_usage = "ENCRYPT_DECRYPT" } resource "aws_kms_key_policy" "user" { key_id = aws_kms_key.s3export.id policy = data.aws_iam_policy_document.kms.json } data "aws_iam_policy_document" "kms" { statement { sid = "Enable IAM User Permissions" effect = "Allow" principals { type = "AWS" identifiers = ["arn:aws:iam::${var.project_number}:root"] } actions = ["kms:*"] resources = ["*"] } statement { sid = "Allow use of the key" effect = "Allow" principals { type = "AWS" identifiers = [aws_iam_role.storage_transfer_role.arn, aws_iam_role.lambda_export_role.arn] } actions = ["kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey"] resources = ["*"] } statement { sid = "Allow attachment of persistent resources" effect = "Allow" principals { type = "AWS" identifiers = [aws_iam_role.storage_transfer_role.arn, aws_iam_role.lambda_export_role.arn] } actions = ["kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant"] resources = ["*"] condition { test = "Bool" variable = "kms:GrantIsForAWSResource" values = [true] } } }
まとめ
Terraformによって構築したKMSキーポリシーのトラブルシューティングについて紹介しました。
公式のモジュールでもコンソール経由の構築と異なるものを構築している場合があるので、構築後に正常に動作した環境との差分確認やGitHubのモジュールのコード確認などを行いましょう。
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitter2022年4月、NHNテコラスに新卒入社。大学時代は山に登ったり、インドに行ったりしてました。
Recommends
こちらもおすすめ
-
AWS Lambdaとは?初心者向けにサービス内容やメリットを解説
2019.5.16
-
SCS受験前に押さえたい!AWS KMS初心者向けハンズオン
2022.5.12
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16