AWS のマルチアカウント管理として Control Tower を導入し、ランディングゾーン設定で特定リージョンのみ利用可能にしていたケースで、許可リージョンを新たに追加しようとしたところエラーとなってしまい、何度再試行しても回復しないトラブルにハマってしまいました。少し限定的な条件下でしか発生しないとは思いますが、対処方法を記録しておきたいと思います。

背景

昨今の生成 AI 需要も高まり Bedrock ではリージョンを跨いで推論できる、クロスリージョン推論がサポートされました。一方 Control Tower でマルチアカウントを管理し、リージョン拒否コントロールを利用している場合、拒否しているリージョンによってはクロスリージョン推論に失敗してしまいます。

Denied Cross Region Inference

このようなケースに対応するため、AWS では Bedrock のクロスリージョン推論だけを許可しつつ、他のサービスについては拒否する方法をブログでガイドしています。

ブログでガイドされている通り、はじめにランディングゾーンで設定するリージョン拒否コントロールから 1つのリージョン (今回はオハイオ (us-east-2)) を使えるように設定しようとしたところ、以下のような AWS Config の Delivery Channel がこれ以上作成できないという旨のエラーが出てしまいました。

Landing Zone update error

「再試行」とあるので何度かリトライしてみたのですが、うまくいく兆しは全くありません (そして毎度時間がかかる…)

しかも、Control Tower のコンソールからはもう「再試行」することしかできず、手詰まり感があります🥵

エラーの詳細

エラーが見にくいので少し整形すると以下のようになります。

AWS Control Tower failed to deploy one or more stack set instances:
* StackSet Id: AWSControlTowerBP-BASELINE-CONFIG:xxxxx,
* Stack instance Id: arn:aws:cloudformation:us-east-2:123456789012:stack/StackSet-AWSControlTowerBP-BASELINE-CONFIG-xxxxx/xxxxx,
* Status: OUTDATED,
* Status Reason: ResourceLogicalId:ConfigDeliveryChannel,
* ResourceType:AWS::Config::DeliveryChannel,
* ResourceStatusReason:Failed to put delivery channel 'aws-controltower-BaselineConfigDeliveryChannel'
  because the maximum number of delivery channels: 1 is reached.
  (Service: AmazonConfig; Status Code: 400; Error Code: MaxNumberOfDeliveryChannelsExceededException; Request ID: xxxxx;

今回、許可リージョンとして追加しようとしたオハイオリージョン (us-east-2) で、AWS Config の Delivery Channel を追加しようとしたが、これ以上追加できないというエラーのようです。

エラーダイアログの「詳細はこちら」を辿ると Control Tower のトラブルシューティングにリンクされています。このページ冒頭のトピックの中に AWS Config に関するエラーについての記述がありました。

一般的な原因: AWS アカウントで AWS Config サービスを有効にすると、デフォルトの命名で設定レコーダーと配信チャネルが作成されます。コンソールを使用して AWS Config サービスを無効にしても、設定レコーダーや配信チャネルは削除されません。これらは CLI を使用して削除するか、AWS Control Tower で使用できるように変更する必要があります。AWS Control Tower でサポートされているいずれかのリージョンで AWS Config サービスが有効になっている場合、このエラーが発生する可能性があります。

表示されたエラーメッセージはドキュメントに記載のあるエラーメッセージとは少々異なりますが、原因としては該当していそうです。

なぜ、拒否リージョンで AWS Config が構成されていた?

拒否されていたリージョンでなぜ AWS Config が構成されていたか? 真因を先にお伝えすると、ずいぶん前に AWS Organizations を構成したその後、Control Tower でリージョン拒否コントールを使用する前に、AWS Systems Manager の「Quick Setup」を使用して AWS Config の設定レコーダーを全て (あるいは複数) のリージョンで有効したことで設定が残ってしまっていたのが原因でした。

リージョン拒否コントロールを設定する前に、適用するリージョンにリソースがないことを確認するようドキュメントにも書いてはあるのですが、配信チャネル、設定レコーダーがリソースという認識がなく見落としてしまった感です 🙈

AWS Organizations を割と早くから導入し、Control Tower を後から導入されたケースで遭遇しやすそうなエラーかと思います。

対処

ドキュメントには AWS CLI で配信チャネルや設定レコーダーを削除するよう、コマンドの例を添えて書かれていますが、当該のリージョンは Control Tower のランディングゾーンでまだ拒否リージョンとしての扱いなので、AdministratorAccess ポリシーをもってしても変更することができません。

そこで AWS Organizations の管理アカウントから、メンバーアカウントに作成済みの AWSControlTowerExecution という特別なロールにスイッチして操作します。ちなみにこのロールはリージョン拒否コントロールのポリシー (SCP) では例外プリンシパルとして設定されています。

{
  // ...(snip)...
  "ArnNotLike": {
    "aws:PrincipalARN": [ "arn:aws:iam::*:role/AWSControlTowerExecution" ]
  },
  // ...(snip)...
}

まず、Organizations の管理アカウントからエラーのあったアカウントの AWSControlTowerExecution へ AssumeRole します。

# 端末によってはあらかじめ AWS_PAGER="" を設定しておくと、SessionToken が途切れずに出力できるかもしれません
# export AWS_PAGER=""

aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/AWSControlTowerExecution
  --role-session-name forEnableRegion

# 各値を環境変数に設定
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...

# リージョン指定を忘れた時に備えて、念のため対象リージョンを設定しておきます
export AWS_DEFAULT_REGION=us-east-2

# 念のため正しく設定できているか、何者として作業するか確認しましょう
aws sts get-caller-identity

これでエラーのあったアカウントで、拒否されているリージョンでも操作が可能になります。

濫用してよいロールではないことは言わずもがなです。リージョンの指定ミスなど無いよう細心の注意を払ってください!

ここからはドキュメントに沿って確認していきます。

1. 配信チャネルの確認

aws configservice describe-delivery-channels --region us-east-2
{
  "DeliveryChannels": [
    {
      "name": "aws-quick-setup-delivery-channel",
      "s3BucketName": "aws-quick-setup-config-recording-XXXXX",
      // ...(snip)...
    }
  ]
}

配信チャネル名 (DeliveryChannels[].name) を控えておきます。今回の私の環境では aws-quick-setup-delivery-channel という名前でした。前述のとおり、Systems Manager の Quick Setup で構成した際の設定が残っていたようです。

2. 設定レコーダーの確認

aws configservice describe-configuration-recorders --region us-east-2
{
  "ConfigurationRecorders": [
    {
      "arn": "arn:aws:config:us-west-1:222222222222:configuration-recorder/default/xxxxx",
      "name": "default",
      "roleARN": "arn:aws:iam::222222222222:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig",
      // ...(snip)...
    }
  ]
}

設定レコーダー名 (ConfigurationRecorders[].name) を控えておきます。ドキュメントにある通り default で設定されていました。
なお、メンバーアカウントによっては設定レコーダーがない ([]) こともあるかもしれません。

3. 設定レコーダーの停止

設定レコーダーと配信チャネルを削除していきます。まず、設定レコーダーを停止します。設定レコーダーがなかった場合は不要です。

aws configservice stop-configuration-recorder \
  --configuration-recorder-name ${CONFIGURATION_RECORDER_NAME} \
  --region us-east-2

4. 配信チャネルの削除

続いて配信チャネルを削除します

aws configservice delete-delivery-channel \
  --delivery-channel-name ${DELIVERY_CHANNEL_NAME} \
  --region us-east-2

5. 設定レコーダーの削除

そして設定レコーダーを削除します。設定レコーダーがなかった場合は不要です。

aws configservice delete-configuration-recorder \
  --configuration-recorder-name ${CONFIGURATION_RECORDER_NAME} \
  --region us-east-2

6. 管理対象アカウントについて 1~5 を繰り返し

以上の 1 - 5 の手順を Control Tower の管理対象アカウントに AssumeRole しながら実施していきます。

私の環境では、Control Tower のセットアップ時に作成する「監査アカウント」と「ログアカウント」で、配信チャネル、設定レコーダーの削除が必要でした。

7. ランディングゾーン設定の再試行

Control Tower のコンソールに戻り、「再試行」を実行します。Organizations 管理対象アカウントで許可しようとしているリージョンの AWS Config の配信チャネルと設定レコーダーが削除されていれば今回のエラーは出なくなるはずです。

(おまけ) Bedrock クロスリージョン推論以外を拒否するには

Control Tower ランディングゾーンで許可リージョンを追加できたことで、クロスリージョン推論が利用可能になりましたが、他の AWS サービスについては引き続き拒否したいケースもあるでしょう。

前述のブログではいくつか方法が紹介されていますが、今回は “オプション2: AWS Control Tower を使用して拒否されたリージョンを有効にし、SCP を使用して条件付きでブロックする” が要件的にはマッチしましたので設定してみました。

今回の例をおさらいしますと、元々 us-east-1 (バージニア北部)、us-west-2 (オレゴン) が利用できる状況下で us-east-2 (オハイオ) を許可リージョンとして追加しました。なので “オハイオの Bedrock クロスリージョン推論以外の AWS サービス呼び出しを拒否する” ようにしたいと思います。

AWS Organizations の “ポリシー” から “サービスコントロールポリシー” を選択し、以下のようにポリシーを作成します。
us-east-2 リージョンで ARN が Bedrock Inference Profile 以外だったら拒否、というアンバイです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-east-2"
        },
        "ArnNotLike": {
          "bedrock:InferenceProfileArn": "arn:aws:bedrock:*:*:inference-profile/*"
        }
      }
    }
  ]
}

このポリシーを対象の OU やアカウントにアタッチにすれば OK です。

まとめ

Control Tower でランディングゾーンの許可リージョンを追加する際に出た、AWS Config の Delivery Channel 作成エラーについて対処した方法を紹介しました。発生条件は、Control Tower のリージョン拒否コントロールを利用するより以前に、Systems Manager の Quick Setup で AWS Config の設定レコーダーをマルチリージョンに展開し、配信チャネルなどを削除せずにリージョン拒否コントロールを利用開始したケースでリージョンの追加をすると発生するという、限定的な条件で発生しました。すでにリージョンを拒否している都合上、通常の方法ではアクセスできないため、AWSControlTowerExecution というロールを使ったのがポイントになります。同じエラーでハマった方の助けになれば幸いです。

AWSControlTowerExecution ロールは非常に強力なロールで、操作を誤ると Control Tower のガードレールを無視して環境の変更などができてしまいます。利用する場合は細心の注意を払って利用するようにしてください。

最後に・・・

この投稿は個人的なものであり、所属組織を代表するものではありません。ご了承ください。