初学者向けIAMざっくり要点解説

## はじめに
AWSの構築や技術支援に携わらせていただいている中で、よく見かける「サービスにアクセスできない」「処理がエラーになった」というトラブルの原因は、TCP/IPネットワークよりも権限設定のことが多いように感じます。
権限設定(IAM)は頻出なのに意外と最初の理解が難しい、かつ構成図や通信要件一覧といった成果物で詳細を整理されるネットワークに比べると権限の関係性はさほど整然と可視化されない、という状況が影響しているのではないかと思います。（主観）

「意外と難しい」への対策として、AWS資格とりたてでこれから構築に臨む方向けに、AWSを利用するうえでIAMで必ず理解すべきと個人的に思うところをビジュアライズのうえ記述してみます。

## ポリシー２種類の違いはおさえる
AWSアカウントを操作していると「IAMポリシー」「バケットポリシー」等いろいろなポリシーが登場しますが、以下の２種類に大別されると理解しておくと腹落ちしやすいと思います。（逆にここを理解していないと、IAMロールの設定がよくわからない、バケットポリシーの使い所がピンとこない、といった混乱の元になります。）
1. アイデンティティベースポリシー
1. リソースベースポリシー

(参考）[アイデンティティベースおよびリソースベースのポリシー　](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_identity-vs-resource.html)

上記公式ページにも色々と記載されていますが、ざっくり理解するなら、それぞれ以下を定義するものと考えれば良いと思います。
1. 「⚪︎⚪︎が**何へ**アクセスするか(能動態))」　⚪︎⚪︎＝IAMユーザー、グループ、ロール
1. 「⚪︎⚪︎が**何から**アクセスを受けるか(受動態)」　⚪︎⚪︎＝ [IAM と連携するサービス](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html#all_svcs)の表にて「リソースベースのポリシー」が「はい」のサービスのリソース

![iam01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733359/aab32cb8-b7b5-6b27-ef73-913933444cb4.jpeg)


## ポリシー２種類を利用する代表例　
### IAMロールのリソースベースポリシーとアイデンティティベースポリシーを利用するAssumeRole
IAMロールは前述のアイデンティティベースポリシー、リソースベースポリシーいずれも利用可能なので、
- IAMロールの**リソースベースポリシー**である`信頼関係`で「IAMロールが他サービスからAssumeRoleを受ける」
- IAMロールにアタッチされた**アイデンティティベースポリシー**である`IAMポリシー`で「IAMロールが他サービスへアクセスする」

これらを定義することで、IAMユーザーが職務権限を取得するスイッチロールや、IAMロールを媒介としたサービス間連携を実現可能です。

![iam02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733359/e6ae4b97-4af8-b38e-2cae-e5adf4b570a7.jpeg)


## その他リソースベースポリシーを利用する代表例
### リソースベースポリシーを利用するクロスアカウントアクセス
「リソースベースポリシーがIAMロールで活用されることはわかったが、それ以外の場面では使い所があるのか？」という点については、上図で記載したS3バケットのリソースベースポリシーである`バケットポリシー`を例に見ていきます。
結論、「クロスアカウントアクセス」の場合、アクセスを受けるリソースのリソースベースポリシー設定は必須となります。

![iam03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733359/32f26e10-51e0-6624-c3a4-bf1540ad8944.jpeg)

#### 同一アカウント内アクセスにおけるリソースベースポリシーの扱い
たとえば、Role Bがアクセスするバケットが同一アカウント「Account 1」内のBucket Cであれば`バケットポリシー`はあってもなくても構いません。むしろ、以下の観点から極力使わないほうがよいと考えます。
- バケットポリシーの文字数制限：仮にRole BとRole Cからのアクセスをバケットポリシー側に定義すると、以下イメージのようにIAMポリシーで各々定義されていたはずのものがバケットポリシーに一挙集約されることになり、バケットポリシーのサイズ制限(2024月3月現在、20KB)を圧迫することになります。
- 影響範囲：仮にRole Bの権限に変更を加えたい場合、IAMポリシーPolicyForRoleBであれば定義変更して影響あるのはアタッチしているRole Bのみです。一方、Bucket CのバケットポリシーであればそこにRole Cに関する定義も含まれており影響可能性が広がるため、オペミスの防止策が追加で必要となる・変更承認のハードルがあがる、といった運用の煩雑さにつながる可能性があります。

##### IAMポリシーをバケットポリシーに集約するケースの定義イメージ
```json:IAMポリシーPolicyForRoleB
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PolicyForRoleB",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::arn:aws:s3:::EXAMPLE-BUCKET/prefixB/*"
        }
    ]
}
```
```json:IAMポリシーPolicyForRoleC
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PolicyForRoleC",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::arn:aws:s3:::EXAMPLE-BUCKET/prefixC/*"
        }
    ]
}
```
↓
```json:Bucket Cのバケットポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PolicyForRoleB",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:role/RoleB"
            },
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::EXAMPLE-BUCKET/prefixB/*",
        },
        {
            "Sid": "PolicyForRoleC",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:role/RoleC"
            },
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::EXAMPLE-BUCKET/prefixC/*",
        }
    ]
}
```

#### クロスアカウントアクセスにおけるリソースベースポリシーの扱い
一方で、Role Bのアクセスするバケットが他アカウント「Account 2」内のBucket Dであれば、Bucket D側の`バケットポリシー`は設定必須となります。バケットポリシーのPrincipalに「Account 1」のアクセス元であるRole Bを指定します。

##### 補足1.S3バケットクロスアカウントアクセスにおけるKMSキーアクセス
S3バケットへのクロスアカウントアクセスの際はKMSキーへのクロスアカウントアクセスも発生することが多いです。Bucket Dを「Account 2」にあるCMKで暗号化している場合、そのCMKのキーポリシーのPrincipalにも「Account 1」のアクセス元であるRole Bを指定する必要があります。なお、キーポリシーをカスタム設定できるのはカスタマー管理キーのみなので、クロスアカウントアクセスの要否を見越してキー種類の選択から注意しておく必要があります。

(参考) [カスタマーキーと AWS キー](https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/concepts.html#key-mgmt)

##### 補足2.リソースベースポリシーがサポートされていないサービスへのクロスアカウントアクセス
今回のケースではS3でリソースベースポリシーがサポートされており`バケットポリシー`が使えますが、リソースベースポリシーがサポートされていないサービスもあります。そのようなサービスへのクロスアカウントアクセスが発生するケースでは、「Account 2」にIAMロールを媒介として作成し、`信頼関係`のPrincipalに「Account 1」のアクセス元を指定することになります。

(参考)　[IAM でのクロスアカウントのリソースへのアクセス](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies-cross-account-resource-access.html)


## おわりに
総括すると、IAM実装においては以下を原則として考えておけばよいものと思います。
1. まずはアイデンティティベースポリシーで権限設定する
1. 1で実装できない権限(AssumeRole、クロスアカウントアクセス)はリソースベースポリシーで設定する

IAMはAWSを利用するうえで避けて通れないサービスであり、セキュアなシステムを構築するうえでしっかりおさえておくべきと感じます。少しでもどなたかのご参考になれば幸いです。