AWS Certified CloudOps Engineer - Associate
سياسات IAM وأدواره
اللبنات التي يقوم عليها كل قرار تصريح في AWS: الكيانات الطالبة والهويات، وعناصر سياسة JSON، وسياسات الهوية مقابل سياسات الموارد، والمُدارة مقابل المضمَّنة، ولماذا يحمل الدور سياستين لا سياسة واحدة.
- فرّق بين الكيان الطالب والهوية، وسمِّ أنواع السياسات التي ترفقها AWS بكل منهما
- اقرأ عبارة سياسة JSON عنصراً عنصراً وتوقّع ما تسمح به
- اختر بين سياسة هوية وسياسة موارد لمتطلّب وصول معيّن
- اشرح لماذا يحمل دور IAM سياسة ثقة وسياسة صلاحيات، وأي طلب تحكم كل منهما
- مرّر دوراً إلى instance في EC2 عبر instance profile وصف كيف يتلقّى التطبيق بيانات الاعتماد
- قارن عمليات AWS STS التي تُصدر بيانات اعتماد مؤقتة بالمنادي والمدة ودعم MFA
- حدّد ما الذي يتغيّر في تقييم السياسات حين يعبر الطلب حدود الحساب
تطبيقك يعمل على 40 instance في EC2 ويحتاج القراءة من bucket في S3. والحلّ المباشر إنشاء مستخدم IAM وتوليد مفتاح وصول ووضعه في ملف إعدادات على الـ instance. ينجح على الأولى. ثم يُخبَز المفتاح في الـ AMI، وتُشارَك الـ AMI، ويلصقه أحدهم في تذكرة دعم، وتصير الدورة التي جدولتها للربع القادم لمساً لأربعين جهازاً دفعة واحدة. ولا موعد انتهاء على ذلك المفتاح، ولا شيء في AWS سيخبرك يوماً بأنه تسرّب.
وأغلب ما في هذا المجال موجود كي يجعل هذا النمط غير ضروري. وهذا الدرس يبني المفردات التي يفترضها بقية المجال: مِمَّ تتكوّن السياسة، وأي أنواع السياسات ترفقها AWS بأي شيء، ولماذا الدور هو الجواب عن مشكلة مفتاح الوصول لا مجرد غلاف ألطف حولها.
الكيانات الطالبة والهويات، وما السياسة فعلاً
الكيان الطالب (principal) هو ما يرسل الطلب. وقد يكون root المستخدم للحساب، أو مستخدم IAM، أو جلسة دور، أو خدمة AWS تتصرّف نيابة عنك. والهوية (identity) هي كائن IAM الذي يأتي منه الكيان الطالب: مستخدم أو مجموعة أو دور.
والسياسة مستند JSON يحدّد الصلاحيات بمجرد إرفاقه بهوية أو بمورد. وحين يرسل كيان طالب طلباً، تجمع AWS كل سياسة تنطبق ثم تقرّر السماح أو المنع. والافتراض هنا مهم: كل طلب مرفوض ما لم تسمح به سياسة، والاستثناء الوحيد هو root المستخدم الذي يملك وصولاً كاملاً.
تدعم AWS تسعة أنواع من السياسات. ستقابلها كلها عبر هذا المجال، ولا تحتاج منها في هذا الدرس إلا ثلاثة:
| نوع السياسة | تُرفق بـ | هل تمنح صلاحيات؟ |
|---|---|---|
| سياسة الهوية | مستخدم أو مجموعة أو دور | نعم |
| سياسة الموارد | مورد (bucket أو طابور أو مفتاح أو دور) | نعم |
| permissions boundary | مستخدم أو دور | لا، تضع سقفاً |
| SCP وRCP في Organizations | الجذر أو OU أو حساب | لا، تضعان سقفاً |
| سياسة الجلسة | تُمرَّر عند إنشاء الجلسة | لا، تضع سقفاً |
| سياسة نقطة نهاية VPC | نقطة نهاية VPC | لا، تحدّ المرور عبر النقطة |
| ACL | مورد، بصيغة غير JSON | نعم، عبر الحسابات فقط |
| مشاركة موارد في AWS RAM | مورد مشارَك | نعم |
انظر إلى العمود الثالث. ثلاثة أنواع فقط تمنح الصلاحيات فعلاً، والبقية تضع سقوفاً، ولهذا فإن "السياسة تسمح بذلك" و"الطلب ينجح" عبارتان مختلفتان. والدرس التالي مخصّص كله لهذا الفارق.
تشريح سياسة JSON
كل سياسة JSON تحمل معلومات اختيارية في أعلاها وعبارة واحدة أو أكثر. وتطبّق AWS "أو" منطقية بين عبارات السياسة الواحدة وبين كل السياسات المنطبقة، فأي سماح منفرد يكفي (ما لم يمنع شيء).
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadReportsBucket",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::finance-reports",
"arn:aws:s3:::finance-reports/*"
],
"Condition": {
"Bool": { "aws:SecureTransport": "true" }
}
}
]
}
والعناصر، والفخّ في كل منها:
Versionإصدار لغة السياسات لا إصدار سياستك أنت. استخدم2012-10-17، فالقيمة الأقدم أو الغائبة تعطّل متغيّرات السياسة بصمت.Sidتسمية اختيارية. لا أثر لها في التقييم، لكنها ما يظهر حين تطارد العبارة التي منعت شيئاً، فسمِّها.EffectإماAllowوإماDeny.Principalيسمّي من تنطبق عليه السياسة. وهو إلزامي في سياسة الموارد وممنوع في سياسة الهوية، لأن الكيان الطالب في الثانية مفهوم ضمناً مما أُرفقت به السياسة. ورؤية كتلةPrincipalتخبرك فوراً أي نوع سياسة تقرأ.Actionيسرد إجراءات الخدمة بصيغةservice:Operationمع السماح بـ*.Resourceيسرد الـ ARNs. والـ bucket والكائنات داخله عنوانان مختلفان، ولهذا يسرد المثال أعلاه الاثنين. فالسياسة التي تحملarn:aws:s3:::finance-reportsوحده تسمح بالسرد لا بقراءة كائن مفرد.Conditionيجعل العبارة تنطبق حين يتحقّق الشرط فقط. والشروط موضوع الدرس التالي.
وقاعدة تستحقّ ترسيخها الآن: العبارة التي لا يتحقّق شرطها لا تنطبق ببساطة. هي لا تمنع، بل تسقط من التقييم وتترك الطلب لما يسمح به غيرها، وغالباً لا شيء.
سياسات الهوية مقابل سياسات الموارد
كلتاهما تمنح صلاحيات. والفرق في السؤال الذي تجيب عنه كل منهما.
سياسة الهوية تجيب عن "ما الذي تستطيع هذه الهوية فعله؟" وتسكن على المستخدم أو المجموعة أو الدور. وسياسة الموارد تجيب عن "من يستطيع لمس هذا المورد؟" وتسكن على المورد نفسه: سياسة bucket في S3، أو سياسة طابور SQS، أو سياسة مفتاح KMS، أو سياسة دالة Lambda، أو سياسة ثقة دور IAM.
| سياسة الهوية | سياسة الموارد | |
|---|---|---|
| تُرفق بـ | مستخدم أو مجموعة أو دور | المورد نفسه |
عنصر Principal | ممنوع | إلزامي |
| مُدارة أم مضمَّنة | كلاهما | مضمَّنة فقط، ولا وجود لسياسات موارد مُدارة |
| عبر الحسابات | تسمّي المورد في حساب آخر | تسمّي الكيان الطالب في حساب آخر |
وداخل الحساب الواحد تتّحد الاثنتان: السماح في إحداهما يكفي، والمنع الصريح في إحداهما يغلب. ولهذا يستطيع Zhang، بلا أي سياسة هوية، قراءة طابور تسمّيه سياسته.
واستثناءان يستحقّان الحفظ لأن الاختبار يحبّهما. سياسات ثقة أدوار IAM وسياسات مفاتيح KMS يجب أن تسمح للكيان الطالب صراحة. فاختصار الاتحاد لا ينقذك هناك: سياسة هوية تمنح kms:Decrypt على مفتاح لا تذكرك سياسته أبداً ليست كافية.
السياسات المُدارة مقابل المضمَّنة
سياسات الهوية تأتي بشكلين، والاختيار بينهما عن إعادة الاستخدام ودورة الحياة لا عن القوة.
السياسات المُدارة كائنات قائمة بذاتها ترفقها بهويات كثيرة. والسياسات المُدارة من AWS تكتبها AWS وتصونها (AmazonS3ReadOnlyAccess وAdministratorAccess وسياسات الوظائف). والسياسات المُدارة من العميل ملكك أنت. عدّل واحدة فيتغيّر كل ارتباط بها دفعة واحدة.
السياسات المضمَّنة تُدفن مباشرة داخل مستخدم أو مجموعة أو دور واحد. وعلاقتها بتلك الهوية واحدة بواحدة، وتُحذف بحذفها.
وتوجيه AWS نفسها أن تبدأ بالسياسات المُدارة من AWS للحصول على خطّ أساس يعمل، ثم تضيّق إلى سياسات مُدارة من العميل بعد أن تعرف الصلاحيات التي يستخدمها الحمل فعلاً. فالسياسات المُدارة من AWS مكتوبة لتنفع كل عميل لـ AWS، وهذا بالضبط سبب ندرة كونها أقل صلاحية ممكنة لعميلك أنت.
واستخدم المضمَّنة حين يجب ألا تعيش الصلاحية بعد الهوية، أو حين تريد ضمان ألا يرفقها أحد بمكان آخر سهواً.
الأدوار: سياستان وسؤالان
هنا المفهوم الذي يحمل بقية المجال. الدور هوية بصلاحيات مثل المستخدم، لكن مع فارقين يغيّران كل شيء:
- هو غير مرتبط بشخص واحد، فأي أحد أو أي شيء تسمح له سياسة الدور يستطيع تقمّصه.
- لا يحمل بيانات اعتماد طويلة العمر. لا كلمة مرور ولا مفتاح وصول. وتقمّصه ينتج بيانات اعتماد مؤقتة تنتهي صلاحيتها.
والنقطة الثانية هي ما يحلّ المشكلة الافتتاحية. لا شيء يُخبَز في الـ AMI، ولا شيء يُدوَّر، ولا شيء يتسرّب إلى الأبد.
وكي يعمل ذلك، يحمل الدور سياستين تحكمان طلبين مختلفين:
- سياسة الثقة سياسة موارد على الدور. وتجيب عن من يُسمح له بأن يصير هذا الدور. وهي وحدها ما يُستشار حين ينادي أحد
sts:AssumeRole. ولا يُسمح بالحروف البديلة داخل ARN في عنصرPrincipalفي سياسة ثقة. - سياسة الصلاحيات سياسة هوية على الدور. وتجيب عن ما الذي تستطيع الجلسة الناتجة فعله. وهي لا تُستشار أبداً أثناء نداء التقمّص.
وأصغر سياسة ثقة لحمل يعمل على EC2:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
وللإنسان القادم من حساب آخر:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": { "sts:ExternalId": "a1b2c3d4-audit-2026" }
}
}
]
}
وشرط sts:ExternalId هو الدفاع القياسي عن مشكلة النائب المخدوع (confused deputy). فحين تعطي طرفاً ثالثاً (مدقّقاً أو مزوّد مراقبة) دوراً في حسابك، يكون ذلك الطرف حاملاً لأدوار عملاء كثيرين. وبلا معرّف خارجي، يستطيع عميل عرف ARN دورك أن يطلب من المزوّد تقمّصه نيابة عنه. والمعرّف الخارجي سرّ تتشاركه أنت والمزوّد، فيجعل سياسة الثقة خاصة بعلاقتكما لا بالمزوّد ككل.
وهذا أيضاً أنفع تقسيم تشخيصي في IAM. البوابتان تفشلان برسالتين مختلفتين. فـ not authorized to perform: sts:AssumeRole يشير إلى سياسة الثقة، وnot authorized to perform: s3:GetObject يشير إلى سياسة الصلاحيات. والدرس الأخير في هذا الموضوع يحوّل هذه الملاحظة إلى إجراء كامل.
كيف يصل الدور إلى instance في EC2: الـ instance profile
الدور كائن في IAM. وEC2 يحتاج وعاءً يرفقه به، وهذا الوعاء هو instance profile.
والقاعدة التي تولّد أسئلة اختبار: الـ instance profile لا يحمل إلا دور IAM واحداً، وهذا الحدّ لا يُرفع. والدور الواحد يظهر في instance profiles كثيرة، لكن العكس لا.
ومنبع الالتباس أن الكونسول يخفي الكائن. فإنشاء دور لـ EC2 من الكونسول ينشئ معه instance profile بالاسم نفسه تلقائياً. وإنشاء الدور نفسه من الـ CLI أو الواجهة البرمجية يعطيك دوراً ولا شيء غيره، فلا يعرض لك معالج الإطلاق (الذي يسرد أسماء instance profiles لا أسماء الأدوار) أي شيء.
# من الـ CLI هذه ثلاث خطوات منفصلة
aws iam create-role \
--role-name AppServerRole \
--assume-role-policy-document file://trust-policy.json
aws iam create-instance-profile --instance-profile-name AppServerProfile
aws iam add-role-to-instance-profile \
--instance-profile-name AppServerProfile \
--role-name AppServerRole
# الإرفاق بـ instance قيد التشغيل
aws ec2 associate-iam-instance-profile \
--instance-id i-02573cafcfEXAMPLE \
--iam-instance-profile Name=AppServerProfile
وبمجرد الإرفاق، تجد حزم AWS SDK على الـ instance بيانات الاعتماد عبر خدمة ميتاداتا الـ instance بلا أي إعداد، وتدوّرها الخدمة قبل انتهاء صلاحيتها. ولتغيير ما تستطيع الـ instance فعله، استبدل الـ instance profile بدل تبديل الدور داخله، لأن إزالة دور من instance profile تستغرق حتى ساعة كي تسري، فالتغيير يحتاج وقتاً لينتشر.
أدوار الخدمة والأدوار المرتبطة بالخدمة
نوعان من الأدوار يحملان اسمين يستخدمهما الاختبار بدقّة.
دور الخدمة (service role) دور تتقمّصه خدمة من AWS كي تتصرّف نيابة عنك. أنت تنشئه، وأنت تكتب سياسة ثقته مسمّياً كيان الخدمة، وتستطيع تعديل صلاحياته. ودور بناء في CodeBuild ودور EC2 أعلاه كلاهما دور خدمة.
والدور المرتبط بالخدمة (service-linked role) تنشئه الخدمة وتملكه. يظهر في حسابك، والخدمة هي من يحدّد صلاحياته، والمسؤول يعاينها ولا يعدّلها. ولا تستطيع حذفه حتى تحذف الموارد التي تعتمد عليه، وهذا حارس يمنع ترك موارد معلّقة لا تستطيع الخدمة إدارتها.
وإن أعطاك سؤال دوراً لم تنشئه أنت وسألك لماذا لا تُضيَّق سياسته، فهو دور مرتبط بالخدمة.
الحصول على بيانات اعتماد مؤقتة: عمليات STS
خدمة AWS Security Token Service تُصدر كل بيانات اعتماد مؤقتة في AWS. والعمليات الخمس تختلف بمن يستطيع مناداتها وكم تعيش النتيجة.
| العملية | من ينادي | المدة (الأدنى، الأقصى، الافتراضي) | مدخل MFA | سياسة جلسة |
|---|---|---|---|---|
AssumeRole | مستخدم IAM أو دور يحمل بيانات اعتماد مؤقتة قائمة | 15 دقيقة، أقصى مدة جلسة الدور، ساعة واحدة | نعم | نعم |
AssumeRoleWithSAML | أي أحد يحمل استجابة SAML من مزوّد معروف | 15 دقيقة، أقصى مدة جلسة الدور، ساعة واحدة | لا | نعم |
AssumeRoleWithWebIdentity | أي أحد يحمل رمز JWT من مزوّد OIDC معروف | 15 دقيقة، أقصى مدة جلسة الدور، ساعة واحدة | لا | نعم |
GetFederationToken | مستخدم IAM أو root المستخدم | مستخدم IAM: 15 دقيقة، 36 ساعة، 12 ساعة. وroot: 15 دقيقة، ساعة، ساعة | لا | نعم |
GetSessionToken | مستخدم IAM أو root المستخدم | مستخدم IAM: 15 دقيقة، 36 ساعة، 12 ساعة. وroot: 15 دقيقة، ساعة، ساعة | نعم | لا |
وثلاث تفاصيل تحسم الأسئلة هنا.
إعداد أقصى مدة جلسة على الدور هو السقف لكل صيغ التقمّص، وهو قابل للضبط حتى 12 ساعة. واطلب أكثر مما يسمح به الدور فيفشل النداء بدل أن يعيد جلسة أقصر.
AssumeRole وGetSessionToken وحدهما تقبلان معلومات MFA. وهذا ما يجعل aws:MultiFactorAuthPresent صحيحاً للجلسة الناتجة، وهو ما يستخدمه الدرس التالي لفرض MFA على الإجراءات الحسّاسة.
GetSessionToken لا تُدخلك إلى الكونسول عبر نقطة نهاية الاتحاد، بينما GetFederationToken تفعل. فإن احتاج سيناريو دخولاً موحّداً إلى الكونسول من وسيط هوية مخصّص، فالعملية هي GetFederationToken.
تسلسل الأدوار ومدة الجلسة
تسلسل الأدوار (role chaining) هو استخدام بيانات اعتماد دور لتقمّص دور ثانٍ. وهو شائع في الـ pipelines وأدوات العمل عبر الحسابات، ويحمل حدّاً صارماً: الجلسة المتسلسلة محدودة بساعة واحدة، مهما كانت أقصى مدة جلسة مضبوطة على الدور الهدف. وتمرير DurationSeconds أكبر من 3600 في نداء متسلسل يجعل العملية تفشل.
ومن المغري قراءة ذلك على أنه "تُقتطع الجلسة إلى ساعة". هي لا تُقتطع. النداء يخرج بخطأ، ولهذا ينكسر pipeline كان يعمل بجلسة أربع ساعات من بيانات اعتماد مستخدم يوم يُدخل أحدهم دوراً وسيطاً.
الوصول عبر الحسابات: القاعدة التي تتغيّر
داخل الحساب الواحد تتّحد سياسات الهوية وسياسات الموارد. وعبر الحسابات يجب أن يسمح الجانبان معاً. فحساب الكيان الطالب عليه منح سماح هوية للإجراء على المورد الهدف، وحساب المورد عليه تسمية ذلك الكيان في سياسة موارد أو في سياسة ثقة دور. والجانب الواحد وحده يفشل دائماً.
وهذا اللاتماثل وحده يفسّر أغلب تذاكر العمل عبر الحسابات. فسياسة bucket كريمة تسمح لـ arn:aws:iam::111122223333:root لا تفعل شيئاً حتى يمنح مسؤول في الحساب 111122223333 هوية ما صلاحية s3:GetObject المقابلة. فتسمية root الحساب في سياسة bucket تفويض لذلك الحساب، لا منح لكل كيان فيه.
نصائح الاختبار
- وجود
Principalفي السياسة يعني أنها سياسة موارد، وغيابه يعني سياسة هوية. وهذا العنصر وحده يحدّد نوع السياسة أسرع من قراءة بقيتها. - "تطبيق على EC2 يحتاج نداء خدمة من AWS" يعني دائماً instance profile يحمل دوراً، ولا يعني أبداً مفتاح وصول على الـ instance.
- دور واحد لكل instance profile، والدور الواحد يعيش في instance profiles كثيرة. وإزالة دور من instance profile تستغرق حتى ساعة، فالعلاج في السيناريو استبدال الـ instance profile.
- رسالتا خطأ وسياستان: رفض
sts:AssumeRoleيعني سياسة الثقة، ورفض الإجراء الهدف يعني سياسة الصلاحيات. - تسلسل الأدوار محدود بساعة، وهو يفشل بدل أن يقتطع.
- كلمات "طرف ثالث" أو "مزوّد" أو "مدقّق" في سيناريو دور عبر الحسابات تشير إلى
sts:ExternalIdومشكلة النائب المخدوع. - العمل عبر الحسابات يحتاج سماحاً على الجانبين. وداخل الحساب يكفي سماح على أحد الجانبين، إلا في سياسات ثقة الأدوار وسياسات مفاتيح KMS التي يجب أن تسمّي الكيان الطالب.
- الدور الذي لا تستطيع تعديل صلاحياته هو دور مرتبط بالخدمة.
القاعدة التي تحملها من هذا الدرس: في AWS يجب أن يكون لبيانات الاعتماد موعد انتهاء، والطريق إلى موعد الانتهاء هو الدور. وكل ما عدا ذلك هنا مسك دفاتر حول تلك الفكرة الواحدة. والدرس التالي يأخذ السياسات التي صرت تقرأها ويجيب عن السؤال الأصعب: ماذا يحدث حين تنطبق خمس منها على الطلب نفسه وتتعارض.
