エンタープライズクラウド部の山下(祐)です。
AWS Organizations環境下で、複数のアカウントを特定のOUに一括で移動させたかったので、簡単なスクリプトを組んで移動させてみました。
今回の環境
今回は、以下のような条件下で移動を行います。
- Organizationsの管理アカウントでAWS CLIが利用可能。ただし、MFAで二要素認証されている。
- 各アカウントが移動前に所属しているOUはバラバラでも良い。
- 移動させたいアカウントはリスト化されている。
- 各アカウントの移動先のOUは同一。
具体的には、下図のSandbox OU・Business OU・IAM OU 配下の4アカウントを、Suspended OUに移動します。(検証環境のためOU名は適当ですが、ご容赦ください。)
事前準備
まずは事前準備として、以下を実施します。
- 移動させたいアカウントの一覧を用意する。
- Organizationsの管理アカウントで一時認証情報を取得する。
- 「.aws/config」に一時認証情報のprofileを追加する。
- 移動先OUのOU IDを確認する。
移動させたいアカウントの一覧を用意する
以下のように、1行につき1アカウントが記載されたテキストファイルを用意します。 本ブログではファイル名を「move_account_list.txt」とします。
111111111111 222222222222 333333333333 444444444444 ・ ・ ・
Organizationsの管理アカウントで一時認証情報を取得する
以下コマンドを実行し、一時認証情報を取得します。 Organizations管理アカウントで、AWS CLI実行時に二要素認証が必要でない環境であれば、本手順は不要です。 「.aws/config」ファイルで複数の profile を使い分けている場合、Organizations管理アカウント用の profile を指定してください。
aws sts get-session-token --serial-number <MFAデバイスのARN> --token-code <MFAトークンコード>
コマンドが成功すると、以下のサンプルのような、一時認証情報が出力されます。 有効期限があるためご注意ください。(Expirationに記載の時刻まで利用可能)
{ "Credentials": { "AccessKeyId": "ASIA574××××××××S5UOKBD", "SecretAccessKey": "Enqe7K7Oj2VKVM×××××××××××thvYSBf86AO/H", "SessionToken": "FwoGZXIvYXdzEKX//////////wEaDG4IBEijFDaVHbCUMiKGAYqcEoXb7SEIV7yf3LTu××××××××××××××××××××××××××××××××××××××p8sLWDg7lj1Ue8jQkWAmZ8/IEtcQDSL88kSY4lExWYBAmMmdbSzkvAeo5fX7np7gPG5O5TxaxFhBCnnI/vbmo7MHZWOo+EqulN0iRm60Y3gbVKJShyJoGMijoyK/mZ/jc2wP4Uoay72yNeJUJcOr5TdZ2uhyf7yTOZomLT9GsE3Xb" "Expiration": "2024-05-28T21:31:35+00:00" } }
取得した情報を「.aws/credential」に追記します。
[temp] aws_access_key_id = ASIA574××××××××S5UOKBD aws_secret_access_key = Enqe7K7Oj2VKVM×××××××××××thvYSBf86AO/H aws_session_token = FwoGZXIvYXdzEKX//////////wEaDG4IBEijFDaVHbCUMiKGAYqcEoXb7SEIV7yf3LTu××××××××××××××××××××××××××××××××××××××p8sLWDg7lj1Ue8jQkWAmZ8/IEtcQDSL88kSY4lExWYBAmMmdbSzkvAeo5fX7np7gPG5O5TxaxFhBCnnI/vbmo7MHZWOo+EqulN0iRm60Y3gbVKJShyJoGMijoyK/mZ/jc2wP4Uoay72yNeJUJcOr5TdZ2uhyf7yTOZomLT9GsE3Xb
「.aws/config」に一時認証情報のprofileを追加する
一時認証用の profile を、「.aws/config」に追記します。
[profile temp] region = ap-northeast-1 output = json
移動先OUのOU IDを確認する
AWS Organizationsの画面でOU IDを確認します。「ou」から始まる文字列です。
スクリプトを実行
事前準備が出来たら、スクリプトを実行します。
今回作成したスクリプト
今回作成したスクリプトは以下です。
#!/bin/bash FILE_NAME=./move_account_list.txt DEST_ID=<移動先OUのOU ID> PROFILE=<一時認証用のprofileのprofile名> while read ACCOUNT do BEFORE_ID=$(aws organizations list-parents --child-id ${ACCOUNT} --profile ${PROFILE} --query 'Parents[].Id' --output text) sleep 5 aws organizations move-account --account-id ${ACCOUNT} --source-parent-id ${BEFORE_ID} --destination-parent-id ${DEST_ID} --profile ${PROFILE} sleep 10 AFTER_ID=$(aws organizations list-parents --child-id ${ACCOUNT} --profile ${PROFILE} --query 'Parents[].Id' --output text) sleep 5 echo "${ACCOUNT},${BEFORE_ID},${AFTER_ID}" >> ./move_result_list.csv done < ${FILE_NAME}
DEST_IDの値はスクリプト中にベタ書きしてしまいました。。本当はIDを直接入れたくないのですが、OU名からOU IDを引っ張ってくるAWS CLIコマンドが無かったため、泣く泣くこのような形を取りました。
もしこのスクリプトを参考にしてご利用される場合、リソースIDが直接記述されることを予めご認識のうえ、取り扱いにはご注意いただくよう、お願いします。
また、今回は検証なのでエラーハンドリングの処理は入れていません。ご自身の環境でご利用される場合は、必要に応じて適宜そういった処理を追加いただければ幸いです。
スクリプトの中身解説
かなりシンプルなスクリプトですが、折角なので中身を解説したいと思います。
変数の宣言
FILE_NAME=./move_account_list.txt DEST_ID=<移動先OUのOU ID> PROFILE=<一時認証用のprofileのprofile名>
変数を宣言します。
「FILE_NAME」にはアカウントリストのファイルパスを指定します。本ブログではスクリプトファイルからの相対パスで記載しています。お手元の環境に合わせて適宜変更ください。
「DEST_ID」には移動先OUのOU IDを指定します。前述通り、リソースIDをベタ書きしてしまっているので、正直あまり良い書き方とは言えません。。
「PROFILE」には一時認証用のprofileのprofile名を指定します。本ブログでは「temp」としています。
繰り返し処理
while read ACCOUNT do ・ ・ ・ done < ${FILE_NAME}
アカウントリストから1行ずつアカウント番号を読み込み処理を行います。 リストに記載されているアカウント数分、処理を繰り返します。
移動前OU IDの取得
BEFORE_ID=$(aws organizations list-parents --child-id ${ACCOUNT} --profile ${PROFILE} --query 'Parents[].Id' --output text) sleep 5
対象のアカウントが移動前に所属しているOUのOU IDを取得し、「BEFORE_ID」という変数に結果を格納しています。
「aws organizations list-parent」では以下サンプルのような結果が得られるので、queryでOU IDだけを取得しています。
{ "Parents": [ { "Id": "ou-examplerootid111-exampleouid111", "Type": "ORGANIZATIONAL_UNIT" } ] }
指定したOUへの移動
aws organizations move-account --account-id ${ACCOUNT} --source-parent-id ${BEFORE_ID} --destination-parent-id ${DEST_ID} --profile ${PROFILE} sleep 10
メインの処理です。アカウントリストから読み込んだをアカウントを、「DEST_ID」で指定したOUに移動します。
移動後のOU IDの確認
AFTER_ID=$(aws organizations list-parents --child-id ${ACCOUNT} --profile ${PROFILE} --query 'Parents[].Id' --output text) sleep 5
移動後に再度アカウントが所属しているOUのOU IDを確認し、「AFTER_ID」という変数に格納しています。本来であれば、「AFTER_ID」と「DEST_ID」を比較して、不一致があればエラー処理を行う等の記述があった方が良いと思うのですが、今回はエビデンスとして取得するに留めています。
CSVへの出力
echo "${ACCOUNT},${BEFORE_ID},${AFTER_ID}" >> ./move_result_list.csv
アカウント番号、移動前のOU ID、移動後のOU IDをCSVファイルへ出力しています。
CSVの内容は以下サンプルのようになります。
111111111111,ou-xxxx-aaaaaaaa,ou-xxxx-12345678 222222222222,ou-xxxx-bbbbbbbb,ou-xxxx-12345678 333333333333,ou-xxxx-bbbbbbbb,ou-xxxx-12345678 444444444444,ou-xxxx-cccccccc,ou-xxxx-12345678 ・ ・ ・
実行結果
最後に、実際にスクリプトを実行した結果です。 AWS Organizationsの画面を更新すると、下図の通り、想定通り全て移動されていました。
以上です。移動するアカウントが100を超えるような場合、かつ、移動前のOUがバラバラの場合、マネジメントコンソール上で移動させるのは手間なので、スクリプトで移動させてみました。同じような状況に置かれている方の参考になれば幸いです。
山下 祐樹(執筆記事の一覧)
2021年11月中途入社。前職では情シスとして社内ネットワークの更改や運用に携わっていました。 2023 Japan AWS All Certifications Engineers。