AWS For engineer

【AWS】AWS Control Tower の AWS Backup ベースライン「失敗」。その原因と対処方法について

AWS Control Tower で OU ごとに AWS Backup を有効化したところ、特定の OU だけ **AWS Backup ベースラインステータスが「失敗」** のまま直らない、という事象に遭遇しました。こんな感じでコンソールには「失敗」としか出ず、何が悪いのか分からない。。

動作環境

  • Control Towerのランディングゾーンのバージョンは4.0
  • Control Towerの管理対象リージョンは大阪と東京。その他のリージョンは拒否
  • Control Towerのセットアップで「AWS Backup を有効にする」を選択

とりあえずOU の再登録

AWS の公式ドキュメントでは、ステータスが Failed の場合、OU を再登録して AWS Backup の設定を OU に再適用することが基本的な対処方法とされています。そこで、TEST OU の詳細ページから「OU の再登録」を実行しましたが、状況は変わらず、ステータスは Failed のままでした。

エラーメッセージを探し出す 

Control Tower のベースライン失敗は、コンソールの表示だけでは原因が分からないので、対象 OU に有効化されているベースラインの一覧と、失敗オペレーションの ID を確認します。Control Tower のアカウントでCloudShellを起動し、以下のコマンドを実行します。

ShellScript
aws controltower list-enabled-baselines --region ap-northeast-1
~省略~
            "statusSummary": {
                "lastOperationIdentifier": "xxxxxxx-xxxx-...",
                "status": "FAILED"
            },

失敗している Backup ベースラインのエントリには 、`statusSummary.lastOperationIdentifier` が付いています。

そのlastOperationIdentifierの ID を記録し、次に以下のコマンドを実行します。

ShellScript
aws controltower get-baseline-operation \
  --operation-identifier <lastOperationIdentifier> \
  --region ap-northeast-1

すると、こんな `statusMessage` が返ってきた。

Plaintext
AWS Control Tower failed to deploy one or more stack set instances:
StackSet Id: AWSControlTowerLocalBackup:...,
Status Reason: ResourceLogicalId:LocalBackupVault,
ResourceType:AWS::Backup::BackupVault,
ResourceStatusReason:Resource handler returned message:
"Insufficient privileges to create a backup vault.
 Creating a backup vault requires backup-storage and KMS permissions.
 (Service: Backup, Status Code: 403 ...)" (HandlerErrorCode: AccessDenied).

KMS permissionsと書かれており、メンバーアカウントがローカルのバックアップボールトを作ろうとして、KMS キーへのアクセス権が足りず 403 で弾かれている。

原因を少し深堀り

Control Tower の AWS Backup 統合は、構造上こう動きます。

Plaintext
- **中央バックアップアカウント** に中央ボールトを作る

- **統治対象の全リージョン** で、**各ワークロードアカウント** にローカルバックアップボールトを作る

- それらのボールトを、指定した **マルチリージョン KMS キー** で暗号化する

そのマルチリージョン KMS キーのアクセス許可はこのようになっていました。

ShellScript
aws kms get-key-policy \
--key-id arn:aws:kms:ap-northeast-1:<管理アカウン>:key/mrk-xxxxxxxx \
  --policy-name default \
  --region <キーが保有しているリージョ> \
  --query Policy --output text
 
 ~省略~
  }, {
    "Sid" : "Enable IAM User Permissions",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "arn:aws:iam::<管理アカウント>:root"
    },
    "Action" : "kms:*",
    "Resource" : "*"
  }, {
    "Sid" : "AllowControlTowerCentralBackupUseOfKey",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "arn:aws:iam::<中央バックアップアカウント>:root"
    },
    "Action" : [ "kms:DescribeKey", "kms:GenerateDataKey", "kms:GenerateDataKeyWithoutPlaintext", "kms:Decrypt", "kms:Encrypt", "kms:ReEncrypt*" ],

マルチリージョン KMS キーは、管理アカウントと中央バックアップアカウントへの許可しか無かったため、ワークロードのメンバーアカウントは自分のローカルボールトをこのキーで暗号化できず、403 になっていました。

対処方法:キーポリシーに組織許可のステートメントを追加する

Key Management Service (KMS)>カスタマー管理型のキー>「キーポリシー」タブに移動します。

既存のステートメントは残したまま、次のステートメントを追加します。`Principal` は `*` だが、`aws:PrincipalOrgID` 条件で自組織のプリンシパルに限定されるので外部からは使えないようにしています。

JSON
{
  "Sid": "AllowControlTowerOrgAccountsUseOfKey",
  "Effect": "Allow",
  "Principal": { "AWS": "*" },
  "Action": [
    "kms:Decrypt",
    "kms:DescribeKey",
    "kms:GenerateDataKey*",
    "kms:Encrypt",
    "kms:ReEncrypt*",
    "kms:GetKeyPolicy",
    "kms:CreateGrant",
    "kms:ListGrants",
    "kms:RevokeGrant"
  ],
  "Resource": "*",
  "Condition": {
    "StringEquals": { "aws:PrincipalOrgID": "o-xxxxxxxxxx" }
  }
}

この東京(ap-northeast-1)のキーにこれを適用し、再適用したところ、**また同じ 403 が出た。**

再適用後の `statusMessage` を見ると、失敗しているのが今度は **大阪リージョン(ap-northeast-3)** のボールトでした。エラー自体は前と同じ 403 / AccessDenied。

最大の落とし穴:マルチリージョンキーはリージョンごとにポリシーが独立

マルチリージョン KMS キーは、プライマリとレプリカでキーポリシーが完全に独立している。

つまり、東京のプライマリキーにポリシーを足しても、大阪のレプリカキーには反映されない。Control Tower は統治対象の全リージョンでローカルボールトを作るので、**1 リージョンでもポリシーが欠けていると、そのリージョンだけ 403 で失敗する。**

対処は単純で、**大阪のレプリカキーにも同じポリシーを適用する。** ARN のリージョン部分を `ap-northeast-3` にして、同じ内容を当てるだけ。

ShellScript
aws kms put-key-policy \
  --key-id arn:aws:kms:ap-northeast-3:<管理アカウン>:key/mrk-xxxxxxxx \
  --policy-name default \
  --policy file://key-policy.json \
  --region ap-northeast-3 #ここを変更

統治リージョンが他にもあれば、その全部のレプリカに同じポリシーが必要になります。統治リージョンは Control Tower の「ランディングゾーン設定」で確認できます。

最終確認で以下のコマンドを実行し、「`SUCCEEDED` 以外」何も出なかったので、組織内のベースラインはすべてクリーンになりました。つまり、これが `SUCCEEDED` で完了し、FAILED の行が消えました。

ShellScript
 aws controltower list-enabled-baselines --region ap-northeast-1 \
 --query "enabledBaselines[?statusSummary.status!='SUCCEEDED'].[targetIdentifier,statusSummary.status]" --output table

まとめ:ハマらないためのチェックリスト

1. **まず実エラーを取る。** コンソールの「失敗」で止まらず、`get-baseline-operation` の `statusMessage` を確認する。これが最短ルート。

2. **403 / AccessDenied が出たら KMS キーポリシーを疑う。** Backup ボールトの暗号化キーに、組織からの利用許可(`aws:PrincipalOrgID` 条件付きで `Decrypt` / `GenerateDataKey*` / `Encrypt` / `CreateGrant` などを含む)があるか。

3. **マルチリージョンキーは全リージョンのレプリカにポリシーを適用する。** プライマリだけ直しても、レプリカが欠けているリージョンで失敗する。プライマリとレプリカでポリシーは独立している。

-AWS, For engineer
-, ,