يا جماعة الخير، السلام عليكم ورحمة الله.
خلوني أحكيلكم قصة صارت معي قبل كم سنة، قصة بتلخص المعاناة اللي كتير من فرق التطوير والعمليات بعيشوها كل يوم. كنا شغالين على مشروع ضخم لعميل مهم، مشروع استمر شهور طويلة من التعب والسهر. الفريق كان شعلة نشاط، الكل بيكتب كود، والكل بيبني خدمات على الكلاود، والأمور ماشية زي الحلاوة… أو هيك كنا مفكرين.
قبل موعد الإطلاق بأسبوع واحد، أجانا طلب “روتيني” من قسم أمن المعلومات: “بدنا نعمل مراجعة أمنية شاملة لكل البنية التحتية”. قلنا بسيطة، إحنا ماشيين على أفضل الممارسات. لكن اللي صار كان كابوس. بعد يومين من التدقيق اليدوي، رجعلنا فريق الأمن بقائمة طويلة عريضة من “المصايب”: قواعد بيانات مفتوحة على الإنترنت بدون قصد، صلاحيات واسعة جدًا لحسابات خدمية، حاويات دوكر (Docker containers) بتشتغل بصلاحيات root، والقائمة تطول.
وقتها شعرت بإحباط شديد. يا زلمة، كل هالتعب، وكل هالشغل، وفي النهاية أخطاء بديهية زي هاي كانت رح تنسف المشروع كله. المشكلة ما كانت في الفريق، الفريق كان ممتاز. المشكلة كانت في “العملية” نفسها. كانت سياساتنا الأمنية مجرد ملف PDF من 50 صفحة، مين فينا عنده وقت يقرأه ويطبقه بحذافيره مع كل تغيير؟ كانت سياساتنا مجرد حبر على ورق، وثغرات أمنية تنتظر الحدوث.
هذيك اللحظة كانت نقطة تحول. عرفت إنه لازم نلاقي طريقة أفضل، طريقة مؤتمتة، طريقة تحوّل السياسات من مجرد “نصائح” إلى “قوانين” يتم فرضها تلقائيًا. وهون بدأت رحلتنا مع ما يسمى بـ “السياسة كشيفرة” أو Policy as Code.
ما هي ‘السياسة كشيفرة’ (Policy as Code)؟ ولماذا هي الحل؟
بكل بساطة، “السياسة كشيفرة” هي ممارسة تعريف السياسات (الأمنية، التشغيلية، الامتثال) على شكل كود، بدلًا من كتابتها في مستندات نصية يقرأها البشر.
فكر فيها بهذه الطريقة:
- الطريقة القديمة: مدير أمن المعلومات يكتب وثيقة Word بعنوان “سياسة استخدام الحوسبة السحابية”، ويرسلها بالإيميل للجميع. المطورون (إذا قرأوها أصلًا) يحاولون تذكر القواعد أثناء عملهم. فريق المراجعة يستخدم قائمة تدقيق (checklist) لمطابقة العمل مع الوثيقة. العملية بطيئة، عرضة للخطأ البشري، وغير فعالة.
- طريقة “السياسة كشيفرة”: نفس السياسات تُكتب بكود باستخدام لغة مخصصة مثل Rego. هذا الكود يتم حفظه في نظام إدارة الإصدارات (مثل Git)، ويتم دمجه في مسار العمل التلقائي (CI/CD pipeline). أي محاولة لخرق السياسة يتم اكتشافها ورفضها تلقائيًا قبل أن تصل إلى بيئة الإنتاج.
النتيجة؟ تحول جذري. بدلًا من أن يكون الأمن “حارس بوابة” يعطل العمل في نهاية المطاف، يصبح الأمن جزءًا لا يتجزأ من عملية التطوير نفسها. هذا هو جوهر ما يسمى بـ DevSecOps.
رحلتنا العملية مع ‘السياسة كشيفرة’: الأدوات والخطوات
الحكي النظري جميل، لكن كيف نطبق هذا الكلام على أرض الواقع؟ خلوني أشاركم تجربتنا العملية خطوة بخطوة.
اختيار الأداة المناسبة: Open Policy Agent (OPA) هو البطل
بعد بحث وتقييم، استقر اختيارنا على أداة مفتوحة المصدر اسمها Open Policy Agent أو اختصارًا OPA. ليش OPA بالذات؟
- لغة تعريفية قوية (Rego): لغة Rego المصممة خصيصًا لكتابة السياسات، سهلة القراءة والكتابة بمجرد أن تعتاد عليها.
- غير مرتبطة بمنصة معينة (Platform-agnostic): هاي نقطة جوهرية. يمكنك استخدام OPA لتأمين Kubernetes, Terraform, Microservices, CI/CD pipelines، وأي شيء آخر يخطر ببالك. هو بمثابة “محرك سياسات” متعدد الأغراض.
- مجتمع ضخم ودعم قوي: OPA هو مشروع متخرج من مؤسسة الحوسبة السحابية الأصلية (CNCF)، وهذا يعني أن له مستقبل واعد ودعمًا كبيرًا.
الخطوة الأولى: كتابة سياستنا الأولى بلغة Rego
قررنا نبدأ بمشكلة كانت تؤرقنا دائمًا: استخدام صور دوكر (Docker images) من مصادر غير موثوقة أو استخدام الوسم `latest` الذي يسبب مشاكل في استقرار البيئات.
هذه كانت أول سياسة كتبناها بلغة Rego، هدفها التأكد من أن كل الحاويات في ملفات Kubernetes تأتي من مستودع شركتنا الموثوق (`our.trusted.registry`).
# policy.rego
package kubernetes.images
# القاعدة الافتراضية: لا يوجد انتهاك
default allow = true
# تعريف الانتهاك (deny)
# الرسالة التي ستظهر في حال وجود انتهاك
deny[msg] {
# ابحث في كل الحاويات المعرفة في ملف الإدخال (input)
some container
input.kind == "Deployment"
container = input.spec.template.spec.containers[_]
# تحقق مما إذا كانت الصورة لا تبدأ بالمستودع الموثوق
not startswith(container.image, "our.trusted.registry/")
# إذا تحقق الشرط، قم بإنشاء رسالة الخطأ
msg = sprintf("Image '%s' comes from an untrusted registry. Please use 'our.trusted.registry/'.", [container.image])
}
شرح الكود ببساطة:
الكود يقول: “بشكل افتراضي، كل شيء مسموح (
default allow = true). لكن، إذا وجدتَ أي حاوية (container) داخل ملف Deployment، وكانت صورة هذه الحاوية (container.image) لا تبدأ بـour.trusted.registry/، فهذا انتهاك (deny). وعندها، قم بتوليد رسالة الخطأ المحددة (msg)”.
الخطوة الثانية: دمج السياسات في دورة حياة التطوير (CI/CD)
كتابة السياسة هي نصف المعركة فقط. القوة الحقيقية تكمن في فرضها تلقائيًا. قمنا بدمج OPA في خط أنابيب التكامل المستمر (CI pipeline) الخاص بنا على GitLab.
أصبح جزء من الـ pipeline يبدو كالتالي (مثال توضيحي):
# .gitlab-ci.yml
validate_k8s_manifests:
stage: test
image: openpolicyagent/opa:latest
script:
# سيقوم هذا الأمر بفحص كل ملفات YAML في مجلد k8s/
# إذا وجدت أي انتهاكات للسياسة (policy.rego)، سيفشل الـ pipeline
- opa eval --input k8s/deployment.yaml --data policy.rego "data.kubernetes.images.deny"
# نتوقع أن تكون النتيجة فارغة. إذا لم تكن فارغة، يعني وجود انتهاكات
# الكود التالي يفشل المهمة إذا كان هناك انتهاك
- 'if [ "$(opa eval -I -d policy.rego -d k8s/deployment.yaml "data.kubernetes.images.deny")" != "[]" ]; then echo "Policy violations found!"; exit 1; fi'
بهذه الخطوة البسيطة، قتلنا المشكلة في مهدها. الآن، أي مطور يحاول إضافة صورة من مستودع غير موثوق، سيفشل الـ pipeline الخاص به فورًا مع رسالة واضحة تخبره بالمشكلة وكيفية حلها. لا مزيد من المفاجآت قبل الإطلاق!
أمثلة من الميدان: كيف طبقنا ‘السياسة كشيفرة’؟
بعد نجاحنا الأول، تحمسنا وبدأنا بتطبيق ‘السياسة كشيفرة’ في كل مكان تقريبًا.
تأمين البنية التحتية كشيفرة (IaC)
كنا نستخدم Terraform لتعريف بنيتنا التحتية على AWS. من أكبر المخاطر الأمنية هي إنشاء S3 Buckets عامة (public) عن طريق الخطأ. كتبنا سياسة OPA بسيطة لمنع ذلك:
# terraform_aws_s3.rego
package terraform.aws.security
deny[msg] {
# ابحث عن أي مورد من نوع aws_s3_bucket
resource := input.resource.aws_s3_bucket[_]
# تحقق من أن صلاحية الوصول (acl) ليست "public-read" أو "public-read-write"
resource.acl == "public-read"
msg = sprintf("Resource '%s' has a public ACL. This is not allowed.", [resource.name])
}
قمنا بتشغيل هذه السياسة على `terraform plan` كجزء من الـ CI. أي محاولة لإنشاء bucket عامة يتم إيقافها فورًا.
حوكمة Kubernetes
مع نمو استخدامنا لـ Kubernetes، أردنا فرض بعض القواعد التشغيلية، مثل:
- كل Pod يجب أن يحدد طلبات ومحدوديات الموارد (resource requests/limits) لمنع استهلاك كل موارد الكلاستر.
- كل خدمة (Service) يجب أن تحتوي على ملصقات (labels) معينة لتسهيل المراقبة.
استخدمنا OPA Gatekeeper، وهو مشروع يدمج OPA مع Kubernetes بشكل أصلي، لفرض هذه السياسات على مستوى الكلاستر مباشرة.
نصائح من ‘أبو عمر’ لتطبيق ناجح
هذه الرحلة لم تكن سهلة دائمًا، وتعلمنا بعض الدروس بالطريقة الصعبة. اسمحوا لي أن أشارككم بعض النصائح العملية:
- ابدأ صغيرًا ومتدرجًا: لا تحاول أتمتة كل سياسات الشركة في يوم واحد. اختر مشكلة واحدة مؤلمة وواضحة (مثل صور Docker أو S3 buckets العامة)، وحلها. النجاح في هذه الخطوة سيعطيك الزخم والدعم لمواصلة المشوار.
- السياسات ليست ثابتة، عاملها ككود: السياسات تتغير وتتطور. يجب أن تُعامل ملفات Rego الخاصة بك كأي كود آخر: ضعها في Git، قم بعمل مراجعات للكود (Code Reviews) عند التغيير، واكتب لها اختبارات.
- الوضوح أهم من التعقيد: اكتب سياسات بسيطة ومفهومة. أضف تعليقات تشرح “لماذا” هذه السياسة موجودة. الهدف ليس فقط منع الخطأ، بل تعليم الفريق الممارسة الصحيحة.
- لا تكن ديكتاتوريًا (في البداية): OPA يسمح لك بتشغيل السياسات في وضع “المراقبة” (Audit mode) أولًا. بدلًا من حظر الإجراءات المخالفة (enforce)، يمكنك فقط تسجيلها أو إرسال تحذيرات. هذا يعطي الفرق وقتًا للتكيف مع السياسات الجديدة دون تعطيل عملهم. بعد فترة، يمكنك الانتقال إلى وضع الفرض الإلزامي.
الخلاصة: وداعًا للفوضى، أهلًا بالثقة المؤتمتة
العودة إلى قصتي في البداية… هل تكررت تلك الكارثة مرة أخرى؟ لا، والحمد لله. “السياسة كشيفرة” لم تحل مشكلة تقنية فقط، بل غيرت ثقافتنا. انتقلنا من ثقافة “اللوم” و “إصلاح الأخطاء” بعد وقوعها، إلى ثقافة “الوقاية” و “الجودة المدمجة”.
لم يعد الأمن عبئًا أو فريقًا نقول عنه “جماعة الـ ‘لأ’ “، بل أصبح شريكًا مؤتمتًا يعمل معنا على مدار الساعة ليضمن أننا نبني أنظمة آمنة ومستقرة وقابلة للتطوير. إنها نقلة نوعية من الفوضى اليدوية إلى الثقة المؤتمتة.
إذا كنتم لا تزالون تعانون من المراجعات اليدوية وقوائم التدقيق التي لا تنتهي، فأنصحكم بشدة أن تبدأوا رحلتكم مع “السياسة كشيفرة”. قد تكون البداية صعبة قليلًا، لكن العائد على المدى الطويل يستحق كل هذا العناء وأكثر. صدقوني! 😉