[AWS Organizations] 特定OUにデプロイされている CloudFormation StackSets を調べるPythonスクリプト

2020.12.01

はじめに

この OUにデプロイしている CloudFormation(CFn)スタックセットを洗い出したい…

こんな要望を解決するスクリプトを書いてみました。

※以下、背景を補足します

CFnスタックセットには Organizations アカウントへの自動デプロイが可能になっています。

  • 特定OUに アカウントが入ったときに、 自動でデプロイされるスタック は何か
  • 特定OUから アカウントが抜けたときに、 自動で削除されるスタック はあるか

アカウントのOU移動の前に上記把握する必要があったためです。

スクリプト

search-stacksets-by-ou.py

import sys
import boto3
import pandas as pd

client = boto3.client('cloudformation')


def is_deployed_in_ou(stackset_name: str, ou_id: str):
    """ StackSet のデプロイ先に 特定OUが含まれているかどうか

    Args:
        stackset_name (str): stackset name
        ou_id (str): organizational unit ID

    Returns:
        bool: StackSet のデプロイ先に 特定OUが含まれているか
    """
    # スタックセット情報を取得
    response = client.describe_stack_set(
        StackSetName=stackset_name
    )
    is_deployed = False
    # OrganizationalUnitIds 値に ou_id が含まれているか
    stacksets_ou_ids = response['StackSet'].get('OrganizationalUnitIds')
    if stacksets_ou_ids:
        is_deployed = ou_id in stacksets_ou_ids
    return is_deployed


def print_stacksets_info_by_ou(ou_id: str):
    """特定OUにデプロイされている CFn StackSets 情報を取得、表示する

    Args:
        ou_id (str): organizational unit ID
    """
    buffer = []
    # スタックセット一覧を取得
    paginator = client.get_paginator('list_stack_sets')
    for page in paginator.paginate():
        for s in page['Summaries']:
            # ステータスが ACTIVE でないものはスキップ
            if s['Status'] != 'ACTIVE':
                continue
            # スタックセットが ou_id にデプロイされているか
            if is_deployed_in_ou(s['StackSetName'], ou_id):
                buffer.append(
                    [
                        s['StackSetName'],
                        s['AutoDeployment'].get('Enabled'),
                        s['AutoDeployment'].get('RetainStacksOnAccountRemoval')
                    ]
                )
    # 出力
    df = pd.DataFrame(buffer, columns=[
        "StackSetName", "AutoDeployment", "AD RetainStacksOnAccountRemoval"
    ])
    print(df.to_markdown(index=False))


if __name__ == "__main__":
    ou_id = sys.argv[1]
    print_stacksets_info_by_ou(ou_id)

必要なパッケージ

requirements.txt

boto3
pandas
tabulate

※私が実行した際の各パッケージのバージョンは以下のとおり

Package Version
boto3 1.16.25
pandas 1.1.4
tabulate 0.8.7

使い方

コマンドライン引数に調べたい OUのIDを入力して、実行します。

python search-stacksets-by-ou.py ou-xxxx-xxxxxxxx

出力例

以下のような出力になります。Markdown テーブルに表示します。

$ python search-stacksets-by-ou.py ou-xxxx-xxxxxxxx
| StackSetName    | AutoDeployment   | AD RetainStacksOnAccountRemoval   |
|:----------------|:-----------------|:----------------------------------|
| IAMAdmPolicy    | False            |                                   |
| IAMDevPolicy    | True             | False                             |
| Network-Cloud9  | False            |                                   |
| Network-VPC     | True             | True                              |   
| S3Buckets       | True             | True                              |
| S3Bucket-Oregon | True             | True                              |

▼ Markdown プレビュー

StackSetName AutoDeployment AD RetainStacksOnAccountRemoval
IAMAdmPolicy False
IAMDevPolicy True False
Network-Cloud9 False
Network-VPC True True
S3Buckets True True
S3Bucket-Oregon True True

表の各列の内容は以下の通り。

  • StackSetName :: OU( ou-xxxx-xxxxxxxx ) に展開されているスタックセット名
  • AutoDeployment :: 「自動デプロイ」機能が有効になっているか
  • AD RetainStacksOnAccountRemoval :: (「自動デプロイ」機能が有効になっている場合) アカウントがOUから抜けた際にスタックセットを保持するか

このOUに入ってきたアカウントに自動デプロイされるスタックセットは AutoDeployment: True の項目を見ることで分かります。

このOUを抜けた際に 削除されてしまうスタックセットAutoDeployment: True, AD RetainStacksOnAccountRemoval: False の項目を見ることで分かります。

おわりに

AWS Organizations 環境で CFn StackSets をガンガン活用していて、デプロイ状況を把握したいときに使えると思います。

この記事が少しでもどなたかのお役に立てば幸いです。

参考