【AWS CloudFormation】ロール作成を通してポリシーとロールの関係を理解する

CloudFormationでRoleを作成しようとしたところ、かなりハマってしまったので、ポリシーとロールの現状の理解をまとめておこうと思います。

# ■ ポリシーとは
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html

ポリシーとは、**だれが** 、 **どんな操作を** 、 **どのリソースに対して**　行えるかを定義する仕組みです。
ポリシーの定義は主に下記の要素で構成されています。

- [Principal](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_principal.html)  
**誰が** に相当する項目。IAMユーザー(ロール)やAWSサービスを指定します。
- [Action](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_action.html)  
**どんな操作を** に相当する項目。 `s3:GetObjec` のようにAWSサービスとその操作を `:` 区切りで指定します。
- [Resource](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_resource.html)  
**どのリソースに対して** に相当する項目。 `arn:aws:s3:::DOC-EXAMPLE-BUCKET/*` のように操作対象のリソースを指定します。
- [Effect](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_effect.html)  
操作を許可する( `Allow` )か、許可しない( `Deny` ) かを指定します。

例えば、S3の読み込み専用ポリシー( `AmazonS3ReadOnlyAccess` )の定義はこんな感じ

```js:AmazonS3ReadOnlyAccess
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:Get*",  // *はワイルドカード
                "s3:List*"
            ],
            "Resource": "*"
        }
    ]
}
```

## ◎ ポリシータイプ
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html#access_policy-types

そんなポリシーには[いくつか種類があります。。。](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html#access_policy-types)が、今回は必要な2に絞って理解していきます。

1. **アイデンティティベースのポリシー**
1. **リソースベースのポリシー**

## ◎ 1. アイデンティティベースのポリシー
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html#policies_id-based

IAM アイデンティティ (ユーザー、ユーザーのグループ、ロール)にアタッチするポリシーで、アタッチされたIAMアイデンティティが **どのリソースに対して(Resource)** 、 **どんな操作を(Action)** 行えるのかを定義します。
**誰が(Principal)** はアタッチされたIAMアイデンティティであるため、 `Principal` のセクションは指定しません。
アイデンティティベースのポリシーには次のような分類があります。

- AWS管理ポリシー  
AWSが用意している再利用可能なポリシー
- カスタマー管理ポリシー  
ユーザー側で作成した再利用可能なポリシー
- インラインポリシー  
各IAMアイデンティティに直接追加するポリシー

※ [管理ポリシーとインラインポリシーの比較](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#choosing-managed-or-inline)


### 例) S3のフルアクセスポリシー

```js:AmazonS3FullAccess
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}
```

## ◎ 2. リソースベースのポリシー
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html#policies_resource-based

リソースベースのポリシーはAWSリソースにアタッチするポリシーで、リソースが **誰に(Principal)** 、 **どんな操作を(Action)** 許可するのかを定義します。
**どのリソースに対して(Resource)** はアタッチされたリソースであるため、 `Resource` セクションは指定しません。
リソースベースのポリシーにはS3のバケットポリシーやIAMロールの信頼ポリシーがあります。
今回理解しておかなければならないのは **IAMロールの信頼ポリシー** です。

### # IAMロールの信頼ポリシー

IAMロールの信頼ポリシーとはIAMロールにアタッチするポリシーで、アタッチされたIAMロールが保有する権限をIAMアイデンティティやAWSサービスに移譲することができます。

例えば、このポリシーはIAMロールが保有する権限をAWS Lambdaに移譲できます。


```js
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                // "AWS": ["arn:aws:iam::AWS-account-ID:user/user-name-1"] のようにIAMアイデンティティを指定してもOK
                "Service": ["lambda.amazonaws.com"] 
            },
            "Action": "sts:AssumeRole",
        }
    ]
}
```

# ■ ロールとは
IAMロールは**アイデンティティベースのポリシー(Policies)** と **IAMロールの信頼ポリシー(AssumeRolePolicyDocument)** から成り立っており、**アイデンティティベースのポリシー** の権限を **IAMロールの信頼ポリシー** で指定したIAMアイデンティティやAWSサービスに移譲することができます。

# ■ CloudFormationでロールを作成

ポリシーとロールを理解したところで、CloudFormationでロールを作成していきます。

## ◎ 設定項目

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html

- **RoleName**: 任意のロール名を指定します。
- [**AssumeRolePolicyDocument**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-assumerolepolicydocument)  
IAMロールの信頼ポリシーを定義します。
IAMロールの権限を `Principal` に移譲するための信頼ポリシーを指定します。
    - [Version](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_version.html): `2012-10-17` が現行
    - [Statement](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_statement.html): ポリシーを定義します。（配列形式)
        - [Effect](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_effect.html): 操作の許可( `Allow` )・不許可( `Deny` )を指定します。
        - [Action](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_action.html): `s3:GetObject` のように、どのAWSサービスの何の操作を対象とするのかを配列形式で指定します。
        - [Principal](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_principal.html): ポリシーを適用するIAMアイデンティティ、AWSサービスなどを指定します。
            - IAMユーザー: `"AWS": ["arn:aws:iam::AWS-account-ID:user/user-name-1"]`
            - IAMロール: `"AWS": "arn:aws:iam::AWS-account-ID:role/role-name"`
            - AWSサービス: `"Service": ["ecs.amazonaws.com"]`
- [**ManagedPolicyArns**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-managepolicyarns): 管理ポリシー(アイデンティティベースのポリシー)のARNを配列形式で指定します。
- [**Policies**](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-policies): インラインポリシー(アイデンティティベースのポリシー)を配列形式で定義します。
    - PolicyName: ポリシー名を指定します。
    - PolicyDocument
        - [Version](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_version.html): `2012-10-17` が現行
        - [Statement](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_statement.html): ポリシーを定義します。（配列形式)
            - [Effect](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_effect.html): 操作の許可( `Allow` )・不許可( `Deny` )を指定します。
            - [Action](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_action.html): `s3:GetObject` のように、どのAWSサービスの何の操作を対象とするのかを配列形式で指定します。
            - [Resource](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_resource.html): 操作対象のリソースを指定します。

## ◎ テンプレート

管理ポリシーを利用するパターンと、インラインポリシーを利用するパターン、2種類の定義を作成します。

```yml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  # 1. 管理ポリシーを利用してRoleを定義
  SampleRole01:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument: # IAMロールの信頼ポリシーの定義
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com # AWS Lambdaにロールを適用できるように設定
      ManagedPolicyArns: # 管理ポリシー(アイデンティティベースのポリシー)の指定
        - arn:aws:iam::aws:policy/TranslateFullAccess
      RoleName: sample-role-01
  
  # 2. インラインポリシーを利用してRoleを定義
  SampleRole02:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument: # IAMロールの信頼ポリシーの定義
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com # AWS Lambdaにロールを適用できるように設定
      Policies: # インラインポリシーを定義
        - PolicyName: hoge
          PolicyDocument: 
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - translate:*
                  - comprehend:DetectDominantLanguage
                  - cloudwatch:GetMetricStatistics
                  - cloudwatch:ListMetrics
                  - s3:ListAllMyBuckets
                  - s3:ListBucket
                  - s3:GetBucketLocation
                  - iam:ListRoles
                  - iam:GetRole
                Resource: '*'
      RoleName: sample-role-02
```

# ■ 参考記事
- [【初心者向け】IAMポリシー(JSON)の見方](https://blog.serverworks.co.jp/iam-policy-json)
- [AWS IAMポリシーを理解する | DevelopersIO](https://dev.classmethod.jp/articles/aws-iam-policy/)
- [IAMロール徹底理解 〜 AssumeRoleの正体 | DevelopersIO](https://dev.classmethod.jp/articles/iam-role-and-assumerole/)
- [IAM でのポリシーとアクセス許可 | aws](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html)
- [管理ポリシーとインラインポリシー | aws](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html)
- [IAM JSON ポリシーの要素のリファレンス | aws](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements.html)
- [AWS::IAM::Role | aws](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-managepolicyarns)