KMSキーのキーポリシーに特定のプリンシパル以外の操作を拒否するステートメントを記載する場合の注意点

記事タイトルとURLをコピーする

こんにちは。テクニカルサポート課の森本です。

お客様からのお問い合わせをいただく中で、DynamoDB テーブルのバックアップを AWS Backup にて取得する際に KMS キーエラーが発生したとのお問い合わせをいただきましたのでその顛末を紹介いたします。

[前提]Backupの環境

  • DynamoDBテーブルはデフォルト(AWS所有のキー)で暗号化
  • AWS Backupのバックアップ実行ロールはデフォルトのロール (AWSBackupDefaultServiceRole)
  • AWS BackupのバックアップボールトはKMSのカスタマーマネージドキーで暗号化

エラーメッセージ

失敗したバックアップジョブには以下のような塩対応のエラーメッセージが表示されていました。

KMS key is either disabled or pending deletion or access to KMS key is denied

被疑箇所

バックアップボールトを暗号化しているKMSキーのキーポリシーを確認したところ、特定のユーザ/ロール以外のアクションを拒否(Deny)するステートメントが存在しておりました。 一旦デフォルトのキーポリシーに当該ステートメントを追加して検証を行ったところ同様のエラーが発生したため、被疑箇所はこちらと考えられました。

{
    "Sid": "Deny actions except Administrator",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "kms:*",
    "Resource": "*",
    "Condition": {
        "StringNotEquals": {
            "aws:PrincipalArn": [
                "arn:aws:iam::000000000000:user/xxx"
            ]
        }
    }
}

対応その1

AWS Backupのバックアップ実行ロールが当該キーポリシーにより拒否されているように見受けられたため、Condition句に当該IAMロールを追記しました。しかし、結果としては依然としてエラーが出続けることとなりました。この時点でKMSキーへのアクセスはAWSの内部的なロールが行っておりそれが拒否されている可能性が見受けられたので、AWS サポートに仕様の確認を行いました。

{
    "Sid": "Deny actions except Administrator",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "kms:*",
    "Resource": "*",
    "Condition": {
        "StringNotEquals": {
            "aws:PrincipalArn": [
                "arn:aws:iam::000000000000:user/xxx",
                "arn:aws:iam::000000000000:role/backup-role"  <- 追加
            ]
        }
    }
}

対応その2

AWS サポートからの回答によると、DynamoDBのバックアップ成功時は、Decrypt APIが実行されており、その際は userIdentity の type が AWSServiceによって実行されているとご確認いただきました。

(CloudTrailのDecrypt API実行履歴より抜粋)
"userIdentity": {
        "type": "AWSService",
        "invokedBy": "backup-storage.amazonaws.com"
    },

AWSService – リクエストは AWS のサービス に属している AWS アカウント によって行われました。例えば、AWS Elastic Beanstalk は、アカウントで IAM ロールを引き受けて、ユーザーに代わって他の AWS のサービス を呼び出すようにします。

CloudTrail userIdentity 要素 - AWS CloudTrail

そのため、Condition句にAWSサービスからの呼び出しを拒否しないような内容を追加し、当該ステートメントを維持しながらバックアップが取得できると助言いただきました。また、バックアップの実行ロールはこちらのステートメントには必要がないことを確認しました。

{
    "Sid": "Deny actions except Administrator",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "kms:*",
    "Resource": "*",
    "Condition": {
        "StringNotEquals": {
            "aws:PrincipalArn": [
                "arn:aws:iam::000000000000:user/xxx"
            ]
        },
        "BoolIfExists": {
           "aws:PrincipalIsAWSService": "false" <- 追加
       }
    }
}

AWS グローバル条件コンテキストキー - AWS Identity and Access Management aws:PrincipalIsAWSService

まとめ

通常のIAMポリシーに権限が足りない等のエラーメッセージが出力される場合は、コマンド実行時や CloudTrailのイベント履歴に以下のようなエラーメッセージが出力されるため、変更 が必要なポリシーも比較的わかりやすいかと思います。

User: arn:aws:iam::0000000000000:user/xxx@example.com is not authorized to perform: iam:xxx on resource: xxx with an explicit deny in an identity-based policy

今回のようにエラーメッセージの内容が曖昧な場合のトラブルシュートは地道な切り分けが必要ですが、当初は失敗時のAPI実行履歴に着目しており成功時のAPI実行履歴に着目できておらず問題解決に時間を要してしまい、結果的にお客様をお待たせしてしまいました。 今後、失敗時のイベントだけでなく成功時にどのような動作が期待されるかの比較も含めてトラブルシュートを行なっていきたいと自戒を込めてのエントリとさせていただきます。

この記事がどなたかの参考になれば幸いです。

森本 晃大(執筆記事の一覧)

テクニカルサポート課

2023年10月入社。絶賛仕事と子育てに奔走中です。