S3 Access Denied trotz öffentlichem Objekt: Block Public Access verstehen und beheben
Du hast ein Bild in S3 hochgeladen, die Berechtigungen auf 'öffentlich' gesetzt – und trotzdem liefert die URL nur ein nichtssagendes Access Denied. Das ist einer der häufigsten Stolpersteine bei S3, weil AWS zwei unabhängige Kontrollschichten betreibt, die sich gegenseitig überschreiben können. Die Objekt-ACL allein reicht nicht aus, wenn 'Block Public Access' auf Bucket-Ebene aktiv ist.
TL;DR: S3 Access Denied trotz öffentlichem Objekt
| Schicht | Einstellung | Wirkung bei Fehler |
|---|---|---|
| Block Public Access (Bucket) | Aktiv (Standard) | Überschreibt alle ACLs und Bucket-Policies – öffentlicher Zugriff wird blockiert |
| Objekt-ACL | public-read gesetzt | Wirkungslos, solange Block Public Access aktiv ist |
| Bucket Policy | Kein s3:GetObject für * | Kein anonymer Zugriff ohne explizite Allow-Policy |
| Object Ownership | Bucket owner enforced | ACLs sind deaktiviert – public-read hat keine Wirkung |
Wie S3-Zugriffskontrolle wirklich funktioniert
S3 wertet Zugriffsanfragen in einer festen Reihenfolge aus. 'Block Public Access' ist dabei keine normale IAM-Policy – es ist ein separater Mechanismus, der vor der Policy-Auswertung greift und öffentliche Zugriffe pauschal unterbindet. Das bedeutet: Selbst wenn Objekt-ACL und Bucket Policy öffentlichen Zugriff erlauben würden, blockiert dieser Schalter die Anfrage, bevor sie die eigentliche Berechtigungsprüfung erreicht.
Block Public Access verhält sich wie ein Hauptschalter vor dem Sicherungskasten. Ob die einzelnen Sicherungen (ACLs, Policies) durchgeschaltet sind oder nicht, spielt keine Rolle – wenn der Hauptschalter offen ist, kommt kein Strom durch.
Zusätzlich hat AWS mit der Einstellung 'Object Ownership: Bucket owner enforced' ACLs auf Bucket-Ebene vollständig deaktiviert. Wer also public-read per ACL setzt, bemerkt möglicherweise nicht einmal, dass diese Einstellung stillschweigend ignoriert wird.
an S3-URL"] --> B{"Block Public Access
aktiv?"} B -- "Ja" --> C["Access Denied
Auswertung endet hier"] B -- "Nein" --> D{"Object Ownership:
BucketOwnerEnforced?"} D -- "Ja" --> E["ACLs ignoriert
weiter zu Bucket Policy"] D -- "Nein" --> F["ACLs werden
ausgewertet"] E --> G{"Bucket Policy erlaubt
s3:GetObject für *?"} F --> H{"Objekt-ACL
public-read gesetzt?"} G -- "Ja" --> I["Zugriff gewährt"] G -- "Nein" --> C H -- "Ja" --> I H -- "Nein" --> C
- Anfrage eingehend: Ein anonymer Client ruft die S3-URL auf.
- Block Public Access: AWS prüft zuerst, ob Block Public Access für den Bucket oder das Konto aktiv ist. Ist das der Fall, endet die Auswertung hier mit Access Denied.
- Object Ownership: Falls ACLs deaktiviert sind ('Bucket owner enforced'), werden Objekt-ACLs ignoriert.
- Bucket Policy: Gibt es eine explizite
Allow-Policy für anonymen Zugriff (Principal: "*")? - Objekt-ACL: Nur wenn ACLs aktiviert sind und Block Public Access inaktiv ist, wird
public-readberücksichtigt. - Zugriff gewährt oder verweigert: Erst wenn alle Schichten passiert sind, wird das Objekt ausgeliefert.
S3 Access Denied diagnostizieren: Schritt-für-Schritt
Schritt 1: Block Public Access auf Bucket-Ebene prüfen
Block Public Access ist bei neuen Buckets standardmäßig vollständig aktiviert. Das ist der häufigste Grund für Access Denied bei vermeintlich öffentlichen Objekten – und wird im S3-Konsolen-Workflow beim Hochladen nicht explizit angezeigt. Prüfe zuerst diesen Schalter, bevor du Zeit mit ACLs oder Policies verbringst.
aws s3api get-public-access-block \
--bucket DEIN-BUCKET-NAME
Erwartete Ausgabe, wenn Block Public Access vollständig aktiv ist:
{
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}
}
Alle vier Werte auf true bedeuten: Kein öffentlicher Zugriff möglich, unabhängig von ACLs oder Bucket Policy.
Schritt 2: Block Public Access auf Kontoebene prüfen
Selbst wenn du Block Public Access auf Bucket-Ebene deaktivierst, kann die Kontoebene den Zugriff weiterhin blockieren. Diese Einstellung wird häufig übersehen, weil sie in einem anderen Bereich der Konsole liegt und separat verwaltet wird.
aws s3control get-public-access-block \
--account-id 123456789012
Wenn hier ebenfalls alle vier Werte true sind, muss auch diese Einstellung angepasst werden – Bucket-Ebene allein reicht dann nicht.
Schritt 3: Object Ownership prüfen
Wenn 'Object Ownership' auf BucketOwnerEnforced gesetzt ist, sind ACLs deaktiviert. Das bedeutet: Das Setzen von public-read per ACL hat keinerlei Wirkung. Dieser Zustand ist nicht offensichtlich – die API akzeptiert den ACL-Befehl ohne Fehlermeldung, ignoriert ihn aber stillschweigend.
aws s3api get-bucket-ownership-controls \
--bucket DEIN-BUCKET-NAME
Wenn die Ausgabe BucketOwnerEnforced zeigt, musst du statt einer ACL eine Bucket Policy für öffentlichen Zugriff verwenden.
Schritt 4: Bucket Policy prüfen
Nachdem Block Public Access deaktiviert und Object Ownership geklärt ist, braucht der Bucket eine explizite Policy, die anonymen Lesezugriff erlaubt. Ohne diese Policy bleibt der Zugriff verweigert, auch wenn alle anderen Einstellungen korrekt sind.
aws s3api get-bucket-policy \
--bucket DEIN-BUCKET-NAME
Wenn keine Policy existiert oder s3:GetObject für Principal: "*" fehlt, ist das der nächste Ansatzpunkt.
Schritt 5: Objekt-ACL prüfen (nur wenn ACLs aktiviert sind)
Erst wenn die vorherigen Schichten geklärt sind, lohnt sich ein Blick auf die Objekt-ACL. Wenn Block Public Access aktiv oder ACLs deaktiviert sind, ist dieser Schritt irrelevant.
aws s3api get-object-acl \
--bucket DEIN-BUCKET-NAME \
--key pfad/zum/bild.jpg
S3 Access Denied beheben: Die zwei Lösungswege
Je nach Konfiguration gibt es zwei valide Ansätze. Der empfohlene Weg ist die Bucket Policy – sie funktioniert unabhängig von der Object Ownership-Einstellung und ist expliziter steuerbar.
Lösung 1 (Empfohlen): Block Public Access deaktivieren und Bucket Policy setzen
Schritt 1: Block Public Access auf Bucket-Ebene deaktivieren.
🔽 Block Public Access deaktivieren (CLI)
aws s3api put-public-access-block \
--bucket DEIN-BUCKET-NAME \
--public-access-block-configuration \
"BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false"
Schritt 2: Bucket Policy für öffentlichen Lesezugriff setzen. Passe den Pfad im Resource-Feld an, wenn nur bestimmte Objekte öffentlich sein sollen (z.B. arn:aws:s3:::DEIN-BUCKET-NAME/public/*).
🔽 Bucket Policy für öffentlichen Lesezugriff (JSON)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::DEIN-BUCKET-NAME/*"
}
]
}
aws s3api put-bucket-policy \
--bucket DEIN-BUCKET-NAME \
--policy file://bucket-policy.json
Lösung 2 (Legacy): ACL-basierter öffentlicher Zugriff
Dieser Weg funktioniert nur, wenn Object Ownership nicht auf BucketOwnerEnforced gesetzt ist. AWS empfiehlt, ACLs für die meisten Anwendungsfälle zu deaktivieren und stattdessen Bucket Policies zu verwenden.
aws s3api put-object-acl \
--bucket DEIN-BUCKET-NAME \
--key pfad/zum/bild.jpg \
--acl public-read
Dieser Befehl schlägt fehl oder hat keine Wirkung, wenn Block Public Access aktiv oder ACLs deaktiviert sind.
Erfahrung aus der Praxis: Die stille Falle
Ein typisches Muster: Ein Entwickler lädt ein Bild hoch, setzt die ACL auf public-read – die Konsole bestätigt die Aktion ohne Fehlermeldung. Die URL liefert trotzdem Access Denied. Der erste Verdacht fällt auf die ACL selbst, dann auf die Bucket Policy. Beides wird geprüft, alles sieht korrekt aus.
Die eigentliche Ursache: Object Ownership war auf BucketOwnerEnforced gesetzt. Die ACL wurde zwar akzeptiert, aber vollständig ignoriert. Es gibt keinen Hinweis in der Konsole oder der API-Antwort, dass der Befehl wirkungslos war. Das CloudTrail-Log zeigt den PutObjectAcl-Aufruf als erfolgreich – was technisch korrekt ist, aber irreführend.
Der Fix war eine Bucket Policy mit s3:GetObject für Principal: "*". Zwei Minuten Arbeit – nach einer Stunde Debugging in der falschen Schicht.
Access Denied"] --> M["Fehldiagnose:
ACL und Policy geprüft"] M --> U["Eigentliche Ursache:
BucketOwnerEnforced"] U --> F["Fix:
Bucket Policy gesetzt"] F --> R["Ergebnis:
Zugriff funktioniert"]
- Symptom: Access Denied trotz gesetzter public-read ACL.
- Erste Diagnose: ACL-Einstellung und Bucket Policy geprüft – beide schienen korrekt.
- Eigentliche Ursache: Object Ownership auf BucketOwnerEnforced – ACLs werden ignoriert, ohne Fehlermeldung.
- Fix: Bucket Policy mit explizitem Allow für s3:GetObject gesetzt.
IAM-Berechtigungen für die Diagnose
Für die oben genannten CLI-Befehle benötigst du folgende IAM-Berechtigungen. Beachte, dass s3:GetPublicAccessBlock auf Kontoebene über s3control aufgerufen wird und eine separate Berechtigung erfordert.
🔽 IAM Policy für S3-Diagnose (Least Privilege)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketPublicAccessBlock",
"s3:PutBucketPublicAccessBlock",
"s3:GetBucketOwnershipControls",
"s3:GetBucketPolicy",
"s3:PutBucketPolicy",
"s3:GetObjectAcl",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::DEIN-BUCKET-NAME",
"arn:aws:s3:::DEIN-BUCKET-NAME/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetAccountPublicAccessBlock"
],
"Resource": "*"
}
]
}
Hinweis: s3:GetAccountPublicAccessBlock erfordert Resource: "*", da es sich um eine kontoweite Einstellung handelt, die nicht auf einzelne Bucket-ARNs eingeschränkt werden kann.
S3 Access Denied: Wrap-Up und nächste Schritte
S3-Zugriffssteuerung ist mehrschichtig – und 'Block Public Access' ist bewusst so konzipiert, dass es alle anderen Einstellungen überschreibt. Für produktive Workloads ist öffentlicher S3-Zugriff selten die richtige Wahl. Erwäge stattdessen CloudFront mit Origin Access Control (OAC), um Inhalte kontrolliert auszuliefern, ohne den Bucket direkt öffentlich zu machen.
Weiterführende Dokumentation:
- AWS Dokumentation: Blocking public access to your Amazon S3 storage
- AWS Dokumentation: Controlling object ownership
- AWS Dokumentation: Using bucket policies
Glossar
| Begriff | Bedeutung |
|---|---|
| Block Public Access | AWS-Mechanismus auf Konto- und Bucket-Ebene, der öffentlichen Zugriff pauschal unterbindet – unabhängig von ACLs und Bucket Policies. |
| Object ACL | Zugriffskontrollliste auf Objektebene. Wird ignoriert, wenn 'Object Ownership: Bucket owner enforced' aktiv ist. |
| Bucket Policy | Ressourcenbasierte IAM-Policy auf Bucket-Ebene. Ermöglicht feingranulare Zugriffssteuerung, auch für anonyme Zugriffe. |
| Object Ownership | Bucket-Einstellung, die steuert, ob ACLs aktiv sind. 'BucketOwnerEnforced' deaktiviert ACLs vollständig. |
| Principal: * | IAM-Policy-Element für anonymen (nicht authentifizierten) Zugriff. Erforderlich für öffentlich zugängliche S3-Objekte via Bucket Policy. |
Kommentare
Kommentar veröffentlichen