上一篇提到,AWS 不會只看到一條 Allow 就停止判斷,同一個帳號內,Identity-based Policy、Permissions Boundary、SCP 與資源政策都可能影響最後結果。
到了跨帳號情境,還會多一道條件:來源帳號與目標帳號都必須同意這次存取。
假設應用程式執行在 Account A,使用 OrderApiRole;它需要讀取 Account B 中 shared-product-data-prod Bucket 的物件。
這裡不需要替 Account A 的應用程式建立一組 Account B 的 IAM User 與長期 Access Key。
比較常見的做法有兩種:
AssumeRole 取得暫時憑證,再以該 Role 操作資源。兩種方法都能完成跨帳號存取,但適合的範圍不同。
如果 Account A 的 Role 要直接讀取 Account B 的 S3 Bucket,AWS 會分別檢查兩個帳號:
s3:GetObject。只有其中一邊設定 Allow 仍然不夠。
例如,Account A 的 OrderApiRole 需要以下權限:
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::shared-product-data-prod/*"
}
Account B 的 Bucket Policy 則要允許這個 Role:
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:role/OrderApiRole"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::shared-product-data-prod/*"
}
來源端回答的是「這個 Role 能不能發出請求」,目標端回答的是「這個 Bucket 願不願意接受它」,任何一邊沒有允許,或其中存在符合條件的明確 Deny,請求都會失敗。
這種方式下,應用程式仍然使用 Account A 的 OrderApiRole,不需要切換身分,也不需要另外取得一組 Account B 的暫時憑證。
另一種方式是在 Account B 建立一個 Role,例如 ProductDataReadRole,並在它的 Trust Policy 中信任 Account A 的 OrderApiRole。
Account A 必須允許原本的 Role 呼叫:
sts:AssumeRole
Account B 的 Trust Policy 則要接受來源 Role:
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:role/OrderApiRole"
},
"Action": "sts:AssumeRole"
}
完成 AssumeRole 後,AWS STS 會回傳一組有期限的暫時憑證,應用程式接下來不再以 Account A 的 OrderApiRole 操作資源,而是以 Account B 的 ProductDataReadRole 身分執行。
至於它能讀取哪些 Bucket、Secrets 或其他資源,則由 ProductDataReadRole 的 Permissions Policy 決定。
這裡很容易混淆兩種 Policy:
Trust Policy 允許 AssumeRole,不代表取得 Role 後就自動擁有 Account B 的所有權限。
我會先看這次存取的範圍,而不是把 AssumeRole 當成所有跨帳號需求的固定答案。
| 做法 | 適合情況 | 需要承擔的管理責任 |
|---|---|---|
| Resource-based Policy 直接授權 | 只存取少數資源,而且服務支援資源政策 | 來源與目標帳號都要維護 Policy,做法也會依服務而異 |
| AssumeRole | 要操作目標帳號中的多項資源或多種服務 | 應用程式要取得並更新暫時憑證,目標帳號要維護 Role 與 Trust Policy |
如果需求只是讓一個 Role 讀取一個 S3 Bucket,直接使用 Identity-based Policy 加上 Bucket Policy,通常比較直接,應用程式不必多做一次身分切換,Account B 也能在 Bucket 上明確看出哪些外部 Principal 可以存取。
但 Resource-based Policy 不是所有服務都支援,而且當需求從一個 Bucket 擴大成多個 Bucket、Secrets Manager、DynamoDB 或其他資源時,權限可能分散在多份資源政策中。這時改用 AssumeRole,可以把 Account B 內的權限集中在一個 Role 管理。
在「Account A 的單一應用程式,只需要讀取 Account B 的一個 S3 Bucket」的限制下,可以選擇由 Account A 的 Identity-based Policy 與 Account B 的 Bucket Policy 共同授權,而不額外建立 AssumeRole 流程,這個做法比較直接,但也接受兩個帳號必須同步維護 Policy,而且未來擴大到其他服務時可能需要改用 AssumeRole 的責任。
如果 S3 物件使用 SSE-KMS 加密,即使兩邊的 S3 Policy 都已經允許,呼叫身分仍然需要對 KMS Key 具有 kms:Decrypt 權限。
跨帳號使用 SSE-KMS 時,還需要使用 Customer managed key,並同時設定來源端的 IAM 權限與目標端的 KMS Key Policy,若只設定 Bucket Policy,不代表加密後的物件一定能成功讀取。
因此,跨帳號存取至少要確認:
當第二個、第三個目標服務陸續加入,或 Bucket Policy 開始塞入大量跨帳號 Principal,就可以評估看看是否要採用 AssumeRole 的方式;相反地,如果只有少量支援 Resource-based Policy 的資源需要共享,建立額外 Role 與憑證切換流程反而可能增加不必要的複雜度。
今天討論的是應用程式或工作負載之間的跨帳號存取,到這裡,我們已經知道跨帳號存取可以透過 AssumeRole 或 Resource-based Policy 完成,下一篇會實際帶大家設定一次,看看兩種做法的效果與差異。