Control Towerから展開されたCloudFormationのStackSetsテンプレートをぶっこ抜くスクリプト書いた

AWS Control Towerで利用されているCloudFormation StackSetsのテンプレートをPythonスクリプトで抽出してみました。ぜひご活用ください。
2019.11.25

こんにちは、臼田です。

皆さん、Pythonしてますか?(挨拶

AWS Control Towerはマルチアカウントで統制を利かせるサイコーなサービスですが、AWS Organizationsと連携して利用する必要があります。しかし、内部の原理的にはOrganizationsを利用しなくても真似することができる部分が多く、例えばCloudFormationのStackSets機能を利用して展開しているテンプレートがその1つです。

せっかくなのでこれを参考にしたいなーと思い、Python SDKを利用して展開されたStackSetsからテンプレートを抽出してみましたので、スクリプトを共有します。

もう少し説明

Control Towerの説明は下記がわかりやすいと思います。

AWS Control Towerのラボをやりながら学んでみた-B1セットアップ編

下記のような内容がStackSetsで展開されています。

StackSet名 説明
AWSControlTowerBP-BASELINE-CLOUDTRAIL
すべてのアカウントでAWS CloudTrailを構成する
AWSControlTowerBP-BASELINE-CLOUDWATCH
Cloudwatchルール、ローカルSNSトピックの構成、ローカルSNSトピックからセキュリティトピックへの通知の転送
AWSControlTowerBP-BASELINE-CONFIG
すべてのアカウント/リージョンでAWS Configを設定します
AWSControlTowerBP-BASELINE-ROLES
すべてのアカウントに必要なすべてのベースラインロールを作成します
AWSControlTowerBP-BASELINE-SERVICE-ROLES
CTが使用するサービス(AWS Config、SNSなど)のすべてのアカウントに必要なすべてのサービスロールを作成します
AWSControlTowerBP-SECURITY-TOPICS
SNSとAWS CloudWatchを使用した中央監視とアラート
AWSControlTowerGuardrailAWS-GR-AUDIT-BUCKET-PUBLIC-READ-PROHIBITED
コアアカウントでAWS Configルールを設定して、S3バケットがパブリックアクセスを許可しないことを確認します
AWSControlTowerGuardrailAWS-GR-AUDIT-BUCKET-PUBLIC-WRITE-PROHIBITED
コアアカウントでAWS Configルールを設定して、S3バケットがパブリックアクセスを許可しないことを確認します
AWSControlTowerGuardrailAWS-GR-S3-BUCKET-PUBLIC-READ-PROHIBITED
ガードレールを適用するためのStackSet
AWSControlTowerGuardrailAWS-GR-S3-BUCKET-PUBLIC-WRITE-PROHIBITED
ガードレールを適用するためのStackSet
AWSControlTowerLoggingResources
ログアーカイブアカウントに必要なリソースをセットアップするStackSet
AWSControlTowerSecurityResources
監査アカウントに必要なリソースをセットアップするStackSet
AWSControlTowerBP-VPC-ACCOUNT-FACTORY-V1
アカウントがプロビジョニングされると、このスタックが実行され、ベースラインに基づいてアカウント構成がセットアップされます

CloudFormationのStackSetsについては下記がわかりやすいです。

[新機能] CloudFormation StackSetsを試してみた

CloudFormationのテンプレートをマルチリージョン、マルチアカウントに展開するサービスです。この機能を利用して各種設定を配信しています。

スクリプト

Python 3.6で動かしています。

import boto3

cfn = boto3.client('cloudformation', region_name = 'us-east-1')
sslist = cfn.list_stack_sets()

for stackset in sslist['Summaries']:
	ss_name = stackset['StackSetName']
	ss = cfn.describe_stack_set(StackSetName=ss_name)
	with open(ss_name + '.yaml', 'w') as f:
		f.write(ss['StackSet']['TemplateBody'])

これを実行するとカレントに抽出したテンプレートが保存されます。下記のようになりました。

$ ls -al
total 208
drwxr-xr-x  14 username  group    448 11 12 17:44 .
drwxr-xr-x   8 username  group    256 11 14 18:12 ..
-rw-r--r--   1 username  group   4307 11 12 17:44 AWSControlTowerBP-BASELINE-CLOUDTRAIL.yaml
-rw-r--r--   1 username  group   5784 11 12 17:44 AWSControlTowerBP-BASELINE-CLOUDWATCH.yaml
-rw-r--r--   1 username  group   3638 11 12 17:44 AWSControlTowerBP-BASELINE-CONFIG.yaml
-rw-r--r--   1 username  group   2040 11 12 17:44 AWSControlTowerBP-BASELINE-ROLES.yaml
-rw-r--r--   1 username  group   1784 11 12 17:44 AWSControlTowerBP-BASELINE-SERVICE-ROLES.yaml
-rw-r--r--   1 username  group   4143 11 12 17:44 AWSControlTowerBP-SECURITY-TOPICS.yaml
-rw-r--r--   1 username  group  41798 11 12 17:44 AWSControlTowerBP-VPC-ACCOUNT-FACTORY-V1.yaml
-rw-r--r--   1 username  group    697 11 12 17:44 AWSControlTowerGuardrailAWS-GR-AUDIT-BUCKET-PUBLIC-READ-PROHIBITED.yaml
-rw-r--r--   1 username  group    701 11 12 17:44 AWSControlTowerGuardrailAWS-GR-AUDIT-BUCKET-PUBLIC-WRITE-PROHIBITED.yaml
-rw-r--r--   1 username  group    642 11 12 17:44 AWSControlTowerGuardrailAWS-GR-RESTRICTED-SSH.yaml
-rw-r--r--   1 username  group   4510 11 12 17:44 AWSControlTowerLoggingResources.yaml
-rw-r--r--   1 username  group   2666 11 12 17:44 AWSControlTowerSecurityResources.yaml

もちろんControl Towerのもの以外にも応用できるので良かったら使ってください。

まとめ

ちょっとしたスクリプトですがせっかく書いたので公開しました。

AWSの仕組みで展開されているテンプレートは頑張って探したりして持ってきてもいいですが、展開されたものを拾うほうが楽なときもあると思いますので是非参考にしてみてください。