このアクション、ABAC ないし RBAC に対応してる?難解な IAM リファレンスに立ち向かうための地図を描いてみた

IAM のアクションが、リソースレベルのアクセス許可やタグベースの認証に対応した条件キーに対応しているかをどのように調べればよいかを調べました。

コンバンハ、千葉(幸)です。

IAM ポリシーを設計する時に、AWS サービスもしくは個々のアクションが ABAC ないし RBAC に対応しているか ASAP で調べたいなーと思ったことはないでしょうか?私はあります。

調べるためには IAM のリファレンスを見るのが(恐らく)一番手っ取り早いのですが、如何せん構成が複雑なのに加えて情報量が多く、なかなか読み解くのに難儀しました。

いろいろ図を描きながら理解を深めていったところ、最終的に以下が出来上がりました。

この図を基に、IAM ポリシーまわりについて「どのようにリファレンスで調べればいいか」を順番に見ていきましょう。

目次

ABAC と RBAC とは

まずはそもそものところを抑えておきます。ABAC RBAC はどちらも権限制御(アクセスコントロール)、認証に関するモデルを指します。前者は属性によって、後者は役割によって権限制御を行います。

これらは AWS 特有の用語ではありませんが、AWS に当てはめて考えると以下のような違いがあります。

ABAC RBAC
何に基づいたアクセス許可か 属性(Attribute) 役割(Role)
プリンシパルに紐付けるポリシー 複数のプリンシパルで単一ポリシーを共用 プリンシパルごとにポリシーを定義
アクセスコントロールの手法 タグベースの認証 リソースレベルのアクセス許可

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/introduction_attribute-based-access-control.html

ABAC

ABAC の適用イメージは以下です。複数あるプリンシパルに対して、ポリシーは共通の一つのみを定義しています。

(上記リンク先より画像引用)

各プリンシパル(ここではIAM ロール)に割り当てるポリシーのイメージは以下です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "AWSサービス:アクション名",
            "Resource": "arn:aws:AWSサービス::AWSアカウント番号:リソース種別/*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/タグキー": "${aws:PrincipalTag/タグキー}"
                }
            }
        }
    ]
}

ここで重要なのはResourceConditionです。

Resourceにおいては、一意の AWS リソースを特定するような指定の仕方はせず、リソースの種類を指定するに留めます。(場合によってはリソースの種類すら特定しない)

代わりにConditionにおいて、対象のリソースに特定のタグが付与されている場合のみアクションを許可する、という評価を実現しています。ここでの特定のタグとは、「アクションをリクエストするプリンシパルに付与されているタグと同一のもの」を指します。

上記の処理を実現する場合の条件キーと値の組み合わせの例は以下です。

条件キー
aws:ResourceTag/タグキー ${aws:PrincipalTag/タグキー}
iam:ResourceTag/タグキー ${aws:PrincipalTag/タグキー}
ec2:ResourceTag/タグキー ${aws:PrincipalTag/タグキー}

としては多くのケースにおいて${aws:PrincipalTag/タグキー}を指定することになります。

条件キーは、アクションの対象となるAWSサービスによって指定可能なものが変わります。全てのAWSサービスないしアクションにおいてこういった指定ができるわけではありません。これは後述します。こういった制御の仕方をタグベースの認証と呼びます。

RBAC

RBAC の適用イメージは以下です。プリンシパルごとにポリシーを用意しています。

適用するポリシーのイメージは以下です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "AWSサービス:アクション名",
            "Resource": "arn:aws:AWSサービス::AWSアカウント番号:リソース種別/リソースID"
        }
    ]
}

ResourceにおいてはリソースIDを指定することになります。ここの例ではリソースを一つしか定義していませんが、複数のリソースに対するアクションを許可する場合は、羅列していくことになります。こういった制御の仕方をリソースレベルのアクセス許可と呼びます。

タグベースの認証と同様に、リソースレベルのアクセス許可は全てのアクションに対して設定可能なわけではありません。どのアクションがこれらに対応しているのかを確認するには IAM リファレンスを参照する必要があります。その見方を確認していきます。

IAM リファレンスの関連性のイメージ図

冒頭の図を再掲します。

この後いくつか IAM リファレンスを参照することになりますが、いろんなページを行ったり来たりすることになるので、全体のイメージ図を描きました。

オレンジ網掛けはタグベースの認証、水色網掛けはリソースレベルのアクセス許可に関わりが深いものです。それ以外の凡例は特に決めていないので、フィーリングで読み取っていただくようお願いします。

IAM と連携する AWS のサービス ページ

まず見るのは、 IAM と連携する AWS のサービス ページです。

このページは以下の要素からなります。今回のテーマにおいて重要なのは太字にしているものですが、折角なので全体を確認していきます。

  • サービス
  • アクション
  • リソースレベルのアクセス許可 ★
  • リソースベースのポリシー
  • タグに基づく承認 ★
  • 一時的認証情報
  • サービスにリンクされたロール

ページにおいては、このようにサービスごとに各項目がマトリクス形式で表示されています。

の項目は「あり」、の項目は「なし」、黄色の項目は「あり」もしくは「なし」で、一部のリソースのみが対応しているといった制限があることを表します。

順番に確認していきます。

サービス

AWS サービス名です。リンクになっており、各サービスのドキュメントの IAM 関連のページに遷移することができます。(一部そうでないものもありますが、、)

アクション

AWS サービスにおけるアクションの有無を表します。基本的にはほぼ「あり」で、確認した限り AWS IQ アクセスリクエスト のみが「なし」になっていました。

リソースレベルのアクセス許可

RBAC との関わりが深い項目です。ポリシー内で ARN を用いてリソースを指定することができるか否かを指します。この項目が緑の「あり」になるのは、以下を満たした場合です。

  • 「AWS サービス内のリソースタイプが全て、いずれかのアクションのリソースレベルのアクセス許可の対象になっていること」

補足すると、以下のイメージです。

AWS サービスは 0 個以上のリソースタイプを持ちます。AWS サービス内のアクションは、特定のリソースタイプに対してリソースレベルのアクセス許可が可能な場合があります。2つ以上のリソースタイプに対応している場合もあれば、どのリソースタイプにも対応していないものもあります。

ここで、全てのリソースタイプが一つ以上のアクションから「リソースレベルのアクセス許可」の対象となっていることで、「AWS サービス全体としてリソースレベルのアクセス許可に対応している」という扱いになり、緑のセルで表現されます。

例えばELBを見ると、項目は黄色になっています。

ELB はv2(ALB、NLB)も含めると、以下のリソースタイプがあります。

リソースタイプ 概要
listener/app ALBのリスナー
listener-rule/app ALBのリスナーのルール
listener/net NLBのリスナー
listener-rule/net NLBのリスナーのルール
loadbalancer/app/ ALBのロードバランサー
loadbalancer/net/ NLBのロードバランサー
targetgroup ALB/NLBのターゲットグループ
listener CLBのリスナー
loadbalancer CLBのロードバランサー

ここで、リソースタイプlistener( CLB のリスナー)だけは、どのアクションからも「リソースレベルのアクセス許可」の対象とされていません。全てのリソースタイプで「リソースレベルのアクセス許可」に対応しているわけではないため、Elastic Load Balancing というサービスとしては黄色になっているというわけです。

おさらいとなりますが、このセルが緑の「あり」になっている AWS サービスにおいても、全てのアクションが「リソースレベルのアクセス許可」に対応しているわけではないという点に注意してください。

リソースベースのポリシー

いわゆる IAM ポリシーを「アイデンティティベースのポリシー」と呼ぶのに対し、リソースに設定するポリシーはリソースベースのポリシーと呼ばれます。例えば S3 のバケットポリシーや、SNS のトピックポリシー、VPC エンドポイントのエンドポイントポリシーが該当します。

以前にこんな図を書いて説明したこともありますので、興味がある方は参照してください。

タグに基づく承認

ABAC との関わりが深い項目です。冒頭で見たように、aws:ResourceTagなどの条件キーを使用して、タグベースでの認証が可能かどうかを確認できます。

例えば S3 を確認すると、黄色で「あり」となっており、注釈として以下が記載されています。

Amazon S3 はオブジェクトリソースに対してのみタグベースの認証をサポートしています。

リンク先を確認すると、以下のような書き方で「特定のタグが付与されているオブジェクトのみGetobject可能」という制御が実現できることが分かります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect":     "Allow",
      "Action":     "s3:GetObject",
      "Resource":    "arn:aws:s3:::examplebucket/*",
      "Principal":   "*",
      "Condition": {  "StringEquals": {"s3:ExistingObjectTag/security": "public" } }
    }
  ]
}

Condition部を以下のような書き方に変えれば、「自身と同じsecurityタグが付与されているオブジェクトのみGet可能」という ABAC が実現できます。

"StringEquals": {"s3:ExistingObjectTag/security": "${aws:PrincipalTag/security}" }

(ここではResouceで許可しているのが特定のバケット配下のみであるため、オブジェクトが複数のバケットに分散しているのであれば、もう少し広めに修正する必要があります。)

一時的認証情報

単純に IAM ユーザー や IAM ロールがアクションを実行するのでなく、以下のようなエンティティからアクションを実行する際に、対応しているかどうかを表します。

  • フェデレーションサインインしたユーザー
  • クロスアカウントでのロール
  • EC2 にアタッチしたロール
  • サービスが使用するロール など

こちらも基本的には「あり」になっているサービスがほぼほぼで、「なし」になっているのは、AWS Marketplace Catalog APIのみでした。

サービスにリンクされたロール

いわゆる AWS service-linked role の有無を表します。このロールを利用するのは AWS サービスの単位であることに注意してください。「EC2インスタンス」「Lambda関数」といったリソースの単位でアタッチするものとは異なります。

ふたたび ELB を例にとって確認します。

個々のリソース(ロードバランサー)に対して IAM ロールをアタッチすることはできませんが、 ELB というサービス全体で使用されるロールは存在します。過去にロードバランサーを作成したことがある方は、 IAM ロールの一覧にAWSServiceRoleForElasticLoadBalancingという名称のロールが存在することが確認できるはずです。

ELBはスケールや故障ノードの置き換えのタイミングで ENI を作成したり削除したりしますが、そういったアクションはサービスにリンクされたロールに付与された権限によって実現されています。

Elastic Load Balancing サービスにリンクされたロール

AWS のアクション、リソース、および条件キー ページ

ここまで「IAM と連携する AWS のサービス」ページの内訳を確認しました。サービス単位での傾向を掴むにはとても便利ですが、細かい部分は抑えられていません。特にセルが黄色になっているものは別のページで詳細を確認する必要があります。

各サービスのリファレンスのページに飛んでもいいのですが、より包括的に確認できるのが AWS のサービスのアクション、リソース、および条件キー ページです。

このページでは以下の3つのテーブルに関する説明と、各AWSサービスに対するリンクが記載されています。

  • アクションテーブル
  • リソースタイプテーブル
  • 条件キーテーブル

各テーブルを順番に確認していきましょい。

アクションテーブル

以下のような構成になっています。

  • アクション:アクション名です
  • 説明:アクションの説明です
  • アクセスレベル:リスト、読み取り、書き込み、アクセス許可管理、タグ付けのいずれかです
  • リソースタイプ:後述します ★
  • 条件キー:後述します ★
  • 依存アクション:複数のリソースにアクセスするアクションの場合に、追加でアクセス許可が必要になるアクションです

ここでは二つの列について詳細に確認していきます。

リソースタイプ

RBAC との関わりが深いエントリです。アクションがリソースレベルのアクセス許可に対応している場合、指定可能なリソースタイプがこの列に記載されます。いくつか注意事項があります。

  • この列が空欄のアクションは、リソースレベルのアクセス許可に対応していない
    • ポリシー内のResourcesにおいて*(すべて)を指定する必要がある
  • この列に「*(アスタリスク)」つきでリソース名が記載されている場合、「リソースレベルのアクセス許可」を行う際にそのリソースを省略できない(必須)
    • あくまで「リソースレベルのアクセス許可を行う場合」に必須
    • ポリシーにおいて"Resource": "*"という指定の仕方はできる
  • この列に「*(アスタリスク)」なしでリソース名が記載されている場合、上述のケースにおいて省略できる(オプション)
  • 一つのステートメントにおいて「必須」と「オプション」のリソースの組み合わせは可能だが、二つ以上の「オプション」を組み合わせることはできない

一つのステートメントにおいて指定されたActionResouceの組み合わせが上記を守っていない場合、Effect(Allow/Deny)は無効となり正しく機能しません。また、後述しますが、リソースレベルのアクセス許可を行う場合にはリソースを正しい ARN で指定する必要があります。

条件キー

ABAC との関わりが深いエントリです。

IAM ポリシーのステートメントで特定のアクションを指定した時に、Codotion要素として含めることができる条件キーを表します。「アクションそのもの」に紐づく場合と、「アクションとリソースタイプの組み合わせ」に紐づく場合があります。

前者の例は以下です。リソースタイプ列がブランクになっている行に条件キーが記載されています。

後者の例は以下です。アクションにおいて特定のリソースタイプを指定した場合、使用できる条件キーに差異があることがわかります。

ここでは両者を合わせてアクションに紐づく条件キーと表現します。

リソースタイプテーブル

以下のような構成になっています。

  • リソースタイプ:リソースタイプです。アクションテーブル内のリソースタイプ列のリンクはここにつながっています
  • ARN:リソースタイプのARNです。特定のリソースタイプに対してリソースレベルのアクセス許可を行う場合、このARNに則って指定する必要があります
    • リソースIDまで含めてすべて記載する必要があるわけではありません
  • 条件キー:後述します ★

条件キー

先ほどアクションテーブル内で確認したものを「アクションに紐づく条件キー」と表現しましたが、それに対してここで確認できるものは「リソースタイプに紐づく条件キー」です。

一つのステートメントにおいて以下の条件を満たす場合に、ここで記載されている条件キーを使用することができます

  • Actionにおいて当該リソースタイプに対する「リソースレベルのアクセス許可」に対応しているアクションが含まれている
  • Resourceにおいて当該リソースタイプが指定されているか、*(すべて)が指定されている

例えば Amazon EC2 Instance Connect のテーブルは以下のようになっています。

  • アクションSendSSHPublicKeyに紐づく条件キーはec2:osuser
  • リソースタイプinstanceに紐づく条件キーはaws:ResourceTag/${TagKey}ec2:ResourceTag/${TagKey}
  • アクションSendSSHPublicKeyはリソースタイプinstanceを指定した「リソースレベルのアクセス許可」に対応している

ここで、以下のような指定の仕方をすることで、「アクションを実行するプリンシパルと同じタグがついているインスタンスにのみ EC2 Instance Connect を利用して接続可能」という制御を実現できます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2-instance-connect:SendSSHPublicKey",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/Project": "${aws:PrincipalTag/Project}"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeInstances",
            "Resource": "*"
        }
    ]
}

今回のケースではResource*としても問題なくポリシーが機能しましたが、アクションテーブルにおいてリソースタイプが複数存在したり、「必須」でなく「オプション」のものがあった場合には同様の挙動を示さないことがあるかもしれません。切り分けを簡易にできるようにするため、なるべくリソースタイプのARNを指定することをおすすめします。

条件キーテーブル

以下のような構成になっています。

  • 条件キー:条件キーです。アクションテーブルやリソースタイプテーブルにおける条件キーのリンクはここにつながっています
  • 説明:条件キーの説明です
  • タイプ:条件キーのデータタイプです。データタイプにより、使用できる 条件演算子 が決定されます

このテーブルにおいて表示されるのは、上で確認した「アクションに紐づく条件キー」と「リソースタイプに紐づく条件キー」の合算です。この条件キーテーブルに載っているからといって、すべてのアクションないしリソースタイプに対して使用できるものではないことに注意してください。

また、ここに載るのは「サービスレベルの条件キー」と言えるものです。すべてのサービス、アクションで使用できる「グローバル条件キー」は含まれていません。立て付けを別のページで確認していきましょう。

AWS グローバル条件コンテキストキー ページ

AWS グローバル条件コンテキストキー ページには「すべてのアクションで使用できるグローバル条件キー」と、「一部のサービス・アクションにおいてのみ使用できるグローバル条件キー」が混在しています。

「グローバル条件キー」の定義としては、aws:プレフィックスから始まる条件キーのことを指します。それに対してiam:ec2:プレフィックスを持つ条件キーは「サービス固有の条件キー」と呼ばれます。

ここまで見てきた中で何度か取り上げたaws:ResourceTag/タグキーはグローバル条件キーです。しかし、すべての AWS サービス、アクションに対応しているわけではありません。この条件キーを使用できるかどうかは、「AWS のアクション、リソース、および条件キー」ページで確認する必要があります。

「サービス固有の条件キー」と「一部のサービス・アクションにおいてのみ使用できるグローバル条件キー」を合わせて、便宜上「サービスレベルの条件キー」と呼びます。

冒頭で見た ABAC においては、以下のようなタグの組み合わせを例にとりました。「サービスレベルの条件キー」として「リソースに付与されているタグの値」を表す条件キーに対応していれば、そのサービス・アクションは ABAC に対応しているということになります。

条件キー
aws:ResourceTag/タグキー ${aws:PrincipalTag/タグキー}
iam:ResourceTag/タグキー ${aws:PrincipalTag/タグキー}
ec2:ResourceTag/タグキー ${aws:PrincipalTag/タグキー}

上表の条件キーはすべて「アクション対象のリソースに付与されているタグの値」を表すものです。(「すべてのアクションで使用できるグローバル条件キー」では、それに該当するものが存在しません。)

そして、その条件キーの有無を手っ取り早く確認できるのが「IAM と連携する AWS のサービス」ページということになります。

少なくともこの表の段階で「なし」であればタグベースの認証に該当する条件キーはありませんし、「あり」であれば、どのリソースタイプ・およびアクションに対してどのような条件キーが使用できるかを確認すれば良いということになります。

ポリシー変数をプレースホルダーとして使用する

上記のキーの組み合わせで値として使用している${aws:PrincipalTag/タグキー}について補足しておきます。

グローバル条件キーaws:PrincipalTagにプレースホルダーテキストタグキーを付加した上で、${}で括ることでポリシー変数として扱っているという位置付けです。

IAM ポリシーエレメント: 変数およびタグ

終わりに

改めて冒頭の図を持ってきました。

この図が意味するところは理解いただけたでしょうか。改めておさらいしておくと以下のようになります。

  • ABAC においてはタグベースの認証が重要な概念である
  • RBAC においてはリソースレベルのアクセス許可が重要な概念である
  • タグベースの認証、リソースレベルのアクセス許可について大まかに確認したい場合は「IAM と連携する AWS のサービス」ページを確認する
  • 詳細に確認したい場合は「AWS のアクション、リソース、および条件キー」ページを確認する
  • aws:から始まるグローバル条件キーも、種類によっては使用できるケースが限られているため、アクションごとに確認が必要

この辺りが自分の中で腹落ちするまでだいぶ時間がかかりました。ABAC や RBAC に限らず、IAM のポリシーを設定する際のご参考にしていただければ幸いです。