رفض الوصول إلى صورة S3 العامة: لماذا يتجاوز Block Public Access إعداد ACL للكائن؟
رفعت صورة إلى S3، ضبطت الكائن على 'عام'، ثم فتحت الرابط المباشر — فظهر لك AccessDenied. المشكلة ليست في صلاحية الكائن نفسه، بل في طبقة تحكم أعلى منه تُلغي كل إعدادات ACL قبل أن يُقيّمها S3 أصلاً، وهي ميزة Block Public Access.
TL;DR — ملخص سريع
| الطبقة | ما تفعله | الأولوية |
|---|---|---|
| Block Public Access على مستوى الحساب | تمنع أي وصول عام لجميع الـ Buckets في الحساب | الأعلى |
| Block Public Access على مستوى الـ Bucket | تمنع الوصول العام لهذا الـ Bucket تحديداً | ثانية |
| Bucket Policy | تُحدد من يصل وبأي شروط | تُقيَّم فقط إذا لم يمنعها BPA |
| Object ACL | تُحدد صلاحية الكائن الفردي | تُقيَّم فقط إذا لم يمنعها BPA |
كيف يعمل Block Public Access في S3
عندما يصل طلب إلى S3، لا يبدأ التقييم من سياسة الـ Bucket أو ACL الكائن — بل يبدأ من إعدادات Block Public Access. هذه الإعدادات تعمل كحاجز خارجي يُقيَّم قبل أي منطق آخر. إذا كان أي من الإعدادات الأربعة مُفعَّلاً على مستوى الحساب أو الـ Bucket، يرفض S3 الطلب العام فوراً دون النظر في سياسات الـ Bucket أو ACLs على الإطلاق.
الإعدادات الأربعة لـ Block Public Access هي:
- BlockPublicAcls — يمنع تعيين ACLs عامة جديدة على الـ Bucket أو الكائنات.
- IgnorePublicAcls — يتجاهل جميع ACLs العامة الموجودة، حتى لو كانت مضبوطة على 'public-read'.
- BlockPublicPolicy — يمنع إضافة سياسات Bucket تمنح وصولاً عاماً.
- RestrictPublicBuckets — يقيّد الوصول العام حتى لو كانت سياسة الـ Bucket تسمح به.
الإعداد الذي يُسبب مشكلتك غالباً هو IgnorePublicAcls — فحتى لو ضبطت الكائن على public-read، يتجاهل S3 هذا الإعداد تماماً طالما هذا الخيار مُفعَّل.
GET Object"] --> B{"Block Public Access
على مستوى الحساب؟"} B -- "مُفعَّل" --> R1["❌ رفض فوري
AccessDenied"] B -- "مُعطَّل" --> C{"Block Public Access
على مستوى الـ Bucket؟"} C -- "مُفعَّل" --> R2["❌ رفض فوري
AccessDenied"] C -- "مُعطَّل" --> D{"هل توجد
Bucket Policy؟"} D -- "نعم" --> E{"هل تسمح
Bucket Policy؟"} E -- "نعم" --> G["✅ وصول مسموح"] E -- "لا" --> R3["❌ رفض
AccessDenied"] D -- "لا" --> F{"هل ACL الكائن
public-read؟"} F -- "نعم" --> G F -- "لا" --> R4["❌ رفض
AccessDenied"] style R1 fill:#ff4444,color:#fff style R2 fill:#ff4444,color:#fff style R3 fill:#ff4444,color:#fff style R4 fill:#ff4444,color:#fff style G fill:#00aa44,color:#fff
- Block Public Access على مستوى الحساب: أول نقطة تحقق. إذا كان مُفعَّلاً، يُرفض الطلب فوراً لجميع الـ Buckets في الحساب.
- Block Public Access على مستوى الـ Bucket: إذا اجتاز الطلب مستوى الحساب، يُفحص إعداد الـ Bucket المحدد. أي إعداد BPA مُفعَّل هنا يرفض الطلب.
- تقييم Bucket Policy و ACLs: فقط إذا كانت جميع إعدادات BPA مُعطَّلة على كلا المستويين، يبدأ S3 في تقييم سياسة الـ Bucket وACL الكائن لتحديد الصلاحية النهائية.
تشخيص مشكلة رفض الوصول إلى S3 خطوة بخطوة
الخطوة 1: فحص Block Public Access على مستوى الحساب
قبل فحص الـ Bucket نفسه، تحقق من إعدادات الحساب — فهي تُلغي إعدادات الـ Bucket بالكامل. كثير من المهندسين يقضون وقتاً في تعديل سياسات الـ Bucket دون أن يدركوا أن الحساب نفسه يمنع أي وصول عام.
aws s3control get-public-access-block \
--account-id 123456789012
إذا أعاد أي من الحقول الأربعة قيمة true، فهذا هو السبب الجذري. لتعطيله على مستوى الحساب:
aws s3control put-public-access-block \
--account-id 123456789012 \
--public-access-block-configuration BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false
تحذير: تعطيل BPA على مستوى الحساب يؤثر على جميع الـ Buckets. قيّم هذا القرار بعناية وفق متطلبات الأمان لديك.
الخطوة 2: فحص Block Public Access على مستوى الـ Bucket
إذا كانت إعدادات الحساب سليمة، انتقل إلى الـ Bucket المحدد. هذا هو الإعداد الذي يُفعَّل افتراضياً عند إنشاء Bucket جديد منذ عام 2023.
aws s3api get-public-access-block \
--bucket your-bucket-name
إذا أعاد IgnorePublicAcls: true أو RestrictPublicBuckets: true، فهذا يُفسر لماذا لا تعمل ACL الكائن. لتعطيل BPA على مستوى الـ Bucket فقط:
aws s3api put-public-access-block \
--bucket your-bucket-name \
--public-access-block-configuration BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false
الخطوة 3: التحقق من ACL الكائن
بعد التأكد من تعطيل BPA، تحقق من أن ACL الكائن مضبوط فعلاً على public-read. في كثير من الحالات، يظن المهندس أنه ضبط الكائن على 'عام' من الواجهة، لكن الإعداد لم يُحفظ بسبب وجود BPA وقت الرفع.
aws s3api get-object-acl \
--bucket your-bucket-name \
--key path/to/your-image.jpg
إذا لم يظهر AllUsers في قائمة المنح، اضبط ACL الكائن يدوياً:
aws s3api put-object-acl \
--bucket your-bucket-name \
--key path/to/your-image.jpg \
--acl public-read
الخطوة 4: استخدام Bucket Policy بدلاً من ACL (النهج المُوصى به)
الاعتماد على Object ACLs لتوفير الوصول العام نهج قديم. AWS تُوصي باستخدام Bucket Policy لأنها أوضح وأسهل في التدقيق. هذا النهج يعمل حتى لو كانت BlockPublicAcls وIgnorePublicAcls مُفعَّلتين، طالما أن BlockPublicPolicy وRestrictPublicBuckets مُعطَّلتان.
🔽 انقر لعرض سياسة Bucket للوصول العام للقراءة
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}
aws s3api put-bucket-policy \
--bucket your-bucket-name \
--policy file://bucket-policy.json
الخطأ الشائع: الخلط بين إعداد الكائن وإعداد الـ Bucket
السيناريو الذي يتكرر كثيراً: مهندس يرفع صورة، يضغط 'Make Public' من AWS Console، يحصل على AccessDenied، ثم يذهب إلى إعدادات الـ Bucket ويُعطّل BPA، ويُعيد المحاولة — لكن المشكلة تستمر.
السبب: عند ضغطه على 'Make Public' وكان BPA مُفعَّلاً، لم تُحفظ ACL الكائن أصلاً. بعد تعطيل BPA، الكائن لا يزال بدون ACL عامة. يجب إعادة ضبط ACL الكائن بعد تعطيل BPA.
Block Public Access يشبه قفل رئيسي على باب المبنى — حتى لو كان مفتاح الغرفة الداخلية معك، القفل الرئيسي يمنعك من الدخول قبل أن تصل إليه.
- الحالة الأولى (BPA مُفعَّل): حتى مع ACL عامة على الكائن، يرفض S3 الطلب لأن
IgnorePublicAclsيتجاهل ACL قبل تقييمها. - الحالة الثانية (BPA مُعطَّل + ACL عامة): الطلب يصل إلى مرحلة تقييم ACL ويُمنح الوصول.
- الحالة الثالثة (BPA مُعطَّل + Bucket Policy): النهج الأنظف — لا اعتماد على ACLs الكائنات الفردية.
IAM Policy للتشخيص والإدارة
إذا كنت تُشخّص هذه المشكلة بصلاحيات محدودة، تحتاج على الأقل إلى الصلاحيات التالية:
🔽 انقر لعرض IAM Policy للتشخيص
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3PublicAccessDiagnostics",
"Effect": "Allow",
"Action": [
"s3:GetBucketPublicAccessBlock",
"s3:PutBucketPublicAccessBlock",
"s3:GetObjectAcl",
"s3:PutObjectAcl",
"s3:GetBucketPolicy",
"s3:PutBucketPolicy",
"s3control:GetPublicAccessBlock",
"s3control:PutPublicAccessBlock"
],
"Resource": [
"arn:aws:s3:::your-bucket-name",
"arn:aws:s3:::your-bucket-name/*"
]
},
{
"Sid": "S3AccountLevelAccess",
"Effect": "Allow",
"Action": [
"s3control:GetPublicAccessBlock",
"s3control:PutPublicAccessBlock"
],
"Resource": "arn:aws:s3control::123456789012:account/123456789012"
}
]
}
لاحظ أن s3control:GetPublicAccessBlock وs3control:PutPublicAccessBlock على مستوى الحساب يتطلبان مورداً مختلفاً عن صلاحيات الـ Bucket العادية — خطأ شائع عند كتابة سياسات IAM لهذا السيناريو.
الخلاصة والخطوات التالية لحل رفض الوصول في S3
جذر مشكلة رفض الوصول في S3 لملفات عامة يكون في معظم الحالات في إعدادات Block Public Access، وليس في ACL الكائن. الترتيب الصحيح للتشخيص: الحساب أولاً، ثم الـ Bucket، ثم الكائن. وإذا كنت تبني نظاماً جديداً، استخدم Bucket Policy بدلاً من Object ACLs — فهي أوضح في التدقيق وأكثر توافقاً مع ممارسات AWS الحديثة.
- راجع توثيق Block Public Access الرسمي لفهم كل إعداد بتفصيل.
- استخدم IAM Policy Simulator للتحقق من صلاحيات معقدة.
- فعّل S3 Server Access Logging لتتبع طلبات
AccessDeniedمستقبلاً.
مسرد المصطلحات
| المصطلح | التعريف |
|---|---|
| Block Public Access (BPA) | مجموعة إعدادات S3 تمنع الوصول العام على مستوى الحساب أو الـ Bucket، تُقيَّم قبل أي سياسة أو ACL |
| Object ACL | قائمة تحكم وصول مرتبطة بكائن S3 فردي تُحدد من يمكنه قراءته أو كتابته |
| Bucket Policy | سياسة JSON مرتبطة بـ Bucket تُحدد قواعد الوصول لجميع الكائنات داخله |
| IgnorePublicAcls | إعداد BPA يتجاهل جميع ACLs العامة الموجودة على الـ Bucket والكائنات |
| RestrictPublicBuckets | إعداد BPA يقيّد الوصول العام حتى لو كانت Bucket Policy تسمح به صراحةً |
تعليقات
إرسال تعليق