Organizationを対象にCloudFormation StackSetsで全リージョン展開を行う時の注意点

2020.09.26

はじめに

こんにちは。大阪オフィスの林です。

CloudFormation StackSetsを使ってOrganizationUnit(以下、OUという)を対象にスタックを簡単にデプロイできる機能があるのですが、全リージョン展開の設定をStackSetsでデプロイした際に少し躓きましたので、遭遇した事象とワークアラウンドをまとめておきたいと思います。
CloudFormation StackSetsからOrganizationへのデプロイについてはこちらの記事も参照頂ければと思います。

結論

先に結論ですが、デプロイ対象のOrganizationもしくはOUに割り当てられているSCPでリージョン制限がされてないか確認しておきましょう。

遭遇した事象

それでは遭遇した事象から順を追って説明していきたいと思います。

CloudFormation StackSetsの作成を進め、デプロイ対象のOUを指定します。※CloudFormation StackSetsの作成そのものの手順は割愛します。

今回のケースでは全リージョンを対象にデプロイを行いたいので、すべてのリージョンを対象とし、CloudFormation StackSetsの作成を進めます。

CloudFormation StackSets作成が完了し、しばらく待っていると「ステータス」が「FAILED」となってしまいました。

「スタックインスタンス」タブから各スタックの詳細を確認してみると、東京リージョン(ap-northeast-1)のみスタックのデプロイに成功しており、東京リージョン(ap-northeast-1)以外はデプロイが失敗していました。

「状況の理由」からメッセージを確認すると、

User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/stacksets-exec-1b12520e766336cfc4d27bbbe7f21ca2/f31a67c6-776a-4f6a-bcfb-f3d495e06e5f is not authorized to perform: cloudformation:CreateStack on resource: arn:aws:cloudformation:ap-northeast-2:xxxxxxxxxxxx:stack/StackSet-SetupAWSConfigRules-StackSet-1f055f3b-f6d8-4f35-8925-bec9a7267ffb/* with an explicit deny

というログが残されており、not authorized with an explicit deny というキーワードが表すように、何かしら認証やそういった類でブロックされているように見受けられました。

SCPを確認

SCPを確認してみると、IAMと東京リージョンのAWS Configの操作しか許可されていないSCPがあり、そのSCPが今回のデプロイ対象としたOUに適用されていたことが分かりました。(下記はそのSCPのポリシードキュメントです)
今回AWS Configのルールを全リージョンに流し込みをするテンプレートでCloudFormation StackSetsを作成していました。AWS Configのサービス自体を操作する許可はポリシードキュメントに記述されていたものの、リージョンの条件(Condition)において、東京リージョンのみが許可となっており、東京リージョン以外が許可されていないポリシーとなっていたため東京リージョン以外のデプロイが失敗していたと考えられます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RegionRestrictions",
            "Effect": "Deny",
            "NotAction": [
                "config:*",
                "iam:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:RequestedRegion": [
                        "ap-northeast-1"
                    ]
                }
            }
        }
    ]
}

ワークアラウンド

SCPでブロックされていることが濃厚になったので、全リージョンに展開するためのワークアラウンドを検討する必要があります。今回のケースの場合、3つのワークアラウンドを検討することが出来ました。

  1. 一時的に他のリージョンも許可するSCPに変更する。
  2. CloudFormation StackSetsで使用されるIAMロールを例外許可する。
  3. 設定されているリージョンのみの展開に限定する方針に変える。

1. 一時的に他のリージョンも許可するSCPに変更する

SCPのポリシードキュメントで一時的に全リージョンを許可することでデプロイ自体は成功します。ただ、やりたいことは出来るのですが少し運用に目を向けてみると、CloudFormation StackSetsの変更や削除などCloudFormation StackSetsの操作を行う都度SCPのポリシードキュメントを変更する必要があるので、一時的な変更で凌ぐという対応はあまりスマートなワークアラウンドではなさそうです。仮に一時的に変更する場合、下記のポリシードキュメントに書き換えることで全リージョンに対してデプロイすることが可能です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RegionRestrictions",
            "Effect": "Deny",
            "NotAction": [
                "config:*",
                "iam:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:RequestedRegion": [
                        "*"
                    ]
                }
            }
        }
    ]
}

上記ポリシードキュメントに書き換えて実行すると東京リージョン以外のリージョンもCloudFormation StackSetsのデプロイが成功しました。

2. CloudFormation StackSetsで使用されるIAMロールを例外許可する

Organizationに対してのCloudFormation StackSetsではデフォルトでarn:aws:iam::xxxxxxxxxxxx:role/aws-service-role/stacksets.cloudformation.amazonaws.com/AWSServiceRoleForCloudFormationStackSetsOrgAdminというIAMロールが使用されます。このIAMロールを例外許可として扱うようなポリシードキュメントに変更することで、既存のポリシードキュメントで制限されていた東京リージョンのみという条件を例外的に扱うことができ、全リージョンに対してCloudFormation StackSetsを使ってデプロイすることが可能です。このワークアラウンドの場合は、CloudFormation StackSetsの操作を行う都度SCPのポリシードキュメントを変更する必要がないので、運用面でも前述した方法に比べスマートです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RegionRestrictions",
            "Effect": "Deny",
            "NotAction": [
                "config:*",
                "iam:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:RequestedRegion": [
                        "ap-northeast-1"
                    ]
                },
                "ArnEquals": {
                    "aws:SourceArn": "arn:aws:iam::xxxxxxxxxxxx:role/aws-service-role/stacksets.cloudformation.amazonaws.com/AWSServiceRoleForCloudFormationStackSetsOrgAdmin"
                }
            }
        }
    ]
}

上記ポリシードキュメントに書き換えて実行すると東京リージョン以外のリージョンもCloudFormation StackSetsのデプロイが成功しました。

3. 設定されているリージョンのみの展開に限定する方針に変える

そもそも何かしら理由があって許可するリージョンを絞ってるので、全リージョンを対象としたCloudFormation StackSetsのデプロイを辞めるといった方法も検討の一つかと思います。その場合、CloudFormation StackSetsの作成時に指定するリージョンで許可されているリージョンのみを指定し展開を行います。

アカウントで無効になっているリージョンにも注意

SCPでのブロックを回避してもそもそもアカウントで有効化されていないリージョンにCloudFormation StackSetsのデプロイを行っても失敗しますので、併せて確認しておくことをお勧めします。

まとめ

Organizationの環境を扱う機会があまりない場合、「SCPでコントロールされている」という視点を忘れがちになります。同じような事象に遭遇した方への参考になれば幸いです!

以上、大阪オフィスの林がお送りしました!