上一篇透過 IAM Policy 與 Bucket Policy,讓 Account A 的 OrderApiRole 直接讀取 Account B 的 S3 Bucket,並測試了 SSE-S3 與 SSE-KMS 加密物件的存取差異。
今天改用第二種跨帳號存取方式:讓 Account A 的 OrderApiRole 先透過 STS AssumeRole,取得 Account B 的 ProductDataReadRole 暫時性憑證,再使用這個身分讀取相同的 S3 Bucket。
這次會沿用前兩篇建立的 S3 Bucket 與 EC2,主要調整 IAM Role 與 Policy,最後透過 AWS CLI,觀察 AssumeRole 前後的身分及存取結果有什麼不同。
本篇沿用前兩篇的測試環境:
| 項目 | Account A:存取方 | Account B:資源擁有方 |
|---|---|---|
| Account ID | 111122223333 |
444455556666 |
| 來源 Role | OrderApiRole |
— |
| 目標 Role | — | ProductDataReadRole |
| S3 Bucket | — | shared-product-data-prod |
| EC2 | order-api-cross-account-test |
— |
| Region | ap-northeast-1 |
ap-northeast-1 |
帳號 ID 與 Bucket 名稱都是範例,實作時需要換成自己的值。
上一篇已經透過兩側的 IAM Policy 與 Bucket Policy,讓 OrderApiRole 可以直接存取 Account B 的 S3。
但這次要測試的是 AssumeRole,因此先移除上一篇的直接存取權限,避免兩種授權方式互相影響。
登入 Account A,進入 IAM → Roles → OrderApiRole → Permissions。
找到上一篇建立的 Inline policy,將這份 Policy 刪除。
請保留
AmazonSSMManagedInstanceCore,因為目前仍然需要透過 Session Manager 連線至 EC2。
如果上一篇有加入授予來源 Role 的跨帳號 KMS 解密政策,也可以先移除這份 Policy,後續再由 Account B 的目標 Role 取得所需的 KMS 權限。
接著登入 Account B,進入 S3 → General purpose buckets → shared-product-data-prod → Permissions → Bucket policy → Edit。
移除上一篇新增的兩個 Statement:
AllowOrderApiRoleListBucket
AllowOrderApiRoleReadObjects
如果 Bucket Policy 只有這兩個 Statement,可以刪除整份 Policy;如果還有其他授權設定,請保留原有內容。
本次使用 Account B 自己的 IAM Role 存取同帳號的 Bucket,在沒有其他政策限制的情況下,可以透過 Role 的 IAM Policy 授權,不需要額外在 Bucket Policy 中授權 Account A 的 OrderApiRole。
回到 Account A,透過 Session Manager 連線至 EC2:
EC2 → Instances → 選擇 order-api-cross-account-test → Connect → Session Manager → Connect
執行:
aws sts get-caller-identity
確認目前使用的仍然是:
arn:aws:sts::111122223333:assumed-role/OrderApiRole/i-0123456789abcdef0
接著嘗試列出 Account B 的 S3 Bucket:
aws s3 ls s3://shared-product-data-prod/
在沒有其他政策額外授權的情況下,預期會收到:
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

確認直接存取已經失敗後,就可以開始設定 AssumeRole。
登入 Account B,進入 IAM → Roles → Create role。
這次建立的 Role 不會直接掛載到 EC2,而是讓 Account A 的 OrderApiRole 透過 STS AssumeRole 取得它的暫時性憑證。
建立時選擇:
111122223333。ProductDataReadRole。

建立完成後,進入 IAM → Roles → ProductDataReadRole → Trust relationships → Edit trust policy。
將 Trust Policy 修改為:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TrustOrderApiRole",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:role/OrderApiRole"
},
"Action": "sts:AssumeRole"
}
]
}

這份 Trust Policy 的 Principal 指定 Account A 的 OrderApiRole,表示 Account B 允許這個特定的 Role 切換至 ProductDataReadRole。
如果直接在建立 Role 時信任整個 Account A,則可能讓 Account A 中其他具有對應 AssumeRole 權限的身分也可以切換角色。因此,這裡進一步將信任對象限制為 OrderApiRole。
與上一篇不同的是,這次 Trust Policy 的 Principal 不再是 ec2.amazonaws.com,而是 Account A 的 IAM Role ARN。
ProductDataReadRole的 Trust Policy 負責決定「誰可以使用這個 Role」,而實際取得 Role 後能操作哪些 AWS 資源,仍然需要透過 Permissions Policy 設定。
進入 IAM → Roles → ProductDataReadRole → Permissions → Add permissions → Create inline policy。
切換至 JSON 編輯器,貼上:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListProductDataBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::shared-product-data-prod"
},
{
"Sid": "ReadProductDataObjects",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::shared-product-data-prod/*"
}
]
}

Policy name 可以自行輸入(這篇實作以 ProductDataReadRole 作為示範),最後點選 Create policy。
這份 Policy 允許 ProductDataReadRole 列出及讀取 Account B 的 S3 Bucket,但沒有授予上傳或刪除物件的權限。
到這裡,Account B 已經完成兩項設定:
OrderApiRole 切換至 ProductDataReadRole。ProductDataReadRole 讀取 Account B 的 S3 Bucket。接下來還需要在 Account A 授予 OrderApiRole 執行 AssumeRole 的權限。
登入 Account A,進入 IAM → Roles → OrderApiRole → Permissions → Add permissions → Create inline policy。
切換至 JSON 編輯器,貼上:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeProductDataReadRole",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::444455556666:role/ProductDataReadRole"
}
]
}

Policy name 可以自行輸入(這篇實作以 AssumeProductDataReadRolePolicy 作為示範),最後點選 Create policy。
這份 IAM Policy 允許 Account A 的 OrderApiRole 呼叫 STS AssumeRole,切換至 Account B 的 ProductDataReadRole。
到這裡,兩側的權限設定已經完成:
| 帳號 | Policy | 用途 |
|---|---|---|
| Account A | OrderApiRole 的 IAM Policy |
允許 AssumeRole 至 Account B |
| Account B | ProductDataReadRole 的 Trust Policy |
信任 Account A 的 OrderApiRole |
| Account B | ProductDataReadRole 的 IAM Policy |
允許讀取本帳號的 S3 Bucket |
這次 Account A 不需要直接取得 Account B 的 S3 權限,而是先取得切換角色的權限,再使用 Account B 的 Role 讀取 S3。
回到 Account A 的 EC2,先確認目前的 IAM 身分:
aws sts get-caller-identity
預期 ARN 類似:
arn:aws:sts::111122223333:assumed-role/OrderApiRole/i-0123456789abcdef0
接著,使用 AWS CLI 呼叫 STS AssumeRole:
aws sts assume-role \
--role-arn arn:aws:iam::444455556666:role/ProductDataReadRole \
--role-session-name ProductDataReadTest
這裡的兩個參數分別代表:
--role-arn:要切換至哪一個 IAM Role。--role-session-name:這次 AssumeRole 工作階段的名稱,方便後續識別。執行成功後,STS 會回傳類似以下資訊:
{
"Credentials": {
"AccessKeyId": "ASIA...",
"SecretAccessKey": "...",
"SessionToken": "...",
"Expiration": "2026-09-22T08:00:00+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROAXXXXXXXXX:ProductDataReadTest",
"Arn": "arn:aws:sts::444455556666:assumed-role/ProductDataReadRole/ProductDataReadTest"
}
}
這裡的 Credentials 就是 STS 核發的暫時性憑證,包含:
| 欄位 | 用途 |
|---|---|
AccessKeyId |
暫時性 Access Key ID |
SecretAccessKey |
暫時性 Secret Access Key |
SessionToken |
暫時性工作階段 Token |
Expiration |
憑證到期時間 |
與長期 IAM User Access Key 不同,AssumeRole 取得的憑證具有有效期限,到期後需要重新取得。
前面雖然已經成功呼叫 AssumeRole,但 AWS CLI 不會因為執行了 aws sts assume-role,就自動改用回傳的憑證。
因此,接下來需要將取得的暫時性憑證套用至目前的終端機,才能使用 Account B 的身分執行 S3 API。
為了避免手動複製憑證,可以在 EC2 終端機執行以下指令:
CREDS=$(aws sts assume-role \
--role-arn arn:aws:iam::444455556666:role/ProductDataReadRole \
--role-session-name ProductDataReadTest \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
--output text) || exit 1
read -r AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN <<< "$CREDS"
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
export AWS_SESSION_TOKEN
unset CREDS
這裡會重新呼叫一次 AssumeRole,取得新的暫時性憑證,再將憑證設定到目前 Shell 的環境變數。
設定完成後,AWS CLI 就可以使用 Account B 的 ProductDataReadRole 暫時性憑證執行後續操作。
這些環境變數只會影響目前的 Shell 工作階段及其子程序,不會直接修改 EC2 原本掛載的
OrderApiRole。結束測試後,可以移除環境變數,恢復使用 EC2 原本的 IAM Role。
完成憑證設定後,再次執行:
aws sts get-caller-identity
預期 ARN 類似:
arn:aws:sts::444455556666:assumed-role/ProductDataReadRole/ProductDataReadTest

與前面相比,可以觀察到兩個差異:
| 項目 | AssumeRole 前 | AssumeRole 後 |
|---|---|---|
| Account ID | 111122223333 |
444455556666 |
| IAM Role | OrderApiRole |
ProductDataReadRole |
| Role session name | EC2 Instance ID | ProductDataReadTest |
雖然目前操作的仍然是 Account A 的同一台 EC2,但 AWS CLI 已經改用 Account B 的 ProductDataReadRole 暫時性憑證。
這也是本次與上一篇最大的差異:上一篇是由 Account A 的 Role 直接存取 Account B 的資源;這次則是先切換至 Account B 的 Role,再以該 Role 的身分存取 S3。
確認目前使用的是 ProductDataReadRole 後,先測試列出 Bucket 中的物件:
aws s3 ls s3://shared-product-data-prod/
如果權限設定正確,且沒有其他政策限制,預期可以成功列出 S3 Bucket 中的物件。

接著,先下載上一篇使用 SSE-S3 加密的測試物件:
cd ~
aws s3 cp \
s3://shared-product-data-prod/test.png \
./method2-test.png
這裡請使用上一篇已確認為 SSE-S3 加密的物件,並依照實際上傳的檔名修改指令。若上一篇的測試檔案名稱不同,請替換成自己的物件名稱。
如果下載成功,預期會看到類似:
download: s3://shared-product-data-prod/test.png to ./method2-test.png
接著執行:
ls method2-test.png
確認檔案已成功下載至 EC2。

最後,再次執行:
aws sts get-caller-identity
確認目前仍然使用 Account B 的 ProductDataReadRole。

這代表 Account A 的 EC2 已經成功透過 AssumeRole,取得 Account B 的暫時性身分,並使用該身分讀取 Account B 的 S3 Bucket。
上一篇已經測試過,當 S3 物件使用 SSE-KMS 加密時,除了 s3:GetObject,還需要具有使用對應 KMS Key 的權限。
上一篇使用 Account A 的 OrderApiRole 直接跨帳號存取時,無法讀取使用 Account B 的 AWS managed key aws/s3 加密的物件。
但這次已經透過 AssumeRole 切換至 Account B 的 ProductDataReadRole,實際讀取 S3 的身分與 KMS Key 位於同一個帳號,因此可以在取得適當的 KMS 權限後,讀取使用 aws/s3 加密的物件。
登入 Account B,進入 IAM → Roles → ProductDataReadRole → Permissions → Add permissions → Create inline policy。
切換至 JSON 編輯器,貼上以下內容:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DecryptProductData",
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:ap-northeast-1:444455556666:alias/aws/s3"
}
]
}

Policy name 可以自行輸入(這篇實作以 DecryptProductDataPolicy 作為示範),最後點選 Create policy。
這份 IAM Policy 允許 ProductDataReadRole 使用 Account B 的 AWS managed key aws/s3 執行解密操作。
由於本次只需要下載 S3 物件,因此先授予 kms:Decrypt 即可,不需要額外授予 kms:Encrypt 或 kms:GenerateDataKey。
aws/s3是 AWS managed key,無法自行修改它的 Key Policy。不過,這次的ProductDataReadRole與 KMS Key 位於同一個 AWS 帳號,因此可以透過 IAM Policy 授予對應的解密權限,不需要像上一篇直接跨帳號存取時一樣,另外授權 Account A 的 Role 使用金鑰。
回到 Account A 的 EC2,確認目前已經透過 AssumeRole 切換至 Account B 的 ProductDataReadRole:
aws sts get-caller-identity
預期 ARN 類似:
arn:aws:sts::444455556666:assumed-role/ProductDataReadRole/ProductDataReadTest
接著,下載上一篇使用 aws/s3 加密的測試物件:
aws s3 cp \
s3://shared-product-data-prod/test-aws-kms.png \
./method2-test-aws-kms.png
如果 S3 與 KMS 權限都設定正確,且沒有其他政策限制,預期可以成功下載物件。

這次與上一篇最大的差異在於:
OrderApiRole,無法跨帳號使用 Account B 的 AWS managed key aws/s3 解密物件。ProductDataReadRole,與 aws/s3 位於同一帳號,因此可以在取得適當的 KMS 權限後讀取物件。這也說明了,相同的 S3 物件,即使使用相同的加密方式,也可能因為實際存取的 IAM 身分不同,而有不同的授權結果。
完成測試後,可以移除剛才設定的 STS 暫時性憑證:
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
再次執行:
aws sts get-caller-identity
預期 ARN 會恢復為:
arn:aws:sts::111122223333:assumed-role/OrderApiRole/i-0123456789abcdef0
這代表 AWS CLI 已恢復使用 EC2 原本的 IAM Role。
此時,如果再次直接存取 Account B 的 S3:
aws s3 ls s3://shared-product-data-prod/
在沒有其他政策額外授權的情況下,預期會再次收到 AccessDenied。
因為目前使用的又是 Account A 的 OrderApiRole,而我們已經在本篇開始時移除上一篇的直接跨帳號 S3 授權。

經過前面的操作,可以將兩種跨帳號存取方式整理如下:
| 比較項目 | Bucket Policy 直接授權 | STS AssumeRole |
|---|---|---|
| 存取方 | Account A | Account A |
| 實際讀取 S3 的 Role | OrderApiRole |
ProductDataReadRole |
| 讀取 S3 時的 Account ID | 111122223333 |
444455556666 |
| Account A 的 IAM Policy | 允許讀取 Account B 的 S3 | 允許 AssumeRole 至 Account B |
| Account B 的 Bucket Policy | 授權 Account A 的 Role | 本次實作不需要額外授權 |
| Account B 的 Role | 不需要 | 設定 Trust Policy 與 S3 存取權限 |
兩種方式都能讓 Account A 的 EC2 讀取 Account B 的 S3 Bucket,但實際使用的 IAM 身分不同。
Bucket Policy 直接授權是讓 Account A 的 OrderApiRole 直接存取 Account B 的 S3,過程中不需要切換至 Account B 的 Role。
STS AssumeRole 則是讓 Account A 的 OrderApiRole 先取得 Account B 的 ProductDataReadRole 暫時性憑證,再使用該 Role 的權限存取 S3。
因此,兩種方式除了權限設定位置不同,實際執行 S3 API 時使用的 IAM 身分也不同。
這三篇透過 Bucket Policy 與 AssumeRole,實作了不同 AWS 帳號之間的資源存取,並觀察兩種方式在權限設定與實際存取身分上的差異。
不過,當 AWS 帳號越來越多,需要管理的就不只是資源之間的存取權限。公司的開發與維運人員可能需要登入不同帳號,各自擁有不同的操作權限。如果每個帳號都要分別管理使用者與權限,維護起來也會越來越複雜。
下一篇將介紹 AWS IAM Identity Center,了解如何集中管理多個 AWS 帳號的人員登入與存取權限,以及如何透過群組、Permission Set 與企業既有的身分系統,簡化多帳號的權限管理。