返回列表

AWS企業帳號代開 亞馬遜雲 S3 提示訪問拒絕怎麼解決

亞馬遜雲AWS / 2026-07-21 19:55:35

第一章:先看懂「訪問拒絕」到底在拒絕什麼

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 寫對,整個流程就會回到可預期的正常運作。

Telegram售前客服
客服ID
@cloudcup
联系
Telegram售后客服
客服ID
@yanhuacloud
联系