【入門編】AWSにおけるアクセスポリシーの評価ロジックを整理してみる

記事タイトルとURLをコピーする

CI部1課に異動しました山﨑です。

AWSにおけるアクセスポリシーの評価ロジックについて簡単に整理したいと思います。

はじめに

AWSにおいて認証・認可(権限の付与)を司るサービスと言えば IAM(Identity and Access Management)が真っ先に思い浮かびます。例えば IAMのIAM Policyではポリシーステートメントに具体的に許可したい操作、拒否したい操作を記述して認可(権限の付与)を行い、IAM Roleに関連付けたりIAM Userに関連付けたりしてポリシーを適用します。しかしながら、こんなシーンに遭遇した方がいらっしゃるのではないでしょうか

「AWS Config の設定でAWS Configを操作する権限を持ったIAM RoleをセットしたしこれでログをS3バケットに書き込める!」

「うわ〜、S3のバケットポリシー書いてなかったから書き込み失敗してるやん。。。」

認証・認可=IAM というイメージが強いためバケットポリシーなどを忘れてしまっていることが多いのではないかと思います。そこで今回はAWSがどのような評価ロジックでリソース操作の許可/拒否を決定しているのかを整理したいと思います。基本的には以下のAWSドキュメントを参考にしています。

docs.aws.amazon.com

評価ロジック

まず結論ですが、AWSでは以下の評価ロジックでリソース操作の許可/拒否を決定しています。

f:id:swx-yamasaki:20210902152519p:plain
評価ロジックのイメージ

拒否の評価(明示的な拒否)

まずAWSの仕様では全てのリクエストは拒否の扱いになります。これは暗黙的な拒否と呼ばれます。AWSでは暗黙的な拒否としてリクエストを処理する前にイメージ図のOrganizations SCP以降のポリシーを全てチェックします。チェックする中でポリシーでDenyされている権限があればその権限を制限します。このようにポリシー内で明示的にDenyすることを明示的な拒否と呼びます。明示的な拒否がなければ、次のポリシー評価に移ります。

Organizations SCP

拒否の評価(明示的な拒否)の次はOrganizations SCPの評価です。SCPとはマルチアカウント管理でとても便利なサービスとして知られるAWS Organizations で利用可能なService Control Policy を示しています。SCPではOrganizations配下の各OU(Organizational Unit)に対する権限を規定します。これによりOUはSCPで規定した権限以上のことは何もできなくなります。AWSのIAMのベストプラクティス (最小権限の許可)にしたがって細かい制御を行うのは運用負荷が高いので、SCPでは許可したいことではなく、拒否させたいことを規定する方が良いと思います。

SCPについては以下のブログをご参照ください

blog.serverworks.co.jp

Organizations については以下のブログをご参照ください

blog.serverworks.co.jp

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

次はリソースベースのポリシーの評価です。これはAWSリソースに対して直接規定するポリシーで例えば以下のAWSサービスにポリシーを適用することができます。

S3を例に挙げます。S3ではリソースベースのポリシーはバケットポリシーと呼ばれます。バケットポリシーでは例えばどのようなPrincipalに対して、どういった操作を許可/拒否するのかを規定することができます。

以下の図ではIAMユーザー(yamasaki)に対してProductionというS3バケットにおけるGetObject/PutObjectの操作を許可しています。

f:id:swx-yamasaki:20210903092945p:plain
バケットポリシーの例

IAM Permissions Boundary

次はIAM Permissions Boundaryの評価です。IAM Permissions Boundary はアイデンティティベースのポリシーで規定可能な権限の範囲を設定します。これによりアイデンティティベースのポリシーでIAM Permissions Boundaryで規定した権限範囲を逸脱した操作を許可したとしてもその操作はできなくなります。つまり、IAM Permissions Boundary と アイデンティティベースのポリシー で双方に許可されている権限のみが操作可能になります。

docs.aws.amazon.com

f:id:swx-yamasaki:20210903181902p:plain
IAM Permissions Boundary のイメージ

セッションポリシー

次はセッションポリシーの評価です。セッションポリシーは、AssumeRole の操作中にオプションで渡すことができるアクセス許可ポリシーです。これにより、そのセッションに対するロールの権限にさらに制限を加えることができます。これだけだとちょっとよく分からないのでSwitch Roleをユースケースとして用いて説明したいと思います。以降ご紹介するサンプルリクエスト等はAWSドキュメントを参考にしています。

docs.aws.amazon.com

ユースケース:クロスアカウントのSwitch Role

f:id:swx-yamasaki:20210903210441p:plain
Switch Roleのイメージ

①AssumeRole API Request

まずはAWS Security Token Service (AWS STS) に対してAssumeRole API Requestを行います。AssumeRole API Request を実行するためにはIAM Roleのメニュータブ中にある「信頼関係」のメニューの中にある「信頼されたエンティティ」の設定でAccount AのAccount IDを指定する必要があります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::111122223333:root"
        ]
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}

信頼されたエンティティはリソースベースのポリシーに分類されるポリシーで、AssumeRole API Request の実施を許可するPrincipalを指定するポリシーです。今回はリクエスト主体がIAM Userですが、EC2に対してAssumeRole API Request の実施を許可することでEC2から別のリソースを操作したい場合は以下のような信頼されたエンティティを記述します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "ec2.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

話が少し脱線してしまいましたが、AssumeRole API Requestの実際のサンプルリクエストは以下をご確認ください

https://sts.amazonaws.com/
?Version=2011-06-15
&Action=AssumeRole
&RoleSessionName=testAR
&RoleArn=arn:aws:iam::123456789012:role/demo
&PolicyArns.member.1.arn=arn:aws:iam::123456789012:policy/demopolicy1
&PolicyArns.member.2.arn=arn:aws:iam::123456789012:policy/demopolicy2
&Policy={"Version":"2012-10-17","Statement":[{"Sid":"Stmt1",
"Effect":"Allow","Action":"s3:","Resource":""}]}
&DurationSeconds=3600
&Tags.member.1.Key=Project
&Tags.member.1.Value=Pegasus
&Tags.member.2.Key=Team
&Tags.member.2.Value=Engineering
&Tags.member.3.Key=Cost-Center
&Tags.member.3.Value=12345
&TransitiveTagKeys.member.1=Project
&TransitiveTagKeys.member.2=Cost-Center
&ExternalId=123ABC
&SourceIdentity=Alice
&AUTHPARAMS

サンプルリクエスト中に記載されているRoleArnがSwitch Roleで利用するためにAccount Bで作成したIAM Roleです。

またPolicyArns.member.1.arn / PolicyArns.member.2.arn / Policy と記載されているポリシーがありますが、これがセッションポリシーです。しかし、明示的にセッションポリシーを指定するケースは稀ですのであまり気にしなくて良いと思います。

②temporary security credentials

AssumeRole API Request のレスポンスは以下のような形式で帰ってきます。

<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
  <AssumeRoleResult>
  <SourceIdentity>Alice</SourceIdentity>
    <AssumedRoleUser>
      <Arn>arn:aws:sts::123456789012:assumed-role/demo/TestAR</Arn>
      <AssumedRoleId>ARO123EXAMPLE123:TestAR</AssumedRoleId>
    </AssumedRoleUser>
    <Credentials>
      <AccessKeyId>ASIAIOSFODNN7EXAMPLE</AccessKeyId>
      <SecretAccessKey>wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY</SecretAccessKey>
      <SessionToken>
       AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQW
       LWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGd
       QrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU
       9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz
       +scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA==
      </SessionToken>
      <Expiration>2019-11-09T13:34:41Z</Expiration>
    </Credentials>
    <PackedPolicySize>6</PackedPolicySize>
  </AssumeRoleResult>
  <ResponseMetadata>
    <RequestId>c6104cbe-af31-11e0-8154-cbc7ccf896c7</RequestId>
  </ResponseMetadata>
</AssumeRoleResponse>

レスポンス中に記載されているCredentialsが一時的な認証情報と呼ばれているものです。

このCredentialsで許可されている権限はSwitch Role用のIAM Roleで許可している権限と同じです。

③IAM Roleの権限でSwitch Role

②で取得したCredentialsを使ってAccount AからAccount BにSwitch Roleします。Switch Role後にAccount Bで操作した場合、CloudTrailのイベントログを確認するとuserIdentityのarnはIAMユーザーではなくSTSになっています。またSTS自体はグローバルサービスであるためawsRegionはus-east-1(バージニア北部)になっています。

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROAZY5ZLIUT4BYFZ5SMS:yamasaki@example.com",
        "arn": "arn:aws:sts::123456789123:assumed-role/SwitchRoleRO/yamasaki@example.com",
        "accountId": "123456789123"
    },
    "eventTime": "2021-08-18T07:01:02Z",
    "eventSource": "signin.amazonaws.com",
    "eventName": "SwitchRole",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "122.xx.xx.xxx",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
    "requestParameters": null,
    "responseElements": {
        "SwitchRole": "Success"
    },
    "additionalEventData": {
        "SwitchFrom": "arn:aws:iam::111122223333:user/yamasaki@example.com",
        "RedirectTo": "https://console.aws.amazon.com/organizations/v2/home?region=ap-northeast-1#"
    },
    "eventID": "323c2383-09e0-4146-bf44-c0f1cc99b10b",
    "readOnly": false,
    "eventType": "AwsConsoleSignIn",
    "managementEvent": true,
    "

アイデンティティベースのポリシー

そして最後にアイデンティティベースのポリシーを評価します。これはリソースベースのポリシーとは異なりIAMユーザーやIAMグループ、IAMロールといったいわゆるIAMアイデンティティと呼ばれるエンティティに記述するポリシーです。これが皆さんがよく聞き馴染みのあるIAMポリシーと呼ばれるものです。

IAM ポリシーの見方や書き方については以下のブログをご参照ください

blog.serverworks.co.jp

まとめ

AWSドキュメントではよく以下のようなイメージ図が出てきます。

※参考: Policy evaluation logic - AWS Identity and Access Management
f:id:swx-yamasaki:20210904103915p:plain
AWSドキュメントより抜粋

図中の網掛けになっている部分が実際に許可される権限というイメージ図ですが、今回のブログを執筆する中で個人的には以下の図のようなイメージを持ちました。

様々なポリシーがありますが、最終的には全てのポリシーで明示的に許可された権限のみが付与されるようなイメージです。

f:id:swx-yamasaki:20210904104807p:plain

では最後に冒頭の「はじめに」でご紹介したシーンを振り返ってみます。

「AWS Config の設定でAWS Configを操作する権限を持ったIAM RoleをセットしたしこれでログをS3バケットに書き込める!」

「うわ〜、S3のバケットポリシー書いてなかったから書き込み失敗してるやん。。。」

これはAWSにおけるアクセスポリシーの評価ロジックに照らし合わせた場合、考える順序が逆であることが分かります。本来であればバケットポリシーから考えて次にIAM Roleのポリシーを考えるというのが正しい順序ということになります。

私自身、まだまだこの評価ロジックの理解が浸透しているとは言えないので何度も読み返して理解を深めていきたいと思います。