AWS Organizationsで毎日AWSアカウントを初期化しようとした

# はじめに
この記事は [NTTテクノクロス Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ntt-tx) の10日目の記事です。

NTT テクノクロスの渡邉です。
普段は AWS 関連の業務に携わっております。
ときおり[社外向けブログ](https://www.ntt-tx.co.jp/column/dojo_aws_blog/20180411/?utm_source=qiita&utm_medium=ac2019&utm_campaign=10)執筆や、社内研修の講師なども。

今回は**AWS アカウントの初期化**について考えていきたいと思います。

# 「AWSアカウント初期化」のニーズはあるか？

そもそも、AWS アカウントを初期化したいケースってなんぞや？と疑問に思うかもですね。
自己紹介でも触れましたが、私は社内で年に数回ほど[ソフト道場研修](https://www.ntt-tx.co.jp/products/soft_dojyo/?utm_source=qiita&utm_medium=ac2019&utm_campaign=10)にて、 AWS領域の講師を務めております。
AWS領域では現在4人の講師陣が自身の専門性を活かし、 [入門編(IaaS)](https://www.ntt-tx.co.jp/column/dojo_aws_blog/20171017/?utm_source=qiita&utm_medium=ac2019&utm_campaign=10)、サーバレス編(PaaS)、Alexa編などを開催しております。[^1]

研修でのAWS アカウント運用イメージは、ざっくりこんな感じです。

- 研修はハンズオン主体とし、事前に払い出した受講者用の IAM ユーザを利用して、所定のサービスを作成してもらう。
  - 操作は主にAWSマネジメントコンソール(以下マネコンと表記)からの経由を想定。
  - IAMユーザの権限は、カリキュラムで用いるサービスのみ認可する。
- 所定のハンズオン後は基本的に自由に操作してもらい、実環境での経験を積んでもらう。
  - 受講者の要望に応じて、講師が IAM 権限を個別で認可する。
  - 高額な利用料が予想されるユースケースでなければ基本的に認可する方針。
- 研修後、ハンズオンにて作成されたリソースが受講者分(15～20程度)残存する。
  - アカウント維持費用の軽減、不要リソースへのセキュリティリスク削減のため、速やかに削除したい。
  - 現実的な話として不要リソースがあると、次の研修で受講者が混乱しますよね……

本業の隙間での研修対応のため、限りある稼働は本編の改善に充てたい。という想いもあり、研修後の削除フローは検討の優先度が低く、講師陣が力技で解決していたのがここ数年。
ただ、研修後に疲れた頭でマネコンを操作するのはスマートじゃない。早く終わらせてハッピーアワーに滑り込みたい。などの意見が講師陣から上がり、いま一度フローを見直したい！というのが「**AWS アカウントの初期化**」というニーズであり、この記事の執筆理由というわけです。

同様の悩みを抱える研修担当さん、イベント主催者さんが世界のどこかに居ると信じながら、AWS的に考えてみましょう。

## １．理想編

リソース削除の理由を思い出してみましょう。
>受講者が触れる AWS アカウントは混乱を招かない為にも、研修開始時点で極力**まっさら**にしたい。

まっさらなアカウント、つまり初期状態のアカウントが常にあれば良く。
それならいっそ、毎日アカウントを作って毎日解約すればいいのでは？
**[AWS Organizations](https://aws.amazon.com/jp/organizations/)**を活用すればアカウント作成、解約するフローも自動化できそう。例えばこんな感じで。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528454/3b1e1ef3-3b9c-5b92-155c-4762f9ab2b79.png)

### 構成図の解説

- 親アカウントのS3バケットに、プロビジョニング用CloudFormation テンプレートを配置。
  - \<ForProvisionningBucket>/common/setup.yaml
     - テンプレートの中身は、管理系サービスの有効化([AWS CloudTrail](https://aws.amazon.com/jp/cloudtrail/), [AWS Config](https://aws.amazon.com/jp/config/), [Amazon GuardDuty](https://aws.amazon.com/jp/guardduty/), etc……)。
  - \<ForProvisionningBucket>/aws-01/setup.yaml
     - テンプレートの中身は、研修受講者用IAMユーザ、研修用IAMRoleなど。

- 必要に応じ、VPCやEIP などの上限緩和申請も自動セットアップする。
  - 具体的には[AWS Service Quotas] (https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/services-that-can-integrate-service-quotas.html)を利用して、Organizationsを通じて作成される新しいアカウントに対し適用される、定義済みクォータリクエストテンプレートを設定する。

- 研修数日前に、親アカウントにて[AWS Lambda](https://aws.amazon.com/jp/lambda/)が起動し、以下の動作を実施。
   - Organizations で子アカウントを作成し、CloudFormationを利用して管理系サービス、研修用IAM類をセットアップする。
- 研修終了日にLambdaが起動し、Organizations で子アカウントを<del>削除する</del>  **組織から解除**する。
  - アカウント削除はrootユーザでのマネジメントコンソール操作が必須のため、フロー検討が別途必要。

※元ネタ：[Automate account creation, and resource provisioning using AWS Service Catalog, AWS Organizations, and AWS Lambda](https://aws.amazon.com/jp/blogs/mt/automate-account-creation-and-resource-provisioning-using-aws-service-catalog-aws-organizations-and-aws-lambda/)

軌道に乗せるまでは大変そうですが、上記AWSのブログにはサンプルコードもあるので比較的とっつきやすそうですね！

と、これで解決すればよかったのですが。

## ２．理想と現実編

上記スキームが確実に可能となるのは、AWS アカウント作成に必要な決済情報(クレジットカードなど)とメールアドレスを**自分が管理している場合**です。

AWS アカウントの仕様をおさらいしましょう。
解約時は 2019.11 時点にて、以下の制約があります。(強調は筆者)


>閉鎖後期間が過ぎると、AWS アカウントは完全に閉鎖され、再開することはできません。削除していなかったコンテンツは削除され、終了していなかった AWS サービスは終了されます。**また、AWS アカウントを閉鎖する際に登録されていたものと同じエイリアスまたは E メールアドレスを使用して新しい AWS アカウントを作成することもできません。**
>
>参考：[アカウントの解約](https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/close-account.html)


したがって、アカウントを使い捨てる運用をするには、使い捨てる為のメールアドレスを入手する必要があります。
本件の場合、自社の決済情報とAWSアカウントIDが紐付くため、適当なフリーアドレスは使えないですよね。もちろん社内ドメインのアドレスを用意しましょう。……えっ、研修の日程数と同数のメールアドレスの発行！？

貴方が一定の権限を有し、アカウント発行用メアドの用意を調整できる立場であれば、大丈夫にできるかもしれません。
私の立場としては、なかなか煩雑そうだなという印象を受けます。「研修の後始末が大変なので、毎日解約&契約させて♪」って社内のIT部門に頼むのは若干勇気が要るし……

社内の調整なしで、現場だけで実現出来る方法も併せて用意しときましょう。

### ちなみに(よくない発想)

アカウント解約後にすぐ復帰することで、実質初期状態のアカウントを取得できそうにも思えますが、
下記の制約により、解約後復帰した AWS アカウントはリソースが未削除のまま復帰されます。

> Q: アカウントを閉鎖した後もコンテンツは保持されますか?
>アカウントの閉鎖前に削除されたコンテンツは保持されませんが、閉鎖後期間中はコンテンツは削除されません。閉鎖後期間が過ぎると、アカウントに残されたコンテンツは削除されます。その前にコンテンツを削除する場合は、アカウントの閉鎖前にコンテンツを削除する必要があります。
>
>参考：[AWS アカウントの閉鎖に関するよくある質問](https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/account-closure-faq.html)

残念(？)ながら利用者が消す手間は変わらない以上、アカウントを解約リセットで転用する案は難しそうです。

## ３．現実編

アカウント解約によるリセットが厳しい場合、初期化のベストプラクティスと呼べる方法は無さそうです。個々のアカウント運用方法によって削除方法も異なるので仕方ありません。
つまり、不要リソースを如何に効率的に削除するかという戦略を取ることに。現実は厳しい。

### 削除対象リソースの探し方

- ハンズオンで作成が計画されたリソース
  - 基本的にはdescribeして、全削除が出来る環境が好ましい。
  - 上記が叶わない場合は、ハンズオンで受講者が作成予定のリソース名、タグ名を法則性のある名称にし、機械的に削除しやすくする。
    - 例えば、hoge-student01、hoge-student02 …… と連番にするなど。
- ハンズオンで作成が計画されていないリソース
  - 受講者が自由時間で作ったもの、あるいは研修中に誤って作ったもの(意外と多い)
  - CloudTrail＋AWS Athenaで下記のようなクエリを投げ、アカウントで発生したCreate系イベントを洗い出すのがスマートかもです。

      ``` SQL
      -- 2019-12-01 09:30 ~ 17:30 JSTの研修で作られたリソース情報を参照するクエリの例
      SELECT * FROM your_athena_tablename
      WHERE eventname like 'Create%'
      and eventtime >= '2019-12-01T00:30:00Z'
      and eventtime < '2019-12-01T08:30:00Z' ;
      ```

### 削除方法、実行環境など

- 計画するリソース情報 + 上記Athenaクエリ結果を削除用Lambdaに渡し、きれいに削除するのが理想的。
- とは言え、そこまでの工数かけられないよ！という方は、いっそ下記の運用でも機能するかも。
  - 管理者用IAMユーザでAWSマネジメントコンソールへログインし、AWS Cloud9で実行環境を作成。
  - 事前に準備済のスクリプト(削除用AWS-CLIコマンドを書き連ねたもの)を実行し、リソースを削除する。
     - Cloud9ではアクセスするIAMの権限でCLIが実行可能。[^2]
  - 全て完了したらCloud9環境も削除。
- 先月発表された、[CloudFormation スタックへの既存リソースのインポート機能](https://aws.amazon.com/jp/blogs/news/new-import-existing-resources-into-a-cloudformation-stack/)も活用できそうです。
  - 面倒なリソースは準備用スタックへ全てimportして、Delete Stack。依存関係も気にせずスッキリですね。

### オマケ
受講者+αで20個くらい削除した経験上、マネコンからの大量削除はお勧めできません。
少なくとも下記のサービス群の初期化については、脱マネコンをご検討ください。つらいぞ。

|サービス名|マネコンからの削除時の仕様|
|:---|:---|
|RDS|・リソース削除時に複数選択できない。<br>・削除を試みると、スナップショット取得可否の確認がある。<br>・直前にキーボードで「Delete me」を入力する必要あり。|
|S3|・リソース削除時に複数選択できない。<br>・削除時にバケット名を入力する必要あり。|
|API Gateway|・リソース削除時に複数選択できない。<br>・**アカウント単位で1分間に1リソースまでしか削除できない制約あり。(CLI等からでも同様)** |
|CroudFront|・リソース削除/disable時に複数選択できない。<br>・各リソースをdisableしてからdeleteが必要。完了までの時間が10～20分以上と不定なので、スクリプト化する際にもwait等の作りこみが必要|
|SNS|・リソースを複数選択できない。<br>・削除時に「これを削除」と入力する必要あり。|
|WAF|・リソースを複数選択できない。<br>・各コンポーネント(WEB ACL、Rules、Condition)の依存関係を紐解きながらの削除が必要。|
|CloudWatch Logs|・削除するのを忘れがち(私見)。<br>・Logsのみ消し損ねた場合、元のリソースIDとの紐づけが難しく、削除に手間取ることも。|

# おわりに
AWSアカウントの初期化について、いろいろ考えてみました。
準備が大変な案も挙げてしまいましたが、利用目的に応じて無理のない作り込みにしましょうね。

11日目は @9800se さんです。お楽しみに！

[^1]: 過去には[監査&ロギング編](https://www.ntt-tx.co.jp/column/dojo_aws_blog/20171212/?utm_source=qiita&utm_medium=ac2019&utm_campaign=10)も実施していました。
[^2]: 参考：[AWS Cloud9 に関するよくある質問](https://aws.amazon.com/jp/cloud9/faqs/)