AWS企業帳號代開 亞馬遜雲 S3 提示訪問拒絕怎麼解決
第一章:先看懂「訪問拒絕」到底在拒絕什麼
S3 的「AccessDenied」(或中文顯示「訪問被拒絕」)看似一句話,實際上可能是幾種不同原因:你沒有權限、桶策略沒放行、物件被加密但你沒有 KMS 權限、或是你想公開但被 Public Access Block 阻擋。很多人一上來就改程式或亂調 ACL,結果越改越亂。
要解決它,第一步不是猜,而是把「拒絕原因」拆開。S3 的錯誤資訊通常會包含幾個線索:請求方法(GET/PUT/HEAD)、你嘗試存取的資源(Bucket/Key)、以及 AWS 可能提供的錯誤類型與訊息文字。即使訊息不夠完整,也至少要確認:你是從哪個環境呼叫(本機程式、Lambda、EC2、外部服務),以及你使用的是哪種身分(Access Key、角色 AssumeRole、或匿名)。
接著要先建立心法:最後生效的權限是多層設定的合成結果。對 S3 來說,常見的層包括:IAM 使用者/角色政策、Bucket Policy、物件 ACL(若還在用)、Block Public Access、以及加密相關的 KMS 權限。任何一層不允許,都可能導致拒絕。
第二章:快速定位錯誤來源的三個關鍵問題
你可以用「三問」快速把問題收斂到少數幾類。這三問不需要你先改任何設定,但會決定你接下來該查哪裡。
AWS企業帳號代開 小節一:你是誰?(身份與憑證來源)
確認你使用的憑證到底是什麼。很多 AccessDenied 是因為以為呼叫方用的是某個角色,實際上走的是另一組憑證。檢查方法取決於你使用的環境:
- 本機或伺服器程式:確認環境變數、AWS Profile、或設定檔使用的 Access Key。
- EC2:確認 instance profile(角色)與附加的 IAM Policy。
- Lambda:確認執行角色(Execution Role)是否真的包含 S3 存取權限。
- 跨帳號:確認是否用了 AssumeRole,且信任關係(Trust Policy)正確。
如果你是跨帳號,還要特別注意:即便對方帳號的角色有 S3 權限,桶策略仍可能不允許你方主體。
小節二:你在存取什麼?(Bucket 還是 Object)
S3 權限常常是以資源粒度授予的。你要存取的是整個桶(Bucket level)還是某個物件路徑(Object key prefix)?常見陷阱有:
- AWS企業帳號代開 只給了「列出桶」(s3:ListBucket) 的權限,但你真正要讀的是物件(需要 s3:GetObject)。
- 你給了 s3:GetObject,但 policy 的 Resource 寫法沒有包含正確的 key(例如只允許前綴 /images/,但你存的是 /backup/)。
- 你呼叫的是 HEAD(例如 SDK 自動做存在性檢查),但權限只給了 GET。
因此先確認:錯誤發生在 GET、PUT、HEAD、還是 DELETE。這會直接決定要找的權限動作。
小節三:你用的是哪種存取方式?(私有/公有、簽名/非簽名)
AccessDenied 也常出現在你以為應該能「公開讀取」的情境。但 S3 現代的預設是偏向安全:即使 Bucket Policy 寫了允許公開讀取,若啟用了 Block Public Access,仍可能封鎖。
此外,若你使用的是 URL 或前端直接存取,需要確認是否是:
- 匿名存取(沒有簽名)。
- 透過預簽名 URL(Presigned URL)。
- 透過身份(使用者/角色)登入後透過 SDK 存取。
這三種方式對權限的要求不同。混用會導致拒絕。
第三章:逐項檢查的排查流程(按優先順序)
下面是一套實戰流程,建議你從上到下做,通常能快速定位問題所在。你不需要一次全做,因為每一步都能縮小範圍。
小節一:先確認 Public Access Block(最常見的「看起來合理但就是不行」)
如果你的目標是讓某些物件「可公開讀」,第一件要查的是:Bucket 設定裡的 Public Access Block。S3 的 Block Public Access 會在底層阻止公有存取。常見情境是:你已經在 Bucket Policy 允許了 public,但它仍被擋住。
你可以在 S3 目的桶的設定中查到類似以下選項:
- Block all public access
- Block public ACLs
- Ignore public ACLs
- Restrict public buckets
若你看到這些選項啟用,且你想要「匿名公開」,那就必須重新設計方式。通常比較安全的做法是使用 CloudFront 或使用預簽名 URL,讓你仍能控管存取。
AWS企業帳號代開 如果你確實要公開讀,仍然需要 Bucket Policy 與物件 ACL 的設定方向一致。一般來說,若你要「桶級」公開讀,建議只用 Bucket Policy 控制,而不要依賴舊式 ACL,避免互相打架。
小節二:檢查 Bucket Policy 是否真的允許你的主體與動作
AWS企業帳號代開 Bucket Policy 是 S3 最關鍵的一層。請注意兩件事:
- Bucket Policy 的主體(Principal)要匹配你實際使用的身份(IAM 角色 ARN、帳號、或匿名)。
- AWS企業帳號代開 Bucket Policy 的 Resource 要匹配你存取的物件路徑與動作。
很多 AccessDenied 不是「完全沒有權限」,而是「只允許了別的 ARN」。例如你在政策裡寫的是角色 A,但程式實際使用的是角色 B;或你寫了 arn:aws:iam::123456789012:role/MyRole,但實際是 arn:aws:iam::123456789012:user/MyUser。
此外,Bucket Policy 常見的 Resource 寫法錯誤也會導致拒絕。對物件讀取通常要是:
- 桶本身:
arn:aws:s3:::your-bucket-name - 桶內物件:
arn:aws:s3:::your-bucket-name/your/key/prefix/*
你若只給了桶本身,對物件 GET/PUT 仍會失敗。
小節三:確認 IAM 的動作是否正確(Get/Put/Head/List)
假設 Bucket Policy 沒問題,下一步就是看 IAM policy。你要確保:
- 讀取:s3:GetObject(以及可能需要 s3:GetObjectVersion 若是版本控制)。
- 寫入:s3:PutObject、s3:AbortMultipartUpload(若有分段上傳)。
- 刪除:s3:DeleteObject。
- 列出:s3:ListBucket(Resource 指向桶本身,且要帶上條件 Prefix/Delimiter 時也要匹配)。
- SDK 可能會先 HEAD:s3:HeadObject。
一個典型案例:前端用 SDK 上傳或下載時,SDK 先做 HEAD 檢查檔案是否存在,再決定是否 GET。你只給了 GetObject,但沒給 HeadObject,就可能仍然 AccessDenied。
另外要注意條件條款。例如只允許特定來源 IP、VPC endpoint、或要求特定的加密條件(如 aws:SecureTransport)。如果環境不符合條件,也會拒絕。
小節四:處理 KMS 加密的權限(常被忽略,卻很致命)
如果你的桶使用了 SSE-KMS(伺服器端加密使用 KMS),即使你在 IAM/Policy 已有 s3:GetObject 權限,也可能在解密階段被拒絕。S3 會需要你具備對 KMS key 的權限,例如:
- kms:Decrypt(讀取解密)
- kms:Encrypt(寫入加密)
- kms:GenerateDataKey
而且 KMS 的政策通常要同時滿足:KMS key policy 與 IAM identity policy。只改一邊常常不夠。
排查方式:
- 查看 S3 物件的加密設定(在物件屬性或桶層級)。
- 確認使用的是哪個 KMS key(key ARN)。
- 檢查 KMS key policy 是否允許你的主體使用該 key 的對應操作。
如果你用的是預設的 AWS 管理 KMS key 或自建 key,處理方式略有差異,但核心仍是確保主體有解密/加密與資料金鑰生成的權限。
小節五:物件層級的 ACL 與擁有者(在少數情況仍會踩雷)
ACL 在現代設計裡通常不建議成為主方案,但如果你的帳戶或桶仍沿用 ACL,AccessDenied 可能與 ACL 有關。尤其當桶啟用了「對擁有者更嚴格」的設定(例如 Object Ownership 相關選項),舊 ACL 可能不再如你預期生效。
建議你檢查:
- 物件是否屬於你希望的擁有者(Object ownership)。
- 是否存在明顯的 ACL 公開設定被忽略。
- 你是否在使用 CopyObject、跨帳號上傳後導致擁有者改變。
一般而言,若你走的是 Bucket Policy + 禁用/忽略公開 ACL 的路線,就能減少 ACL 帶來的不可預期行為。
小節六:區域、端點與簽名(看似權限,實際是請求落點不對)
不是所有「拒絕」都是權限問題。還有一些常見誤區會讓你以為是 AccessDenied,其實是請求沒有被正確簽名或打到錯誤區域。
- AWS企業帳號代開 確認 SDK/S3 endpoint 使用正確區域(us-east-1 等)。
- 如果使用自寫簽名,確保簽名版本、服務名(s3)、以及時區/過期時間正確。
- 如果是臨時憑證(STS),確認是否過期,且權限還在。
這些情況通常也會伴隨其他錯誤訊息(例如 SignatureDoesNotMatch、ExpiredToken),但有時候前端只看到 AccessDenied。當你排查完權限仍不對,就要回頭檢查端點與簽名。
第四章:用例子把政策寫對(避免反覆試錯)
政策寫得正確,比不斷重試更快。下面用幾個常見目標,給你「方向正確」的政策模板與要點。你可以依你的桶名與 prefix 改寫。
小節一:讓某個角色可以讀取指定資料夾下的物件
假設你只想讓角色能讀取 images/ 前綴下的物件:
- IAM identity policy:給 s3:GetObject + s3:ListBucket(可選)
- Resource 必須包含物件路徑,並用
images/*。
你會需要注意:如果你要列出 images 內容,才要 ListBucket;如果你只要直接讀取特定物件,就不一定需要 ListBucket。
小節二:允許上傳(分段上傳需額外權限)
若你用大型檔案上傳,常見是 multipart upload。除了 s3:PutObject,你通常還需要:
- s3:AbortMultipartUpload
- (有時)s3:ListBucketMultipartUploads、s3:ListMultipartUploadParts
不然你會在上傳途中收到拒絕,但你只看 PutObject 會以為已經給了權限。
小節三:跨帳號讀取(桶策略才是關鍵)
跨帳號最常見的錯誤是:對方帳號給了 IAM 權限,但你的桶策略沒有信任他們。這種情況下,Bucket Policy 必須加入允許的 Principal。
此外,跨帳號讀取還要注意 Object ownership 與 ACL。建議統一使用所有者集中管理:讓桶擁有者取得物件所有權,並用桶策略控制讀取,而不是把 ACL 當主要手段。
AWS企業帳號代開 小節四:臨時公開(用預簽名 URL 替代「永久公有」)
很多團隊一開始就想把桶改成 public read,省事但風險高。更合理的方式是:桶保持私有,透過預簽名 URL 給使用者限定時間的下載權限。
這樣你仍能避免 Public Access Block 的衝突,且能保留審計與到期控制。AccessDenied 的原因也更好追:只要驗證簽名是否正確、憑證是否具備 s3:GetObject 與 KMS 解密權限,就能定位。
第五章:排查清單(你可以照順序打勾)
AWS企業帳號代開 當你真的遇到 AccessDenied,不要陷入「猜測式調參」。用下面清單逐項確認。你每完成一項,問題範圍就會縮小。
小節一:身份與資源
- [ ] 我用的憑證是哪個角色/使用者?(ARN 是否一致)
- [ ] 我存取的是 Bucket 還是特定 Object key?
- [ ] 我呼叫的是 GET/PUT/HEAD/List 哪個動作?
- [ ] 我的 Resource 路徑是否精確包含目標 prefix?
小節二:Bucket Policy 與 Block Public Access
- [ ] Bucket Policy 中是否正確允許 Principal 與動作?
- [ ] Bucket Policy 中是否正確寫了物件 Resource(含
/.../*)? - [ ] Public Access Block 是否阻擋我想要的模式(公開或半公開)?
小節三:IAM 權限是否完整
- [ ] 是否給了所有需要的動作(含 HeadObject/ListMultipart 等可能的額外動作)?
- [ ] 是否有條件條款(IP、VPC endpoint、SecureTransport)導致不符合?
小節四:KMS
- [ ] 桶是否使用 SSE-KMS?
- [ ] KMS key policy 與 IAM policy 是否同時允許 Decrypt/Encrypt/GenerateDataKey?
- [ ] 使用的 KMS key ARN 是否就是該物件所屬 key?
小節五:環境與簽名
- [ ] endpoint/region 是否正確?
- [ ] 預簽名 URL 是否未過期且簽名方法正確?
- [ ] 臨時憑證是否過期?
第六章:常見錯誤模式與解法(讓你少走彎路)
這一章整理一些「現場很常見」的 AccessDenied 型態。你對照一下,很快就能知道該往哪裡下手。
小節一:只給了 s3:GetObject,卻仍然拒絕
原因可能是:SDK 先 HEAD、或你存的是特定版本(需要 GetObjectVersion)、或 KMS 解密失敗。解法是補上 HeadObject、加上版本控制相關權限,並檢查 KMS。
小節二:桶政策允許 public,但仍然 AccessDenied
幾乎肯定是 Public Access Block 或同時啟用了「忽略 public ACLs」類設定。解法是:確認你採用的公開方式是否與 Block Public Access 的策略一致。若要公開內容,改用 CloudFront + OAC/签名或預簽名 URL,通常更穩。
小節三:跨帳號讀不到,對方 IAM 看起來有權限
這就是經典桶策略缺漏。解法:在你的 Bucket Policy 補上允許的 Principal(跨帳號角色/使用者)。同時檢查你桶內物件的所有權與加密設定。
小節四:能在控制台看到,但程式讀不到
控制台通常使用你登錄者的權限(或你是桶擁有者/管理員),而程式使用的是不同角色或不同憑證。解法:核對程式實際使用的角色 ARN 與 policy,並確保資源路徑匹配。
小節五:能 GET 但不能 PUT,或上傳中途失敗
寫入常需要更多動作,尤其 multipart upload。解法是依你上傳方式補齊 PutObject 與 multipart 相關權限,並檢查 KMS Encrypt 權限。
第七章:如何把修好後的權限維持乾淨(避免下次又爆)
修好了 AccessDenied 不代表結束。很多團隊修一次就加一個 Allow,最後政策膨脹、越來越難控管。更好的做法是把原則寫進流程裡。
小節一:最小權限,針對 prefix 授權
避免把 s3:* 給在所有物件。請針對你實際需要的前綴(例如 logs/、images/)授權,並把 Bucket Policy 與 IAM identity policy 的範圍一致化。
小節二:用一致的方案取代 ACL 依賴
若你已採用 Object Ownership 與 Bucket Policy 控制,盡量不要回頭用 ACL 亂救。ACL 與 Block Public Access 的組合容易造成行為偏差。
小節三:如果用 KMS,把權限寫成可維護
不要只在 IAM policy 補 Decrypt 卻忘了 KMS key policy。建議你明確列出 key ARN,並在需要時用條件(例如 kms:ViaService)限制使用情境,讓權限不至於過寬。
AWS企業帳號代開 小節四:使用測試主體與小範圍物件
每次調整策略,先用小範圍測試主體和少量物件驗證。你不需要拿整個桶當實驗室,這樣也能避免誤把敏感內容公開。
第八章:結語——別急著改程式,先把權限拼圖對齊
S3 的「訪問拒絕」通常不是難題,而是權限拼圖缺了一塊。你只要先確認身份是誰、動作是什麼、資源到底是哪個 Bucket/Key,再依序檢查 Bucket Policy、IAM、Block Public Access、KMS、以及可能的 ACL 與端點簽名,就能把問題從「看起來到處都可能」變成「明確定位、明確修復」。
下次再遇到 AccessDenied,你可以先停下來,用本文的排查清單逐項核對。多半你不需要大改架構,只要把那個最關鍵的 Allow/Resource/Principal 寫對,整個流程就會回到可預期的正常運作。

