AWS Storage Vol5|S3 Access Grants×IAM Identity Center

目次

1. この記事について

fig01: S3大規模アクセス管理 全体像 (IAMポリシー/バケットポリシー → S3 Access Points → S3 Access Grants → Storage Browser のスケーリング階層)
fig01: S3大規模アクセス管理 全体像 (IAMポリシー/バケットポリシー → S3 Access Points → S3 Access Grants → Storage Browser のスケーリング階層)
本記事で解決する課題

  • IAMポリシー(最大5KB)/バケットポリシー(最大20KB)への手動記述がスケールせず、データセット・主体が増えるたびにポリシー管理が破綻する
  • 数百〜数千のデータセットを部門・アプリ・外部パートナーなど多主体へ動的にアクセス許可する仕組みをどう設計するか
  • 企業ディレクトリ(IAM Identity Center)ユーザーによる代理アクセスと、S3アクセス監査(CloudTrail)をエンドユーザー単位で一元化する方法
本記事の主要トピック

  • S3 Access Grants(Instance / Location / Grant / GetDataAccessによるcredentials vending)の本番Terraform構築
  • IAM Identity Center trusted identity propagationによる企業ディレクトリユーザーの直接アクセスと監査簡素化
  • Storage Browser for S3(AWS Amplify React OSSコンポーネント)によるセルフサービスアクセスUI

1-1. 本記事のゴール

本記事を読み終えた時点で、読者は次の状態に到達します。S3 Access Grantsを使い、prefix/bucket/object単位のアクセス権限をIAM principalと企業ディレクトリユーザーの双方へ動的に付与できます。IAM Identity Center trusted identity propagationを統合し、エンドユーザーがIAMロールを経由せず直接S3へアクセスしつつ、CloudTrailにエンドユーザーIDが直接記録される監査体制を構築できます。さらにStorage Browser for S3を使い、エンドユーザー自身がブラウザ上でデータへセルフサービスアクセスできるUIを提供できます。これらすべてをTerraformでコード管理された本番構成として実装できる状態がゴールです。

1-2. 読者像

大規模なS3データレイク、または多数のデータセットを部門・社内アプリケーション・外部パートナーといった多主体へ公開しており、バケットポリシー(最大20KB)やIAMポリシー(最大5KB)の肥大化・アカウントあたりのIAM principal数上限に直面しているデータプラットフォームエンジニア・セキュリティエンジニアを想定します。Vol1「S3/EFS/FSx/Storage Gateway基礎」・Vol2「S3 Advanced運用」でS3の基本〜応用機能を習得済みで、次段階として大規模組織向けのアクセス管理設計に取り組む読者を対象とする内容です。

1-3. なぜ今これを書くか

Amazon S3 Access Grantsは2023年11月にGA(一般提供開始)し、その後2024年4月・2025年10月と対応リージョンが段階的に拡大してきた機能です。S3のアクセス制御は長年「IAMポリシー・バケットポリシーへの手動記述」が基本でしたが、Access GrantsとIAM Identity Center trusted identity propagationの組み合わせにより、「企業ディレクトリのアイデンティティを起点にS3権限を動的付与する」設計へ移行できるようになりました。Storage Browser for S3の登場で、エンドユーザー向けのセルフサービスUIもOSSコンポーネントとして提供可能になっています。本シリーズVol1-4ではS3の基礎からAdvanced運用(Lifecycle/Object Lambda/CRR/Vectors/Tables/Backup)、FSx/EBSの詳細までを扱ってきましたが、「大規模・多主体アクセス管理」は未着手の領域でした。本Vol5でこの空白を埋めます。

なお本記事の執筆にあたり、S3 Access GrantsおよびStorage Browser for S3は2026年7月時点でAsia Pacific (Tokyo)リージョン(ap-northeast-1)において利用可能であることをAWS公式ドキュメント(S3エンドポイント一覧のs3-control/s3-accesspointエンドポイントおよびIAM Identity Centerのリージョン対応表)で確認しています。

1-4. 本記事のスコープ外(重複回避)

以下はシリーズ内の既存記事、または本記事の対象外として扱います。

  • S3 Access Pointの基礎実装(aws_s3_access_pointの作成・Supporting Access Pointとしての利用)は、Vol2「S3 Advanced運用」§4「S3 Object Lambda本番運用」で実装レベルまで解説済みです。本記事ではAccess Pointの基礎を再解説せず、Vol2 §4へクロスリンクで委譲します。本記事における「Access Points」は、あくまで「IAMポリシー/バケットポリシー」と「S3 Access Grants」の間に位置する中間段階(数千AP/region、APごとに独立したポリシーを持てる)という文脈でのみ扱います。
  • EFS Access Points(POSIX UID/GIDベースのアクセス制御)はVol1 §3-4で解説済みの別サービスです。名称が似ていますが本記事のS3 Access Points/Access Grantsとは無関係であり、混同しないよう注意してください。
  • IAM Identity Centerそのものの初期セットアップ手順(組織全体でのインスタンス作成・ディレクトリ連携)は本記事のスコープ外とし、既に有効化済みであることを前提とします。

本記事のスコープは、シリーズVol1-4の内容を踏まえ、重複を避けるように定めています。S3 Access Grants・Storage Browser、およびS3文脈でのIAM Identity Center統合は、本シリーズでこれまで扱ってこなかった領域です。

読み進め方としては、まず §3 でS3のアクセス制御手法全体を俯瞰し、それぞれの位置づけを整理します。そのうえで §4 でS3 Access Grantsの本番構築、§5 でIAM Identity Center統合による企業ディレクトリユーザーの直接アクセス、§6 でStorage Browserによるセルフサービスアクセスへと、段階的に実装を進めていきます。自身の環境に近い課題を扱う節から読んでも理解できる構成としています。

前作: AWS Storage本番運用 Vol4 を読む


2. 前提・環境・準備

fig02: 環境構成図 (S3バケット + Access Grants instance + IAM Identity Center + Storage Browser React app)
fig02: 環境構成図 (S3バケット + Access Grants instance + IAM Identity Center + Storage Browser React app)

2-1. 前提環境

本記事のハンズオンを進めるにあたり、以下の環境・権限を前提とします。

  • AWSアカウント: S3 Access Grants / S3 Control API / IAM Identity Center / CloudTrailの操作権限を持つIAMロールでの作業を想定します。
  • IAM Identity Center: 事前に組織インスタンスとして有効化済みであること。trusted identity propagationはIAM Identity Center有効化が前提条件のため、未有効化の場合は本記事の§5着手前に有効化しておく必要があります。
  • AWS CLI: v2.15以降(Access Grants関連APIの安定サポートのため)。
  • Terraform: v1.5以降を推奨します。
  • hashicorp/awsプロバイダー: v5.27.0以降が必須aws_s3control_access_grants_instance / aws_s3control_access_grants_location / aws_s3control_access_grantの3リソースは、terraform-provider-aws v5.27.0のリリースノート(GitHub Releases「FEATURES」欄にNew Resource: aws_s3control_access_grants_instanceほか2件)で新規追加されたことを公式確認しています。v5.27.0未満では本記事のTerraformコードは適用できません(リソースタイプ未定義エラーとなります)。
terraform {
  required_providers {
 aws = {
source  = "hashicorp/aws"
version = ">= 5.27.0"
 }
  }
}
  • リージョン: 本記事はAsia Pacific (Tokyo) ap-northeast-1を前提とします。S3 Access GrantsおよびStorage Browser for S3(内部的にS3 Control API / STS AssumeRoleを呼び出す)は、AWS公式のS3エンドポイント一覧(s3-control.ap-northeast-1.amazonaws.com / s3-accesspoint.ap-northeast-1.amazonaws.com)およびIAM Identity Centerのリージョン対応から、東京リージョンで利用可能であることを確認しています。

作業するIAM principal(TerraformのAssumeRole先ロール等)には、最低限以下のアクションを含むIAMポリシーを付与しておきます。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "S3AccessGrantsAdmin",
"Effect": "Allow",
"Action": [
  "s3:CreateAccessGrantsInstance",
  "s3:CreateAccessGrantsLocation",
  "s3:CreateAccessGrant",
  "s3:GetAccessGrantsInstance",
  "s3:GetAccessGrantsLocation",
  "s3:GetAccessGrant",
  "s3:ListAccessGrants",
  "s3:AssociateAccessGrantsIdentityCenter",
  "s3:GetDataAccess"
],
"Resource": "*"
 },
 {
"Sid": "IdentityCenterReadOnly",
"Effect": "Allow",
"Action": [
  "sso:DescribeInstance",
  "identitystore:ListUsers",
  "identitystore:ListGroups"
],
"Resource": "*"
 }
  ]
}

上記は最小権限の出発点であり、本番運用ではリソース単位(Resource)を実際のAccess Grants instance ARN・Identity Store ARNへ絞り込んでください。

2-2. 使用技術スタック

技術要素役割備考
S3 Access Grantsprefix/bucket/object単位のアクセス権限を動的付与するS3ネイティブ機能Instance/Location/Grantの3階層構造。GA: 2023年11月
IAM Identity Center企業ディレクトリ(Active Directory等)ユーザーの集中管理・trusted identity propagation東京リージョン対応済み
Storage Browser for S3エンドユーザー向けセルフサービスアクセスUI(OSS)AWS Amplify UI for React上で提供。LIST/GET/PUT/COPY/UPLOAD/DELETEに対応
Terraform (hashicorp/aws)Access Grants関連リソースのコード管理v5.27.0以降必須
AWS CLI / SDKAccess Grants instance/location/grant操作、credentials vending動作確認v2.15以降推奨

Storage Browser for S3はS3 Glacier Flexible Retrieval・S3 Glacier Deep Archive・S3 Intelligent-Tiering Archive/Deep Archiveアクセス階層のオブジェクトには非対応である点に注意してください。本記事のハンズオンではStandardストレージクラスのオブジェクトを対象とします。

hashicorp/awsプロバイダーのバージョン固定は本記事において特に重要です。S3 Access Grants関連のTerraformリソースは比較的新しく追加された機能であり、社内で共有のTerraformモジュール/CI環境が古いプロバイダーバージョンにピン留めされている場合、terraform planの時点で「Invalid resource type」エラーとなります。本記事のコード例を適用する前に、既存のTerraform環境のプロバイダーバージョン制約を確認し、必要であればterraform init -upgradeでv5.27.0以降へ更新しておいてください。

2-3. ゴール状態の定義

本記事のハンズオンでは、以下の到達状態を定義しゴールとします。

  1. S3 Access Grants instanceが作成され、IAM Identity Centerインスタンスと関連付けられている状態
  2. S3 Access Grants locationとして対象バケット(またはprefix)が登録されている状態
  3. IAM principal・IAM Identity Centerユーザー(またはグループ)の双方に対してgrantが付与され、GetDataAccess APIで一時的な認証情報(credentials vending)を取得できる状態
  4. IAM Identity Center trusted identity propagationが有効化され、企業ディレクトリユーザーがIAMロールを経由せず直接S3データへアクセスでき、CloudTrailログにエンドユーザーIDが直接記録される状態
  5. Storage Browser for S3(React/Amplifyアプリケーション)からエンドユーザーが自身に許可されたデータのみを閲覧・アップロード・ダウンロードできる状態

§4以降でこれらを段階的にTerraformで構築し、各段階の動作確認手順を示す。各節と到達状態の対応は以下の通り。

到達状態前提
§4 S3 Access Grants本番構築上記1〜3(Instance/Location/Grant/credentials vending)2-1のIAMポリシー・hashicorp/aws v5.27.0以降
§5 IAM Identity Center統合上記4(trusted identity propagation・CloudTrail監査)IAM Identity Center有効化済み(前提)
§6 Storage Browser for S3上記5(セルフサービスUI)§4完了(Access Grants instance稼働中)

いずれの節も、前の節で構築したリソースに依存する積み上げ構成です。途中の節から着手する場合は、該当する前提リソースを別途用意してください。

着手前チェックリスト

  • IAM Identity Centerが組織インスタンスとして有効化されているか(AWS Organizations管理アカウントまたは委任管理者アカウントで確認)
  • hashicorp/awsプロバイダーがv5.27.0以降にピン留め・更新されているか(terraform versionおよび.terraform.lock.hclで確認)
  • 作業ロールに2-1のIAMポリシー相当の権限が付与されているか
  • 対象リージョンをap-northeast-1に統一しているか(Access Grants instanceはS3データと同一リージョンである必要があります)

上記4点のいずれかが未整備の場合、§4以降のTerraform適用時にエラーとなるため、必ず本節の内容を満たしてから次節へ進んでください。

なお、S3 Access Grants instanceはアカウント・リージョンにつき1つのみ作成可能という制約があります。既に他用途でinstanceを作成済みの場合は、新規作成ではなく既存instanceへのlocation追加で対応する設計に切り替える必要があります(§4で詳述)。

この制約はTerraformコードのimport設計にも影響します。既存環境がある読者は、§4着手前にaws s3control get-access-grants-instance --account-id <ACCOUNT_ID>を実行し、instanceが既に存在するかどうかを確認しておいてください。既存instanceがある場合は、§4のコード例をそのままterraform applyせず、terraform importで既存instanceを取り込んでからlocation/grantを追加する手順に読み替える必要があります。

以上が本記事全体を通じた前提・環境・準備です。§3以降では、これらの前提の上でS3アクセス制御のスケーリング段階を解説し、Access Grantsの本番構築へ進みます。


3. S3アクセス制御のスケーリング段階 — なぜAccess Grantsか

S3の大規模データレイクでは、部門・アプリケーション・外部パートナーなど多数の主体に対して、prefix単位・object単位のアクセス権を随時発行する必要が生じます。AWSはこの課題に対して単一の万能解を提示するのではなく、規模に応じた4段階の選択肢を用意しています。本節ではその段階を順に整理し、最終段階としてなぜS3 Access Grantsが必要になるのかを明らかにします。

段階手法主な制約適合規模
1IAMポリシー/バケットポリシー手動管理バケットポリシー20KB上限・IAMポリシー5KB前後の実務上限主体×prefixの組み合わせが少数(数十以内)
2S3 Access PointsAccess Point自体の作成・削除という運用オーバーヘッド数百〜数千のAccess Point(各20KBポリシー)を分離管理できる規模
3IAM session broker(自前構築)ブローカーの可用性・監査ログを自前実装する必要Access Point上限を超えるが、マネージドサービスを避けたい場合
4S3 Access GrantsS3 Access Grants instanceはリージョンあたり1個数千〜数万の主体×prefixを、ポリシー編集なしで動的管理したい規模

3-1. 第1段階: IAMポリシー/バケットポリシー手動管理の限界

バケットポリシーには20KBのサイズ上限があり、IAMポリシーもインライン・マネージドいずれも数KB程度で実務上の上限に達します。主体(ユーザー・アプリケーション)とprefixの組み合わせが増えるほど、ポリシーステートメントは線形に増加し、やがて上限に到達します。さらに、ポリシーを1件更新するたびに巨大なJSONドキュメント全体をレビューする必要があり、最小権限の原則を維持する運用コストが跳ね上がります。

3-2. 第2段階: S3 Access Points — 数千アクセスポイントへの分散(中間段階)

Access Pointそのものの作成方法・VPC制限付きアクセスといった基礎実装は、本シリーズStorage本番運用 Vol2 §4「S3 Object Lambda本番運用」でSupporting Access Pointとして実装済みのため、本節では再解説しません。

ここではAccess Pointを「大規模アクセス管理のスケーリング段階における中間解」として位置づけます。1つのバケットに対して数千のAccess Pointを作成でき、各Access Pointは独自に最大20KBのポリシーを持てるため、主体ごとにAccess Pointを分離すればバケットポリシー1本あたりのサイズ制限を回避できます。ただし、Access Point自体もリージョンあたりの上限数(引き上げ申請可能)と、Access Pointの作成・削除・ポリシー更新という運用オーバーヘッドを抱えており、数百〜数千の主体を相手にする場合は依然として管理コストが高止まりします。

3-3. 第3段階: IAM session brokerという自前ソリューション

Access Pointの上限にも収まらない規模になると、多くの組織は「STS AssumeRoleを呼び出し、リクエストごとにスコープを絞ったポリシーを動的生成して一時クレデンシャルを発行するブローカーサービス」を自前で構築してきました。このパターンは動作しますが、次のコストを伴います。

  • ブローカー自体の可用性・スケーラビリティ・監査ログを自前で担保する必要がある
  • 権限マッピングのロジックがアプリケーションコードに埋め込まれ、IAMの外側で管理される「隠れた認可レイヤー」になる
  • 企業ディレクトリ(IdP)のユーザー・グループとの連携は個別実装が必要になる

3-4. 第4段階: S3 Access Grants — アイデンティティ起点の動的アクセス制御

S3 Access Grantsは、上記の自前ブローカーパターンをAWSのマネージドサービスとして提供するものです。IAM principal、あるいはIAM Identity Center経由の企業ディレクトリuser/groupに対して、prefix単位・object単位のREAD/WRITE/READWRITE権限を「grant」として事前登録しておけば、アプリケーションはGetDataAccess API 1回の呼び出しでスコープの絞られた一時クレデンシャルを取得できます。これにより、ポリシードキュメントのサイズ上限やAccess Point数の上限を意識することなく、数千〜数万の主体×prefixの組み合わせを一元管理できます。IAM Identity Center統合による企業ディレクトリ直接アクセスの詳細は次節(§5)で扱います。

本節のまとめ

  • IAMポリシー/バケットポリシー → S3 Access Points → IAM session broker → S3 Access Grantsの順にスケール
  • S3 Access Point「基礎」実装はStorage本番運用 Vol2 §4を参照(本記事では再解説しない)
  • S3 Access Grantsは「アイデンティティ起点で動的にスコープ付き一時クレデンシャルを発行する」点がAccess Pointとの本質的な違い

4. S3 Access Grants本番構築 — Instance/Location/Grant/Credentials Vending

fig03: S3 Access Grants構成要素とcredentials vendingフロー
fig03: S3 Access Grants構成要素とcredentials vendingフロー

S3 Access Grantsは「Instance → Location → Grant → GetDataAccess」の4ステップで構成されます。本節ではこの一連の流れをTerraformとAWS CLIで本番実装します。

4-1. 構成要素の全体像

要素役割
Instancegrantを格納する論理コンテナ。AWSアカウント×リージョンごとに1個のみ作成可能
Locationバケットまたはprefixを、S3 Access Grantsが引き受ける(assume)IAMロールにマッピング
Grant特定のgrantee(IAM principalまたは企業ディレクトリuser/group)に、Location配下のスコープ(バケット/prefix/object)への READ・WRITE・READWRITE 権限を付与
GetDataAccessgranteeが呼び出すAPI。マッチするgrantがあれば、Locationに紐づくIAMロールをAssumeRoleし、スコープ限定の一時クレデンシャルを返却

Instanceの作成が起点になりますが、Instance単体ではgrantを持たないため、最低1つのLocationを登録するまでは一切のアクセスが許可されません。

4-2. Terraform: Access Grants Instanceの作成

本記事§2-1で確認した通り、aws_s3control_access_grants_instance / aws_s3control_access_grants_location / aws_s3control_access_grantはhashicorp/awsプロバイダーv5.27.0で追加されたリソースです。

resource "aws_s3control_access_grants_instance" "main" {
  # identity_center_arn は §5(IAM Identity Center統合)で追加する
  tags = {
 Environment = "production"
 ManagedBy= "terraform"
  }
}

Instanceはアカウント・リージョンにつき1個しか作成できないため、複数のワークロードから同じInstanceを共有する設計を前提にLocation/Grantを分割します。

4-3. Terraform: Locationの登録(S3 prefix/bucket単位)

LocationはバケットまたはprefixをIAMロールにマッピングします。S3 Access Grantsは、granteeへ一時クレデンシャルを発行する際にこのIAMロールをAssumeRoleします。AWSはデフォルトLocation(s3://)を1つ登録し、アカウント内の全バケットをカバーする構成を推奨しています。個別のバケットで異なるIAMロール(VPCエンドポイント制限など)を使いたい場合のみ、バケット単位・prefix単位のLocationを追加登録します。

data "aws_iam_policy_document" "access_grants_location_assume" {
  statement {
 effect  = "Allow"
 actions = ["sts:AssumeRole"]
 principals {
type  = "Service"
identifiers = ["access-grants.s3.amazonaws.com"]
 }
  }
}

resource "aws_iam_role" "access_grants_location" {
  name= "s3-access-grants-location-role"
  assume_role_policy = data.aws_iam_policy_document.access_grants_location_assume.json
}

data "aws_iam_policy_document" "access_grants_location_permissions" {
  statement {
 effect = "Allow"
 actions = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
 ]
 resources = [
"arn:aws:s3:::${var.data_lake_bucket}",
"arn:aws:s3:::${var.data_lake_bucket}/*",
 ]
  }
}

resource "aws_iam_role_policy" "access_grants_location" {
  name= "s3-access-grants-location-policy"
  role= aws_iam_role.access_grants_location.id
  policy = data.aws_iam_policy_document.access_grants_location_permissions.json
}

# デフォルトLocation: アカウント内の全バケットをカバー
resource "aws_s3control_access_grants_location" "default" {
  depends_on = [aws_s3control_access_grants_instance.main]

  iam_role_arn= aws_iam_role.access_grants_location.arn
  location_scope = "s3://"
}

複数事業部でIAMロールを分離したい場合は、location_scopeにバケット名やprefixを指定して個別のLocationを追加登録します。

resource "aws_s3control_access_grants_location" "finance_prefix" {
  depends_on = [aws_s3control_access_grants_instance.main]

  iam_role_arn= aws_iam_role.access_grants_location_finance.arn
  location_scope = "s3://${var.data_lake_bucket}/finance/"
}

4-4. Terraform: Grantの付与(IAM principal / 企業ディレクトリuser・group)

Grantはgranteeブロックで対象を指定します。grantee_typeにはIAM(IAM principal)、またはDIRECTORY_USERDIRECTORY_GROUP(IAM Identity Center経由の企業ディレクトリuser/group)を指定できます。企業ディレクトリ連携の前提となるIAM Identity Center trusted identity propagationの設定は§5で扱うため、ここではIAM principalへの付与を実装します。

# IAM principal(アプリケーションIAMロール)へのgrant: READWRITE
resource "aws_s3control_access_grant" "app_readwrite" {
  access_grants_location_id = aws_s3control_access_grants_location.default.access_grants_location_id
  permission = "READWRITE"

  access_grants_location_configuration {
 s3_sub_prefix = "datasets/app-team/*"
  }

  grantee {
 grantee_type = "IAM"
 grantee_identifier = aws_iam_role.app_team.arn
  }

  tags = {
 Team = "app-team"
  }
}

# IAM principal(分析チームIAMロール)へのgrant: READのみ
resource "aws_s3control_access_grant" "analytics_readonly" {
  access_grants_location_id = aws_s3control_access_grants_location.default.access_grants_location_id
  permission = "READ"

  access_grants_location_configuration {
 s3_sub_prefix = "datasets/*"
  }

  grantee {
 grantee_type = "IAM"
 grantee_identifier = aws_iam_role.analytics_team.arn
  }

  tags = {
 Team = "analytics-team"
  }
}

aws_s3control_access_grantaccess_grants_location_configuration.s3_sub_prefixは、Locationが登録しているスコープの配下をさらに絞り込むためのサブprefixです。デフォルトLocation(s3://)を使う場合、grant側で必ずバケット・prefix・objectのいずれかにスコープを絞り込む必要があります。

4-5. Credentials Vending — GetDataAccessによる一時クレデンシャル発行

Grantを登録した後、アプリケーションはGetDataAccess APIを呼び出すことでスコープ限定の一時クレデンシャルを取得できます。S3 Access GrantsはリクエストとGrantを照合し、マッチすればLocationに紐づくIAMロールをAssumeRoleして、Grantのスコープに限定されたクレデンシャルを返却します。

aws s3control get-data-access \
  --account-id 123456789012 \
  --target "s3://data-lake-bucket/datasets/app-team/report.parquet" \
  --permission READWRITE \
  --target-type Object

レスポンスにはAccessKeyId/SecretAccessKey/SessionToken/Expirationが含まれます。有効期限はデフォルト1時間で、15分〜12時間の範囲で調整可能です(AssumeRoleのセッション上限に準拠)。マッチするGrantが存在しない場合はAccessDeniedが返り、アプリケーション側でのポリシー個別管理は一切不要です。

4-6. Cross-account Grant

別アカウントのIAM principalにGrantを発行するには、Access Grants Instanceにリソースベースポリシーを設定し、対象アカウントからのs3:GetDataAccesss3:ListAccessGrantss3:ListAccessGrantsLocations呼び出しを許可します。

data "aws_iam_policy_document" "access_grants_instance_resource_policy" {
  statement {
 effect  = "Allow"
 actions = [
"s3:ListAccessGrants",
"s3:ListAccessGrantsLocations",
"s3:GetDataAccess",
 ]
 principals {
type  = "AWS"
identifiers = [var.consumer_account_id] # クロスアカウント許可先
 }
 resources = ["*"]
  }
}

resource "aws_s3control_access_grants_instance_resource_policy" "main" {
  policy = data.aws_iam_policy_document.access_grants_instance_resource_policy.json
}

このリソースポリシーを設定したうえで、Grant自体のgrantee_identifierに対象アカウントのIAM principal ARNを指定すれば、クロスアカウントでのcredentials vendingが成立します。データを所有するアカウント側でLocation・Grant・IAMロールを一元管理できるため、消費側アカウントごとにバケットポリシーを分散管理する必要がなくなります。

4-7. タグによるアクセス制御の粒度向上

aws_s3control_access_grantはリソースタグをサポートしており、TeamCostCenterといったタグを付与しておくと、Grant数が数百〜数千に達した際もタグベースでの棚卸し・監査が可能になります。IAMポリシーのようにタグ条件でアクセス可否を分岐させる機能ではなく、あくまで管理・可視化のためのメタデータである点に注意してください。

4-8. Limitations(本番設計での注意点)

S3 Access Grants本番構築の落とし穴

  • Instanceはアカウント×リージョンで1個のみ。マルチリージョン展開時はリージョンごとに個別のInstance/Location/Grant設計が必要
  • デフォルトLocation(s3://)を使う場合、Grant側で必ずスコープを絞り込む必要がある(Location=Grantとも無制限スコープにはできない)
  • GrantのIAMロールがS3操作(s3:GetObject等)の権限を持っていなければ、Grant自体が有効でもAccessDeniedになる(Location側IAMロールとGrantの二重チェックが必要)
  • クロスアカウントGrantはInstanceのリソースベースポリシー設定を忘れると、Grant自体が正しくてもGetDataAccessが失敗する

5. IAM Identity Center trusted identity propagation統合 — 企業ディレクトリ直接アクセス

fig04: IAM Identity Center trusted identity propagationシーケンス
fig04: IAM Identity Center trusted identity propagationシーケンス(企業ディレクトリユーザー → Storage Browser → Identity Center → Access Grants → S3・CloudTrailにエンドユーザーID直接記録)

§4ではIAM principal(IAMユーザー・ロール)へのgrant発行を実装しました。しかし実際にS3データへアクセスする主体の多くは、IAMユーザーではなく企業ディレクトリ(Active Directory・Okta・Microsoft Entra ID等)で管理されるエンドユーザーです。本節では、IAM Identity Centerのtrusted identity propagation機能を統合し、企業ディレクトリで認証済みのエンドユーザーが、IAM principalへのマッピングを介さずにS3 Access Grants経由でS3データへ直接アクセスできる仕組みをTerraformとAWS CLIで構築します。

5-1. trusted identity propagationが解決する課題

企業ディレクトリのユーザーはIAM principalではないため、従来はアプリケーション側で「ディレクトリユーザー → 固定のIAMロール」への静的マッピングを自前実装する必要がありました。この方式には次の問題があります。

  • 複数のディレクトリユーザーが同じIAMロールにマッピングされるため、CloudTrailにはマッピング先のIAMロールしか記録されず、実際に操作したエンドユーザーを追跡できない
  • マッピングテーブルをアプリケーションコード側で保守する必要があり、IAMの外側に「隠れた認可レイヤー」が生まれる(§3-3のIAM session brokerパターンと同じ課題)

IAM Identity Centerのtrusted identity propagationは、ディレクトリユーザーの識別情報(identity context)をIAMロールセッションに安全に埋め込んで伝播させることでこの課題を解決します。受信側のAWSサービス(本記事ではS3 Access Grants)は、このidentity contextをもとにgranteeを解決し、認可判断を行います。あわせてCloudTrailにもエンドユーザーの識別子が直接記録されるため、IAMロールの先にいる実際のユーザー単位での監査が可能になります(詳細は5-6で扱います)。

5-2. 前提条件

trusted identity propagationの統合には、以下が前提となります。

  • IAM Identity Centerの有効化: §2-1で述べた通り、組織インスタンスとして有効化済みであること
  • 企業ディレクトリの自動プロビジョニング: 外部IdP(Okta・Entra ID等)からIAM Identity Centerへ、SCIM(System for Cross-domain Identity Management)によるユーザー・グループの自動同期が構成済みであること。本記事では、この自動プロビジョニング設定自体をスコープ外とし、既に完了している前提で進めます
  • S3 Access Grants instance: §4で作成済みのaws_s3control_access_grants_instanceと、最低1つのLocationが登録済みであること
  • IAM Identity Centerインスタンスと、S3 Access Grants instanceは同一AWSリージョンに存在する必要があります
5節で構築する範囲

  • Access Grants instanceとIAM Identity Centerインスタンスの関連付け
  • Storage Browser/カスタムアプリ向けのIAM Identity Centerアプリケーション登録とtrusted token issuer設定
  • DIRECTORY_USER/DIRECTORY_GROUPへのgrant発行と、identity contextを使ったGetDataAccess呼び出しフロー

5-3. Terraform: Access Grants instanceとIAM Identity Centerの関連付け

aws_s3control_access_grants_instanceリソースはidentity_center_arn引数をサポートしており、これを設定するだけでAccess Grants instanceとIAM Identity Centerインスタンスが関連付けられます(内部的にはAWS CLIのassociate-access-grants-identity-centerと同じAPIが呼び出されます)。§4-2で作成したリソースにidentity_center_arnを追加します。

data "aws_ssoadmin_instances" "main" {}

resource "aws_s3control_access_grants_instance" "main" {
  identity_center_arn = tolist(data.aws_ssoadmin_instances.main.arns)[0]

  tags = {
 Environment = "production"
 ManagedBy= "terraform"
  }
}

terraform applyを実行すると、既存のAccess Grants instanceに対してIAM Identity Centerが関連付けられます。関連付けの状態はAWS CLIでも確認できます。

aws s3control get-access-grants-instance \
  --account-id 123456789012 \
  --region ap-northeast-1

レスポンスのIdentityCenterArnIdentityCenterApplicationArnが設定されていれば、関連付けは完了です。すでにTerraform管理外でAccess Grants instanceを作成済みの環境や、Terraformの状態を変更せず緊急で関連付けを行いたい場合は、AWS CLIのassociate-access-grants-identity-centerコマンドを直接実行できますが、その場合は次回terraform planで差分が検出される点に注意してください。

aws s3control associate-access-grants-identity-center \
  --account-id 123456789012 \
  --identity-center-arn arn:aws:sso:::instance/ssoins-1234a567bb89012c \
  --region ap-northeast-1

5-4. IAM Identity Centerへのアプリケーション登録とtrusted token issuer設定(Terraform)

Storage Browser for S3(§6)やカスタムアプリケーションがディレクトリユーザーを認証した後にS3 Access Grantsを呼び出すには、IAM Identity Centerにアプリケーションを登録し、外部IdPをtrusted token issuerとして設定する必要があります。IAM Identity Centerが発行するトークンとS3側のgranteeを結びつけるための一連の設定です。

resource "aws_ssoadmin_application" "storage_browser" {
  name= "storage-browser-s3"
  instance_arn = tolist(data.aws_ssoadmin_instances.main.arns)[0]
  application_provider_arn = "arn:aws:sso::aws:applicationProvider/custom"

  portal_options {
 visibility = "DISABLED"
  }
}

resource "aws_ssoadmin_trusted_token_issuer" "corp_idp" {
  name  = "corp-idp-trusted-issuer"
  instance_arn= tolist(data.aws_ssoadmin_instances.main.arns)[0]
  trusted_token_issuer_type = "OIDC_JWT"

  trusted_token_issuer_configuration {
 oidc_jwt_configuration {
issuer_url  = "https://login.microsoftonline.com/${var.corp_tenant_id}/v2.0"
claim_attribute_path = "preferred_username"
identity_store_attribute_path = "userName"
jwks_retrieval_option= "OPEN_ID_DISCOVERY"
 }
  }
}

resource "aws_ssoadmin_application_access_scope" "access_grants_scope" {
  application_arn = aws_ssoadmin_application.storage_browser.arn
  scope= "s3:access_grants:read_write"
}

aws_ssoadmin_trusted_token_issuerclaim_attribute_pathは外部IdPが発行するIDトークン内の属性(通常はユーザー名やメールアドレス)、identity_store_attribute_pathはその値をIAM Identity Center側のIdentity Storeでどの属性と突合するかを指定します。aws_ssoadmin_application_access_scopeで設定するスコープs3:access_grants:read_writeは、このアプリケーションがS3 Access Grants向けにトークンを交換できることを明示するものです。

5-5. AWS CLI: trusted token issuerの関連付けとIAM認証方式の設定

2026年7月時点で、trusted token issuerをアプリケーションの認可(grant)に結びつける設定と、アプリケーションのIAM認証方式(認可されたIAMロールのみがトークン交換を呼び出せるようにする設定)には対応するTerraformリソースが提供されていません。この2つはAWS CLIで実施します。

まず、trusted token issuerとアプリケーションをjwt-bearerグラントタイプで結びつけ、信頼する監査対象(audience)を登録します。

cat > grant.json <<'EOF'
{
  "JwtBearer": {
 "AuthorizedTokenIssuers": [
{
  "TrustedTokenIssuerArn": "${TRUSTED_TOKEN_ISSUER_ARN}",
  "AuthorizedAudiences": ["${CORP_IDP_AUDIENCE_ID}"]
}
 ]
  }
}
EOF

aws sso-admin put-application-grant \
  --application-arn "${APPLICATION_ARN}" \
  --grant-type "urn:ietf:params:oauth:grant-type:jwt-bearer" \
  --grant file://grant.json

次に、アプリケーションのIAM認証方式を設定し、Storage Browser/カスタムアプリが使用するIAMロールのみがsso-oauth:CreateTokenWithIAMを呼び出せるように制限します。

cat > authentication-method.json <<'EOF'
{
  "Iam": {
 "ActorPolicy": {
"Version": "2012-10-17",
"Statement": [
  {
 "Effect": "Allow",
 "Principal": {
"AWS": "arn:aws:iam::123456789012:role/storage-browser-app-role"
 },
 "Action": "sso-oauth:CreateTokenWithIAM",
 "Resource": "*"
  }
]
 }
  }
}
EOF

aws sso-admin put-application-authentication-method \
  --application-arn "${APPLICATION_ARN}" \
  --authentication-method-type IAM \
  --authentication-method file://authentication-method.json

5-6. 企業ディレクトリユーザーがS3へ到達するまでのトークン交換フロー

上記の設定が完了すると、Storage Browser/カスタムアプリは以下の3段階でエンドユーザーの識別情報を保持したままS3 Access Grantsへ到達できます。

  1. CreateTokenWithIAM: アプリケーションは、外部IdPで認証したエンドユーザーのIDトークンを、storage-browser-app-roleのIAM認証情報で署名してCreateTokenWithIAM APIへ渡します。IAM Identity Centerはtrusted token issuerの設定(5-5)をもとにIDトークンを検証し、sts:identity_contextクレームを含む新しいトークンを返却します。
  2. AssumeRole(identity context付与): アプリケーションは、sts:identity_contextの値をprovided-contextsとして渡しながら、S3 Access Grants呼び出し用のIAMロールをAssumeRoleします。これにより、発行されるセッションにエンドユーザーの識別情報が「identity-enhanced IAM role session」として埋め込まれます。
aws sts assume-role \
  --role-arn "arn:aws:iam::123456789012:role/storage-browser-app-role" \
  --role-session-name "directory-user-session" \
  --provided-contexts ProviderArn="arn:aws:iam::aws:contextProvider/IdentityCenter",ContextAssertion="${IDENTITY_CONTEXT}"
  1. GetDataAccess: 手順2で得たセッションを使ってS3 Access GrantsのGetDataAccessを呼び出します。S3 Access Grantsは、セッションに埋め込まれたidentity contextからエンドユーザーを特定し、そのユーザー(またはユーザーが属するグループ)に対するgrantを照合します。マッチするgrantがあれば、IAM principalへのマッピングを一切経由せず、エンドユーザーのIDのままスコープ限定の一時クレデンシャルが発行されます。

この一連の流れを成立させるには、§4-3で作成したLocationのIAMロール(aws_iam_role.access_grants_location)の信頼ポリシーに、sts:SetSourceIdentitysts:SetContextを追加する必要があります。

data "aws_iam_policy_document" "access_grants_location_assume" {
  statement {
 effect  = "Allow"
 actions = ["sts:AssumeRole", "sts:SetSourceIdentity"]
 principals {
type  = "Service"
identifiers = ["access-grants.s3.amazonaws.com"]
 }
  }

  statement {
 effect  = "Allow"
 actions = ["sts:SetContext"]
 principals {
type  = "Service"
identifiers = ["access-grants.s3.amazonaws.com"]
 }
 condition {
test  = "ForAllValues:ArnEquals"
variable = "sts:RequestContextProviders"
values= ["arn:aws:iam::aws:contextProvider/IdentityCenter"]
 }
  }
}

5-7. Terraform: DIRECTORY_USER/DIRECTORY_GROUPへのgrant発行

grantee側の設定は§4-4と同じaws_s3control_access_grantリソースで行います。grantee_typeDIRECTORY_USERまたはDIRECTORY_GROUPを指定し、grantee_identifierにはIAM Identity CenterのIdentity Store上のユーザーID・グループIDを指定します。

resource "aws_s3control_access_grant" "finance_dept_directory_group" {
  access_grants_location_id = aws_s3control_access_grants_location.default.access_grants_location_id
  permission = "READ"

  access_grants_location_configuration {
 s3_sub_prefix = "datasets/finance/*"
  }

  grantee {
 grantee_type = "DIRECTORY_GROUP"
 grantee_identifier = var.finance_dept_identity_store_group_id
  }

  tags = {
 Team = "finance-dept"
  }
}

Identity Store上のユーザーID・グループIDは、IAM Identity Centerコンソールの該当ユーザー・グループの詳細画面、またはAWS CLIのaws identitystore list-users / list-groupsで取得できます。

5-8. CloudTrailによる監査の簡素化

trusted identity propagationを統合する最大の効果の一つが、CloudTrailの監査精度です。IAM principalへのgrantのみを使う§4の構成では、GetDataAccessのCloudTrailイベントに記録されるuserIdentityは、実際にAPIを呼び出したIAMロール(アプリケーションのIAMロールやLocationのIAMロール)にとどまり、その先にいる個々のエンドユーザーは記録されません。

一方、identity-enhanced IAM role sessionを経由したGetDataAccess呼び出しでは、CloudTrailイベントのuserIdentity要素にonBehalfOfフィールドが追加され、以下の2つの値が直接記録されます。

フィールド内容
onBehalfOf.userId呼び出しの背後にいるIAM Identity Centerユーザー(またはグループ経由でアクセスした場合はそのユーザー)のID
onBehalfOf.identityStoreArn対象のIAM Identity CenterのIdentity Store ARN

これにより、「どのIAMロールがAPIを呼び出したか」だけでなく「どの企業ディレクトリユーザーがそのデータへアクセスしたか」をCloudTrailログから直接特定できるようになり、IAM principalへの静的マッピングを自前実装していた場合に比べて監査ログの解析コストが大幅に下がります。

IAM Identity Center統合の落とし穴

  • Access Grants instanceとIAM Identity Centerインスタンスは同一リージョンである必要がある(異なるリージョンの場合はIAM Identity Centerインスタンスのレプリケーションが必要)
  • trusted token issuerのグラント設定(5-5)・IAM認証方式設定(5-5)にはTerraformリソースが提供されていないため、terraform applyだけでは統合が完結しない。AWS CLI実行手順をデプロイパイプラインに組み込む必要がある
  • Locationの IAM ロール信頼ポリシーにsts:SetSourceIdentity/sts:SetContextを追加し忘れると、AssumeRoleはIdentity Contextを持たない通常のセッションとして成功してしまい、後続のGetDataAccessでgranteeが解決できずにAccessDeniedとなる(エラーの原因が分かりにくい)
  • DIRECTORY_USER/DIRECTORY_GROUPのgrantee_identifierはIAM Identity CenterのIdentity Store ID(UUID形式)であり、IAMのユーザー名やARNとは異なる体系である点に注意

6. Storage Browser for S3 — React/Amplifyセルフサービスアクセス

§4・§5でS3 Access GrantsとIAM Identity Center trusted identity propagationの基盤を構築しました。本節では、この基盤の上にエンドユーザー向けのセルフサービスUIであるStorage Browser for S3を導入します。

6-1. Storage Browser for S3の概要と3つの認証方式

Storage Browser for S3は、AWS Amplify UI for React上で提供されるオープンソースのUIコンポーネントで、エンドユーザーがS3データをブラウザ上で閲覧・アップロード・ダウンロード・コピー・削除できるセルフサービスインターフェースを提供します。認証・認可の設定方式として、AWS公式は次の3方式を提供しています。

方式想定用途本記事での位置づけ
方式1: AWS Amplify Auth顧客・外部パートナー向け。Amazon Cognitoベースで最速構築対象外(§4・§5とは異なる認証基盤が必要)
方式2: IAM principal直接管理AWSアカウント内のIAM principalへ直接S3 Access Grantsで権限付与対象外(IAM principalへの静的マッピングが前提)
方式3: IAM Identity Center + S3 Access Grants(スケール対応)企業ディレクトリ全体へ集中管理でデータアクセスを提供本記事で採用(§4・§5の構築内容とそのまま接続)

本記事は§4でS3 Access Grants、§5でIAM Identity Center trusted identity propagationを構築済みのため、方式3(スケール対応の管理方式)を採用し、追加の認証基盤を新設せずにStorage Browser for S3を接続します。

6-2. インストール

Storage Browser for S3は@aws-amplify/ui-react-storageパッケージとして提供されます。

npm i --save @aws-amplify/ui-react-storage aws-amplify

6-3. bootstrapアプリケーションとidentity bearerロールのTerraform構築

Storage Browserコンポーネントがブラウザ上でS3データへアクセスするには、外部IdPが発行したJSON Web Token(JWT)を、IAM Identity Centerが発行するトークンと交換し、さらにそのトークンで一時IAM認証情報を取得するバックエンド(トークン交換API)が必要です。このバックエンドが使用する2つのIAMロールをTerraformで構築します。

1つ目は、JWTをIAM Identity Centerのトークンへ交換するCreateTokenWithIAM APIを呼び出すbootstrapロールです。§5-4で作成したaws_ssoadmin_application.storage_browserのARNをそのまま参照します。

data "aws_iam_policy_document" "storage_browser_bootstrap_assume" {
  statement {
 effect  = "Allow"
 actions = ["sts:AssumeRole"]
 principals {
type  = "AWS"
identifiers = [var.token_exchange_backend_principal_arn]
 }
  }
}

resource "aws_iam_role" "storage_browser_bootstrap" {
  name= "storage-browser-bootstrap-role"
  assume_role_policy = data.aws_iam_policy_document.storage_browser_bootstrap_assume.json
}

data "aws_iam_policy_document" "storage_browser_bootstrap_permissions" {
  statement {
 effect = "Allow"
 actions= ["sso-oauth:CreateTokenWithIAM"]
 resources = [aws_ssoadmin_application.storage_browser.arn]
  }

  statement {
 effect = "Allow"
 actions= ["sts:AssumeRole", "sts:SetContext"]
 resources = [aws_iam_role.storage_browser_identity_bearer.arn]
  }
}

resource "aws_iam_role_policy" "storage_browser_bootstrap" {
  name= "storage-browser-bootstrap-policy"
  role= aws_iam_role.storage_browser_bootstrap.id
  policy = data.aws_iam_policy_document.storage_browser_bootstrap_permissions.json
}

2つ目は、bootstrapロールがAssumeRoleし、Storage Browserコンポーネントへ返却する一時クレデンシャルを発行するidentity bearerロールです。§4-4/§5-7で付与したgrantに対して、GetDataAccessListCallerAccessGrantsの両方を許可する必要があります(ListCallerAccessGrantsはコンポーネントがログインユーザーの利用可能なlocation一覧を取得するために呼び出します)。

data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

data "aws_iam_policy_document" "storage_browser_identity_bearer_assume" {
  statement {
 effect  = "Allow"
 actions = ["sts:AssumeRole", "sts:SetContext"]
 principals {
type  = "AWS"
identifiers = [aws_iam_role.storage_browser_bootstrap.arn]
 }
  }
}

resource "aws_iam_role" "storage_browser_identity_bearer" {
  name= "storage-browser-identity-bearer-role"
  assume_role_policy = data.aws_iam_policy_document.storage_browser_identity_bearer_assume.json
}

data "aws_iam_policy_document" "storage_browser_identity_bearer_permissions" {
  statement {
 effect  = "Allow"
 actions = ["s3:GetDataAccess", "s3:ListCallerAccessGrants"]
 resources = [
"arn:aws:s3:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:access-grants/default",
 ]
  }
}

resource "aws_iam_role_policy" "storage_browser_identity_bearer" {
  name= "storage-browser-identity-bearer-policy"
  role= aws_iam_role.storage_browser_identity_bearer.id
  policy = data.aws_iam_policy_document.storage_browser_identity_bearer_permissions.json
}

identity bearerロールのaccess-grants/defaultは、§4-2で作成したデフォルトのAccess Grants instanceを指すARNです。§4-3でバケット単位・prefix単位のLocationを個別登録した場合でも、grantee向けのIAM権限リソースは常にinstance単位のaccess-grants/defaultを指定します(Location/Grant単位でARNを分ける必要はありません)。

6-4. React: createManagedAuthAdapterによるコンポーネント初期化

バックエンドのトークン交換APIを準備した後、Reactアプリケーション側でcreateManagedAuthAdapterを使ってStorage Browserコンポーネントを初期化します。

import {
  createManagedAuthAdapter,
  createStorageBrowser,
} from '@aws-amplify/ui-react-storage/browser';
import '@aws-amplify/ui-react-storage/styles.css';

export const { StorageBrowser } = createStorageBrowser({
  config: createManagedAuthAdapter({
 credentialsProvider: async (options) => {
// トークン交換APIを呼び出し、identity bearerロールの一時クレデンシャルを取得する
const response = await fetch('/api/storage-browser-credentials', {
  method: 'POST',
  headers: { Authorization: `Bearer ${getCurrentIdpJwt()}` },
});
const { accessKeyId, secretAccessKey, sessionToken, expiration } = await response.json();
return {
  credentials: { accessKeyId, secretAccessKey, sessionToken, expiration: new Date(expiration) },
};
 },
 region: 'ap-northeast-1',
 accountId: '123456789012',
 registerAuthListener: (onAuthStateChange) => {
// 例: 外部IdPのログアウトイベントで onAuthStateChange() を呼び出し、
// コンポーネント内のS3データ表示状態をクリアする
 },
  }),
});

credentialsProviderが呼び出す/api/storage-browser-credentialsエンドポイントの実装では、次の手順でJWTをIAM認証情報へ交換します。

  1. リクエストヘッダーからJWTを取得し、JWKS(JSON Web Key Set)エンドポイントの公開鍵で署名を検証、exp/iss/sub/audクレームを確認する
  2. CreateTokenWithIAM APIへJWTを渡し、IAM Identity Centerが発行するsts:identity_contextクレーム付きトークンを取得する(bootstrapロールの認証情報で呼び出す。一度使用したJWTは再利用できない)
  3. 取得したidentity context付きトークンで、identity bearerロールをAssumeRoleする(provided-contextsパラメータで§5-6と同様にidentity contextを渡す)
  4. AssumeRoleで得た一時クレデンシャル(AccessKeyId/SecretAccessKey/SessionToken/Expiration)をStorage Browserコンポーネントへ返却する

registerAuthListenerは、外部IdP側でユーザーがログアウトした場合などに、コンポーネント内部にキャッシュされたS3データ一覧・クレデンシャルをクリアするためのコールバック登録ポイントです。

6-5. 対応操作と非対応ストレージクラス

Storage Browser for S3コンポーネントが標準で提供する操作は次の通りです。

操作内容
閲覧(List)バケット・prefix配下のオブジェクト一覧表示
ダウンロード(Get)オブジェクトのダウンロード
アップロード(Put/Upload)ファイル・フォルダのアップロード(マルチパートアップロード対応)
コピー(Copy)オブジェクトの別locationへのコピー
削除(Delete)個別ファイル・フォルダ単位の削除
フォルダ作成バケット・prefix配下への新規フォルダ作成
検索・プレビューファイル名検索、画像/動画/テキストファイルのインラインプレビュー

一方、2026年7月時点で、S3 Glacier Flexible Retrieval・S3 Glacier Deep Archiveストレージクラスのオブジェクトに対する操作は、Amplify UI公式ロードマップ上で「評価中の機能」として明記されており、非対応です。これは本記事§2-2で述べたS3 Glacier系・S3 Intelligent-Tiering Archive/Deep Archiveアクセス階層の非対応とも整合します。これらのストレージクラスを含むデータセットにStorage Browserからアクセスさせたい場合は、事前に対象オブジェクトをStandardなど対応ストレージクラスへ復元(restore)しておくか、Storage Browserの公開対象から除外する設計が必要です。

Storage Browser for S3導入の落とし穴

  • bootstrapロールとidentity bearerロールの権限を混同すると、CreateTokenWithIAMは成功するのに後続のAssumeRoleAccessDeniedになる(bootstrapロールにはsts:AssumeRole+sts:SetContext、identity bearerロールにはs3:GetDataAccess+s3:ListCallerAccessGrantsという役割分担を混同しないこと)
  • 外部IdPのJWTは一度CreateTokenWithIAMで使用すると再利用できない。トークン交換APIをリトライ実装する場合、同一JWTでの再送ではなくIdP側から新規JWTを取得し直す設計が必要
  • S3バケットにCORS設定がないと、ブラウザから直接アップロード・ダウンロードするStorage Browserコンポーネントのリクエストがブラウザ側でブロックされる(コンソール/CLIからのAWS API呼び出しとは異なりCORSの影響を受ける)
  • Glacier系ストレージクラスのオブジェクトを含むlocationをそのままStorage Browserへ公開すると、該当オブジェクトの操作でエラーになる。restore済みか対象外か、事前に切り分けておく

7. 詰まりポイント7選 図解

fig05: アクセス制御手法の選択判断ツリー
fig05: アクセス制御手法の選択判断ツリー

§3〜§6で構築してきたS3 Access Grants・IAM Identity Center統合・Storage Browser for S3の導入では、いずれも設定漏れや権限設計の誤解によって「一見成功しているのに実際にはアクセスできない」状態に陥りやすい箇所が存在します。本節では、実装時に特に詰まりやすい7つのポイントを整理します。

7-1. Locationの権限設定ミス

§4-3で登録したLocationのIAMロール(aws_iam_role.access_grants_location)に、対象バケット・prefixへのs3:GetObjects3:PutObjects3:ListBucket等の権限が不足していると、Grant自体は有効なのにGetDataAccessのレスポンスクレデンシャルでS3操作をした際にAccessDeniedとなります。Grantの有効性とLocation側IAMロールの実権限は独立してチェックされる二重構造であるため、片方だけを確認して「設定は正しいはず」と思い込まないことが重要です。

7-2. Credentials Vendingの有効期限切れ

GetDataAccessで発行される一時クレデンシャルの有効期限はデフォルト1時間です(§4-5)。長時間のバッチ処理やファイルアップロード中にこの期限が切れると、処理の途中でExpiredTokenエラーが発生します。長時間ジョブでは、有効期限が近づいた時点でGetDataAccessを再呼び出しし、クレデンシャルをローテーションする実装が必要です。Storage Browser側ではcredentialsProviderforceRefreshオプションを使い、期限切れ検知時に再取得をトリガーする設計にします。

7-3. Identity Center未連携時の403

§5-3でidentity_center_arnを設定する前の状態でDIRECTORY_USER/DIRECTORY_GROUP向けのGrantを作成しようとすると、Access Grants instanceがまだIAM Identity Centerと関連付けられていないため、Grant作成自体が失敗するか、作成できてもGetDataAccess呼び出し時に403が返ります。§5-3の関連付け(aws s3control get-access-grants-instanceIdentityCenterArnが設定されていることの確認)を、DIRECTORY_USER/DIRECTORY_GROUP向けGrant作成の前提条件として必ず先に完了させます。

7-4. Storage BrowserのGlacier系ストレージクラス操作制限

§6-5で述べた通り、Storage Browser for S3はS3 Glacier Flexible Retrieval・S3 Glacier Deep Archiveのオブジェクト操作に非対応です。ライフサイクルポリシーでこれらのストレージクラスへ自動移行される設計のバケットをそのままStorage Browserへ公開すると、移行後のオブジェクトでエンドユーザーからの操作エラーが多発します。Storage Browserの公開対象prefixには、Glacier系へ移行しないライフサイクルルールを適用するか、Standard等の対応ストレージクラスに限定した専用prefixを設計します。

7-5. Grantの優先順位の誤解

同一granteeに対して、異なるスコープ(バケット全体のGrantとサブprefixのGrant)が重複して存在する場合、S3 Access Grantsは最も一致度の高い(最も限定的な)スコープのGrantを優先して適用します。「広いスコープのGrantで許可しているから、狭いスコープのGrantは不要」という思い込みで狭いスコープのGrantを削除すると、想定より広い権限が残ってしまう、あるいは逆に必要な権限が失われるといった誤設計に繋がります。Grant設計時は、granteeごとに有効なGrantの一覧をListAccessGrantsで棚卸しし、重複スコープがないか定期的に確認します。

7-6. Cross-account設定漏れ

§4-6で解説したクロスアカウントGrantでは、Access Grants Instanceのリソースベースポリシー(aws_s3control_access_grants_instance_resource_policy)を設定し忘れると、Grant自体は正しく作成されていても、消費側アカウントからのGetDataAccessAccessDeniedになります。エラーメッセージからはリソースベースポリシーの不備かGrant自体の不備か区別しにくいため、クロスアカウント構成を組む際は、リソースベースポリシーの設定を必ずGrant作成のチェックリストに含めます。

7-7. 既存Access Pointとの併用設計ミス

§3-2で述べた通り、S3 Access PointはAccess Grantsとは別のスケーリング段階の仕組みです。既存のAccess Point経由でアクセス制御しているprefixに対して、そのAccess PointのARNをAccess GrantsのLocationとして重ねて登録すると、Access Pointポリシーとgrant権限の両方を満たす必要が生じ、想定より厳しい(あるいは意図しない)アクセス制御になります。Access PointとAccess Grantsを併用する場合は、どちらが「最終的なアクセス可否の判定者」なのかをprefixごとに明確に分離し、同一prefixに両方の制御を重ねて適用しないよう設計します。

詰まりポイントの共通パターン

  • 「片方の設定だけ確認して安心する」二重チェック漏れ(7-1・7-6)
  • Storage Browser固有の制約を見落とす(7-2・7-4)
  • S3 Access Grantsの仕組み(優先順位・関連付け・他機能との併用)への理解不足(7-3・7-5・7-7)

8. アンチパターン → 正解パターン変換演習 + シリーズ繋ぎ

本節では、S3大規模アクセス管理でよく見られる5つのアンチパターンを取り上げ、本記事で構築してきたS3 Access Grants・IAM Identity Center統合・Storage Browserを使った正解パターンへの変換を演習形式で確認します。最後に、本シリーズ「AWS Storage本番運用」Vol1〜4全体の繋がりを整理します。

8-1. アンチパターン1: バケットポリシー無限拡張

症状: 部門・アプリケーションが増えるたびにバケットポリシーへStatementを追記し続け、20KB上限に接近している。ポリシー変更のたびに巨大なJSONドキュメント全体をレビューする必要があり、レビューコストが線形以上に増大している。

正解パターン: §3-1で整理した通り、主体×prefixの組み合わせが数十を超えた時点でバケットポリシーへの追記を止め、§4のS3 Access Grants(Instance/Location/Grant)へ移行します。既存のバケットポリシーのStatementを棚卸しし、各Statementが対象とする主体・prefixをそのままGrantとして再登録すれば、ポリシードキュメントのサイズを一切気にせず主体を追加できます。

8-2. アンチパターン2: IAMポリシー5KB上限への到達

症状: 1つのIAMロールに、アクセス可能なprefixを列挙する形でインラインポリシーを追記し続けており、マネージドポリシー・インラインポリシー双方の実務上限に近づいている。

正解パターン: prefix列挙をポリシードキュメントに持たせるのではなく、§4-4のGrantとして「IAM principal × prefix × permission」の組み合わせを登録します。IAMロール側のポリシーは§2-1で示したs3:GetDataAccess呼び出し権限のみを持てばよく、prefixの追加・削除はGrantリソースの増減で完結し、IAMポリシー本体を編集する必要がなくなります。

8-3. アンチパターン3: Access Point乱立で管理不能

症状: §3-2のAccess Pointを主体ごとに作成し続けた結果、リージョンあたりのAccess Point数上限に接近し、どのAccess Pointがどの主体向けか台帳管理が破綻している。

正解パターン: Access Pointは「バケットポリシー分割の中間解」であり、数千規模の動的な主体管理には設計上限界があります。既存Access Pointを棚卸しし、恒久的に必要なもの(VPC制限など固定要件を伴うもの)のみ残し、主体追加のたびにAccess Pointを新設していた運用を、§4のLocation(バケット・prefix単位、既存Access Pointより少数で足りる)+ Grant(主体単位、Access Pointのように上限を気にせず追加可能)の組み合わせへ置き換えます。

8-4. アンチパターン4: Access Grants未導入のままIAM principal個別付与を継続

症状: S3 Access Grantsの存在は認識しているが、既存のIAMロールベースのアクセス制御を移行するコストを懸念し、新規主体だけIAM principalへの個別ポリシー付与で場当たり的に対応し続けている。

正解パターン: §4-2で示した通り、Access Grants Instanceの作成自体は既存のIAM構成に影響を与えません。まず新規主体からGrant運用へ切り替え(§4-4)、既存のIAM principalは並行稼働させながら段階的にGrantへ移行します。全主体を一度に移行する必要はなく、Instance/Locationは共有インフラとして先行構築し、Grantの追加は主体ごとに独立して進められる点が、他のマイグレーションと比べて移行リスクが低い理由です。

8-5. アンチパターン5: Storage Browser未導入でエンドユーザーに一時クレデンシャル直接配布

症状: エンドユーザーがS3データにアクセスする際、管理者がaws s3control get-data-access(§4-5)を手動実行し、発行された一時クレデンシャルをチャットやメールで直接配布している。

正解パターン: この運用はクレデンシャルの配布経路自体が監査対象外になり、有効期限切れのたびに再発行を待つ運用負荷も発生します。§5のIAM Identity Center trusted identity propagationと§6のStorage Browser for S3を導入すれば、エンドユーザーは自身の企業ディレクトリ認証のままブラウザ上でセルフサービスアクセスでき、クレデンシャルの手動配布そのものが不要になります。あわせてCloudTrailのonBehalfOfフィールド(§5-8)により、誰がいつアクセスしたかも自動的に記録されます。

本節の演習まとめ

  • アンチパターン1・2は「ポリシードキュメントへの追記」という発想自体が問題であり、Grant(§4-4)への切り替えが直接の解決策
  • アンチパターン3はAccess Point(中間段階)を最終解として使い続けてしまう誤り。Access GrantsのLocation/Grant構造への置き換えが必要
  • アンチパターン4は移行コストへの懸念が導入を妨げているケース。既存IAM構成と並行稼働できる設計であることが移行の後押しになる
  • アンチパターン5はクレデンシャル配布という運用そのものがリスク。Identity Center統合+Storage Browserでセルフサービス化すれば構造的に解消する

8-6. シリーズ全体の繋ぎ — AWS Storage本番運用 Vol1〜5

本シリーズ「AWS Storage本番運用」は、Vol1でS3・EFS・FSx・Storage Gatewayの基礎を固めるところから始まり、Vol2でS3のAdvanced運用(Lifecycle・Intelligent-Tiering・Object Lambda・S3 Express One Zone・クロスリージョンレプリケーション)、Vol3でS3 Vectors・S3 Tables・Backupによるデータ活用と保護、Vol4でFSx for Lustre/NetApp ONTAP/OpenZFS・File Cache・EBSの詳細を扱ってきました。そして本Vol5では、これらすべてのボリュームで前提としてきた「S3へのアクセスを誰にどう許可するか」という管理面に焦点を当て、IAMポリシー/バケットポリシーの手動管理からS3 Access Grants・IAM Identity Center統合・Storage Browserへとスケールさせる方法を解説しました。

Vol1〜4で構築したストレージ基盤(データレイクバケット・FSxファイルシステム・Backup vault等)にアクセスする主体が数十を超えて増え続ける段階に達したら、本Vol5の内容がそのまま適用できます。特にVol2 §4で扱ったS3 Access Point(Supporting Access Point)は、本Vol5 §3-2で述べた通りAccess Grantsへ至る中間段階として位置づけられ、両記事は補完関係にあります。

Vol1: S3 / EFS / FSx / Storage Gateway基礎を読む
Vol2: S3 Advanced運用を読む
Vol3: S3 Vectors / Tables / Backupを読む
Vol4: FSx / EBS詳細を読む

AWS / ストレージの最新記事8件