構成
以下の構成により、Control TowerマスターアカウントでStackSetsを展開します。
※アカウント自体はControl Towerのアカウント登録により作成します。
アカウント払い出し時に、管理者がアカウントに予算を作成した上で使用者にアカウントを渡すことを想定しています。
使用者ごとに予算額、通知先が異なるためStackSetsで一気に展開することは不可能なので、StackSetsを後から更新して対応します。
流れとしては、まず、ターゲットをOU(組織単位)としてStackSetsを作成し、自動デプロイ機能を有効化します。
そして、Control Towerのアカウント登録機能を使用してアカウントを作成(このときOUも指定する仕様になっています)。
そうすると、アカウント作成完了時にはそのアカウントにはBudgetsも作成されていることに。
しかし、これだとStackSets作成時のパラメータ設定通りの予算額と通知先になってしまい、各アカウントでカスタマイズできていないので、パラメータの上書きで対応します。
注意点として、StackSets作成時に入力したメールアドレス宛にSNSトピックのサブスクリプション確認メールが届くので、その確認を行ってからパラメーターの上書きを行うこと(そうしないと上書きを行っても保留中のサブスクリプションが置換されず残ったままになります。)。
この構想だと最初に指定したメールアドレスにアカウント作成のたびに確認メールが届くことになりますが、他の方法が思いつかなかったためその点は許容します。
なお、最初のメールアドレスを自分で確認できないメールアドレスにしてしまうと作業が進まないので、アカウント作成担当者のメールアドレスに設定します。
※セルフサービス型バージョンの記事もあります。
AWSのControl Towerマスターアカウントからセルフマネージド型StackSetsを展開してみた
StackSets作成
Control TowerマスターアカウントのCloudFormationのStackSets画面に移り、StackSetの作成
をクリック。
準備していたテンプレートをアップロードします。
テンプレートは記事の最後に掲載。
StackSetの名前や、パラメータを入力します。
予算額とメールアドレレスはともに変更予定なので適当なものでも構いませんが、メールアドレスはサブスクリプションの確認メールのリンクをクリックする必要があるので、自分が使用できる実在するメールアドレスを入力します。
タグはなくても構いませんが、アクセス許可はサービスマネージドアクセス許可
を選択します。
理由としては二つです。
① StackSet展開用のIAMロールを自分で作成する必要がない
セルフサービスのアクセス許可
だと、管理アカウントとターゲットアカウントの両方でIAMロールを手動で作成する必要があります。
② 自動デプロイが使用できる
自動デプロイを有効化すると、指定したOUに追加・削除されると自動でStackSetが展開・削除されます。
デプロイターゲットのOUを入力します(以下の写真のように、あらかじめ確認しておきます。)。
写真では自動デプロイが無効になっていますが、有効にします。
有効を選択すると、スタックインスタンスを削除する時に実際のリソースを残すかどうか選択できます。
リソースを残す設定にすると、スタックインスタンスを削除しても実際のリソースは残り、StackSetsの管理下から外れるという結果になります。
AWS OrganizationsでOUのIDを確認できます。
最後は今まで設定した事項を確認して作成するだけです。
作成を開始した様子です。
作成中です。
2分ほどで作成が完了しました。
そのときの写真をとり忘れましたが、エラーのときは状況の理由
欄に理由が記載されます。
各アカウントにBudgetsとSNSトピックが作成されましたが、各アカウントの予算額等はパラメーターで入力した一律の値です。
各アカウント用にカスタマイズするために、アクション
,StackSetのパラメータを上書き
をクリックします。
OU単位へのデプロイ
とアカウントへのデプロイ
がありますが、個別にカスタマイズしたいのでアカウントへのデプロイ
を選択します。
アカウント番号を入力するのであらかじめ調べておきます。
リージョンは既に展開済みのリージョンを選択します(展開したリージョンしか選べないようになっていると思います。)。
上書きするパラメータを選択して、上書き値の編集
から該当のアクションを選択して入力します。
設定した項目を確認したら完了です。
これで指定したアカウントへカスタマイズされたBudgetsとSNSが作成されました。
あとはアカウントの数だけ繰り返します。
最初のStackSetsの展開さえ行えば、ターゲットのOUにアカウントが追加されたら自動デプロイされます。
そのたびにパラメータの上書きが必要ですが、各アカウントにサインインして手動でポチポチするよりかは早く設定できると思います。
テンプレート
Description: "Basic Budget"
Parameters:
Amount:
Type: String
Default: 100
Description: Budgeted amount
email1:
Type: String
Description: Notification email1 address
email2:
Type: String
Description: Notification email2 address
Resources:
Budget:
Type: AWS::Budgets::Budget
Properties:
Budget:
BudgetName: test1
BudgetLimit:
Amount: !Ref Amount
Unit: USD
TimeUnit: MONTHLY
BudgetType: COST
NotificationsWithSubscribers:
- Notification:
NotificationType: FORECASTED
ComparisonOperator: GREATER_THAN
Threshold: 50
ThresholdType: PERCENTAGE
Subscribers:
- Address: !Ref SNS1
SubscriptionType: SNS
- Notification:
NotificationType: FORECASTED
ComparisonOperator: GREATER_THAN
Threshold: 70
ThresholdType: PERCENTAGE
Subscribers:
- Address: !Ref SNS1
SubscriptionType: SNS
- Notification:
NotificationType: FORECASTED
ComparisonOperator: GREATER_THAN
Threshold: 100
ThresholdType: PERCENTAGE
Subscribers:
- Address: !Ref SNS2
SubscriptionType: SNS
SNS1:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: !Ref email1
Protocol: email
TopicName: StackSetsBudgets1
SNS2:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: !Ref email1
Protocol: email
- Endpoint: !Ref email2
Protocol: email
TopicName: StackSetsBudgets2
SNSPolicy1:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Id: MyTopicPolicy
Version: '2012-10-17'
Statement:
- Sid: My-statement-id
Effect: Allow
Principal:
Service: budgets.amazonaws.com
Action: SNS:Publish
Resource: !Ref SNS1
Topics:
- !Ref SNS1
SNSPolicy2:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Id: MyTopicPolicy
Version: '2012-10-17'
Statement:
- Sid: My-statement-id
Effect: Allow
Principal:
Service: budgets.amazonaws.com
Action: SNS:Publish
Resource: !Ref SNS2
Topics:
- !Ref SNS2
個人的なメモ(ここからは蛇足です)
検証時にへーと思ったことを書いていきます。
スタックインスタンスが認識しているOUと実際のOUが異なる場合がある
このように、StackSetでターゲットとなっているOUにいるアカウントが、別のOUに移動したときのスタックインスタンスの更新や削除時の挙動について調べてみました。
ちなみに自動デプロイ機能を使わないでStackSetsを展開したらどうなるか検証していた時に発見したものです。
とりあえずStacksetにドリフト検出をしてみました。
私の予想ではリソースが変更していないとはいえ、OUが変更されているからドリフト検出されると思っていたのですが、予想に反してドリフト検出されませんでした。
そこで、どのような挙動になるか確認するために更新や削除を行ってみます。
まず、StackSetにA OU
を指定して更新してみます。B OU
所属のBアカウントも更新されました。
次に、B OU
を指定して削除してみます。スタックインスタンスにB OU
が見つかりませんとエラーが出ます。
よって、Bアカウントは実際はB OU
に所属しているが、スタックインスタンスではBアカウントはA OU
として認識されていそうなことがわかりました。
とても紛らわしいので、自動デプロイ機能を使わない場合でアカウントの所属OUを変更するときは、その前に該当のスタックインスタンスのみを削除したいですが、サービスマネージドアクセス許可でStackSetを作成していると、OU単位でしか削除できません。
サービスマネージドアクセス許可のStackSetは、自動デプロイを有効化した方がよさそうです。
パラメータの上書きアクションでスタックインスタンス以外のアカウントは追加できない
スタックインスタンスの追加アクションではアカウント単位の追加ができないので、パラメータの上書きアクションでスタックインスタンスを作成していないアカウントを指定してデプロイしようとしました。
結果は見出しのとおり追加できませんでした。
スタックインスタンスが見つかりませんと出ました。
デプロイ対象のアカウントやOUを選択できるので、スタックインスタンスにない新たなアカウントを追加できるのではないかと思い試してみましたが、無理なようです。
StackSetの詳細を編集するからでも同様のエラーが発生してできませんでした。
サービスマネージド型ではOU単位でしかスタックインスタンスの追加・削除ができないようです。