一番簡単なStackSets（CloudFormation）

# はじめに
今まで避けていたCloudFormationのStackSetsを、勉強のつもりで触ってみました。
簡単なサンプルでやり方を記事にしますので、同じような方の参考になれば幸いです。

# 記事概要
- 子AWSアカウントに対して、親AWSアカウントから"StackSets"を使って、CloudFormationを実行
    - 子AWSアカウントと親AWSアカウントは、同じでも可能
        - 今回は別にしました
    - AWS Organizationsを使わない方法になります

今回は以下のCloudFormationを実行してIAMユーザを作ります。

```yaml:createIAMUser.yaml
AWSTemplateFormatVersion: 2010-09-09

Resources:
  AWSUser:
    Type: AWS::IAM::User
    Properties:
      UserName: 'You'
```

# 参考ページ

https://goodbyegangster.hatenablog.com/entry/2019/07/24/004732

# 手順

## 子AWSアカウントにIAMロール作成
子のAWSアカウント内に、CloudFormationを実行させるIAMロールを作成します。

```yaml:creatChildRsource.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetExecutionRole to enable use of your account as a target account in AWS CloudFormation StackSets.

Parameters:
  AdministratorAccountId:
    Type: String
    Description: AWS Account Id of the administrator account (the account in which StackSets will be created).
    MaxLength: 12
    MinLength: 12

Resources:
  ExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: AWSCloudFormationStackSetExecutionRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !Ref AdministratorAccountId
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AdministratorAccess'
```
- リソースが作成できる権限を与えてください
    - 今回はAdministratorAccessを付与しています
- パラメータには、親AWSアカウントのIDを入力してください

## 親AWSアカウントにIAMロール作成
親のAWSアカウント内に、StackSetsを実行するIAMロールを作成します。

```yaml:creatParentrRsource.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetAdministrationRole to enable use of AWS CloudFormation StackSets.

Resources:
  AdministrationRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: AWSCloudFormationStackSetAdministrationRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: AssumeRole-AWSCloudFormationStackSetExecutionRole
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - sts:AssumeRole
                Resource:
                  - 'arn:aws:iam::*:role/AWSCloudFormationStackSetExecutionRole'
```
- `Resource`で、先ほど子AWSアカウントに作成したIAMロールが対象になっているか確認

## 親AWSアカウントで、StackSets実行
ここからはコンソールを操作します。

CloudFormationの画面で、StackSetの作成をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/a10af5e2-38d1-32c0-9e52-5471617bdb7e.png)

IAM実行ロール名は、先ほど作成したロールを指定。
テンプレートファイルは本記事の最初に示した、ユーザを作成する`createIAMUser.yaml`を指定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/b7ef7e8b-7cb3-8b00-e02d-56d003fcfc95.png)

StackSetの名前を指定して次へ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/147db48a-8047-fb73-3d3a-f7308e6e2322.png)

実行指定は競合する場合に考慮が必要な設定のようですが、今回はIAMユーザを1つ作るだけなので、非アクティブにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/84d49770-9c06-12fa-b05c-47478f4b368f.png)

今回は新しくスタックを作るので、新しいスタックのデプロイを選択。
デプロイ先に、子AWSアカウントIDをカンマ区切りで指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/ebe5635f-2274-ff3c-8429-a5d453ceef66.png)

リージョンは東京を1つ指定し、デプロイオプションはデフォルトのままにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/56f7f3b9-258c-1fe0-32c4-e2d94c3a340b.png)

確認画面で設定を確認します。
IAMユーザを作成するので、いつもの以下のチェックが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/d15b8ebf-b0bc-574e-4024-df51efbe96bc.png)


作成を開始すると、オペレーションタブに進捗が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/204fd516-aa35-1e02-1839-260dff46c07e.png)

成功すると、スタックインスタンスタブに内容が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/9b141f3f-db34-c7e4-6894-ac320306642e.png)

子AWSアカウントで、IAMユーザを作成するスタックが作られていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/5dc6792b-70d4-dcbd-bedb-828e3668be74.png)

ちゃんとIAMユーザも作られていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/3e49c645-12fa-5f14-c802-f9ae27f36dfe.png)

## StackSetsで、テンプレートを変更
続けて、テンプレートのyamlファイルを変更してみます。ユーザ名を以下のように変更しました。
```yaml:createIAMUser-neo.yaml
AWSTemplateFormatVersion: 2010-09-09

Resources:
  AWSUser:
    Type: AWS::IAM::User
    Properties:
      UserName: 'Yuu-Takasaki'
```

先程作成したStackSetを選択し、アクションから "StackSetの詳細を編集" を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/8f8e37d1-ad2e-de43-69c2-24ea35d9dce3.png)

その後はほぼ作成時と同様の画面になります。テンプレートファイルは変更後のものを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/d55a9873-6213-2a65-d767-07c6f337f01e.png)

アカウントとリージョンは空になっていました。作成時と同じ設定にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/c3b1c062-4a03-df3b-6eda-611900df0725.png)

実行を開始すると、オペレーションにUPDATEで進捗が表示されます。スタックインスタンスのタブは完了後も特に変わりありませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/a8c8afdd-6faa-6908-0575-0c3dc2b92874.png)

子AWSアカウントの対象のスタックを見ると、UPDATEとなっていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/382b40cc-9288-31a6-48e9-e4f203985a91.png)

IAMユーザ名も新しいものになっていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/0b41adb4-79c6-3bbd-6663-cfc4061ecb4e.png)


## 削除手順
作成した各種リソースを削除する場合は以下の順序になります。

1. スタックの削除
    - スタックが残っている状態でStackSetを削除はできず、エラーになりました。 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/b02bf5bd-c619-9449-7028-d081cfc78f1b.png)

1. StackSetの削除
1. 親/子のアカウントで作成したIAMロールの削除

### スタックの削除方法
スタックの削除は、アクションから選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/9ccfbbc4-d7cc-e723-73b6-0560e309000d.png)

こちらでもデプロイオプションが空なので、削除する内容を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/a3a1e1d5-542e-f5bc-ffa7-b71d0562a42c.png)

デプロイオプションに、"スタックを保持"というのがあります。これをONにすると、このStackSetから管理外になるだけで、子AWSアカウントのスタックはそのまま残ります。
今回はOFFにして作成したIAMユーザも削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/de6b1b1c-ba0e-132d-9312-9a6399f2f3db.png)


実行すると、オペレーションにDELETEが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/2f6bdc1d-04fd-2650-2a50-88723224b68e.png)

成功すると、スタックインスタンスは空になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/028adfb7-a242-c207-bce0-a972e0a4395e.png)

### StackSetsの削除方法
続けて、アクションから Stacksetの削除 を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/3379d15b-51e3-07ff-8807-d5b0dd1fde59.png)

確認ポップアップが出てきますので、削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/3fbb0922-8970-5384-83f5-fa9bc3d867de.png)

これでStackSetは削除されます。
あとは作成したIAMロールを削除してください。

# おわりに
今回はIAMユーザを作るだけのStackSetsを記事にしました。
親子関係があったり、Organizationsを使うと思い込んでいたりで避けていた機能でしたが、親子それぞれにIAMロールを作り、GUIだけでできたため、かなり簡単だった印象です。
私と同様避けていた方は、簡単ですので触ってみてください。

ただパラメータを使うと厄介な点ありましたので、それについていずれ記事にしたいと思います。