配布されているCloudFormationテンプレートをいい感じに書き換える小ネタ

こんにちは。AWS歴３年生の人です。

CloudFormation、便利ですよね。AWSから公式配布されているテンプレートや各ソフトウェアメーカーから公式配布されているテンプレートを使ってサクっと環境を再現することも簡単です。

ただ、会社などの業務利用しているAWSアカウントなどは「ガードレール」といった品質・セキュリティ統制が整備されていることもあり、そう簡単にサクッといかないのでその場合に、書き方を変えるだけで回避できるポイント、あるあるのチェックポイントの一例をご紹介します。



## YAMLからJSONに、JSONからYAMLに変換する

「自分はYAML派なんだけど配布されているテンプレートがJSONで書かれている・・・」など

CloudFormationを流す前からやる気がそがれてしまいそうですが、以下の方法で簡単に変換ができます。

１．CloudFormation　＞　デザイナー　を起動する

２．タブ「テンプレート」を選択（下記図の①）

３．変換前のコードをペーストする（下記図の②）

４．右上の「テンプレート言語の選択」を変換後を選択する（下記図の③）

![cfndesign1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611580/dd567a85-eedf-a840-e2d8-d9223a211453.png)


無事に変換ができました！

![cfndesign2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611580/37daef59-508a-fec0-0cb5-1d0d51606b7b.png)




## ロールのインラインポリシーをカスタマー管理ポリシーに書き換える

インラインポリシーは、ロール作成と同時に記述できて便利なのですが、後からポリシー単体で管理したい場合などがあるので、カスタマー管理ポリシーに書き換えます。

- 変更前　インラインポリシーの例

  ```yaml
    AdminGroupRole:
      Type: 'AWS::IAM::Role'
      Properties:
        RoleName: !Join 
          - ''
          - - !Ref pUserPoolId
            - '-AdminGroupRole'
        AssumeRolePolicyDocument:
          Version: 2012-10-17
          Statement:
            - Sid: ''
              Effect: Allow
              Principal:
                Federated: cognito-identity.amazonaws.com
              Action: 'sts:AssumeRoleWithWebIdentity'
              Condition:
                StringEquals:
                  'cognito-identity.amazonaws.com:aud': !Ref pIdentityPoolId
                'ForAnyValue:StringLike':
                  'cognito-identity.amazonaws.com:amr': authenticated
        Policies:
          - PolicyName: vodaws-admin-group-policy
            PolicyDocument:
              Version: 2012-10-17
              Statement:
                - Sid: VisualEditor0
                  Effect: Allow
                  Action:
                    - 's3:PutObject'
                    - 's3:DeleteObject'
                  Resource: !Sub 'arn:aws:s3:::${pInputBucket}/public/*'
  ```



- 書き換えポイント

  - Policies以下を削除し、ロールとは別にカスタマー管理ポリシーとして作成するように書き換えます

  - ロールからは作成したポリシーを参照するように記述します

    

- 変更後　ロールとカスタマー管理ポリシーを分けた後の例

  ```yaml
    AdminGroupPolicy:
      Type: AWS::IAM::ManagedPolicy
      Properties:
        ManagedPolicyName: vodaws-admin-group-policy
        PolicyDocument:
          Version: 2012-10-17
          Statement:
            - Sid: VisualEditor0
              Effect: Allow
              Action:
                - 's3:PutObject'
                - 's3:DeleteObject'
              Resource: !Sub 'arn:aws:s3:::${pInputBucket}/public/*'
    AdminGroupRole:
      Type: 'AWS::IAM::Role'
      Properties:
        RoleName: !Join 
          - ''
          - - !Ref pUserPoolId
            - '-AdminGroupRole'
        AssumeRolePolicyDocument:
          Version: 2012-10-17
          Statement:
            - Sid: ''
              Effect: Allow
              Principal:
                Federated: cognito-identity.amazonaws.com
              Action: 'sts:AssumeRoleWithWebIdentity'
              Condition:
                StringEquals:
                  'cognito-identity.amazonaws.com:aud': !Ref pIdentityPoolId
                'ForAnyValue:StringLike':
                  'cognito-identity.amazonaws.com:amr': authenticated
        ManagedPolicyArns:
          - !Ref AdminGroupPolicy      
  ```

  

  ロールとポリシーを分けることで、ひとつのリソースの記述行が短くなり、あとからポリシーを別のロールにアタッチすることもできるようになりました。

  


## ロールにPermissions Boundaryをつけたい場合

配布されているCloudFormationはPermissions Bounbaryがないことが多いので、必要に応じて以下のようにロールに追加します。

- 前述のロールにPermissions Boundary（ポリシー名PermissionBoundary）をつけた例

  ```yaml
    AdminGroupRole:
      Type: 'AWS::IAM::Role'
      Properties:
        RoleName: !Join 
          - ''
          - - !Ref pUserPoolId
            - '-AdminGroupRole'
        AssumeRolePolicyDocument:
          Version: 2012-10-17
          Statement:
            - Sid: ''
              Effect: Allow
              Principal:
                Federated: cognito-identity.amazonaws.com
              Action: 'sts:AssumeRoleWithWebIdentity'
              Condition:
                StringEquals:
                  'cognito-identity.amazonaws.com:aud': !Ref pIdentityPoolId
                'ForAnyValue:StringLike':
                  'cognito-identity.amazonaws.com:amr': authenticated
        ManagedPolicyArns:
          - !Ref AdminGroupPolicy 
        PermissionsBoundary: !Join
          - ""
          - - "arn:aws:iam::"
            - !Ref "AWS::AccountId"
            - ":policy/PermissionBoundary"  
  ```

  

## その他

- 命名ルールが定められている場合は従いましょう。

- cognitoのidentityPoolIdのCloudFormationで、「identityPoolIdの作成が先か、アタッチするロールの作成が先か」のニワトリタマゴ問題にぶつかります。
  AWSから配布されているCloudFormationではカスタムリソースを使って動的にロールのマッピングを行って解決しています。カスタムリソースが使えない場合は、最初にどちらかの設定を空で作成し、あとから手作業でAuthRole,UnauthRoleにロールアタッチ、もしくはAssumeRolePolicy（信頼関係）を修正しています。（他に正解があるかもしれません・・・）

  

  

## 最後に

配布されているCloudFormationを作ってくれている方には、ただただ感謝の一言です。書き方の勉強にもなるのでいつも参考にさせてもらっています。ありがとうございます！



## この記事で参考にしたCloudFormation

Creating a secure video-on-demand (VOD) platform using AWS
https://aws.amazon.com/blogs/media/creating-a-secure-video-on-demand-vod-platform-using-aws/