【入門編】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

2021年11月にアップデートがありました

本ブログの執筆時期は2021年9月でしたが、2021年11月に評価ロジックが変更されておりましたので以下のブログで変更点等を掲載しました。詳細については是非こちらをご覧ください。

blog.serverworks.co.jp

評価ロジック

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

評価ロジックのイメージ

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

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

Organizations SCP

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

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

blog.serverworks.co.jp

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

blog.serverworks.co.jp

注意点としては、SCPの有効範囲はIAM UserとIAM Roleのみであるという点です。評価ロジックに記載されているリソースベースのポリシー等をSCPで制御することはできず、アイデンティティベースのポリシーのみ制御ができます。

※参考:サービスコントロールポリシー (SCPs) - AWS Organizations

つまりSCPを適用している場合は、「SCPで明示的な許可」かつ「アイデンティティベースのポリシーで明示的な許可」をしている操作のみが最終的な許可される権限になります。

※参考: Policy evaluation logic - AWS Identity and Access Management

AWSドキュメントより抜粋

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

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

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

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

バケットポリシーの例

IAM Permissions Boundary

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

docs.aws.amazon.com

IAM Permissions Boundary のイメージ

セッションポリシー

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

docs.aws.amazon.com

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

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

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

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

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

山﨑 翔平 (Shohei Yamasaki) 記事一覧はコチラ

2019/12〜2023/2までクラウドインテグレーション部でお客様のAWS導入支援を行っていました。現在はIE(インターナルエデュケーション)課にて採用周りのお手伝いや新卒/中途オンボーディングの業務をしています。2023 Japan AWS Top Engineers/2023 Japan AWS Ambassadors