من يملك بيئة الإنتاج؟ لماذا تعتبر حدود الصلاحيات بين البيئات أمرًا مهمًا

يقوم أحد المطورين في فريقك بتغيير بسيط في ملف إعدادات. كان قصده تحديث بيئة الاختبار (staging)، لكنه نفذ الأمر بالخطأ على بيئة الإنتاج. بعد خمس دقائق، يبدأ المستخدمون في الإبلاغ عن أخطاء. يندفع الفريق لمعرفة ما حدث، ومن قام بالتغيير، وكيفية التراجع عنه. في هذه الأثناء، المطور الذي تسبب في المشكلة ليس متأكدًا حتى مما إذا كان لديه صلاحية لتعديل بيئة الإنتاج من الأساس.

هذا السيناريو يتكرر أكثر مما ترغب معظم الفرق في الاعتراف به. الأمر لا يتعلق بسوء النية أو مهندسين غير أكفاء. بل يتعلق بغياب حدود واضحة بين البيئات. عندما يمتلك الجميع نفس الصلاحيات للوصول إلى بيئات التطوير والاختبار والإنتاج، يصبح النظام غير قادر على التمييز بين التغييرات المقصودة والأخطاء.

المشكلة مع الوصول الشامل

تبدأ العديد من الفرق بإعداد بسيط: الجميع يحصل على صلاحية الوصول إلى كل شيء. يمكن للمطورين تعديل بيئة الاختبار أو الإنتاج أو حتى بيئة تطوير فريق آخر. يبدو هذا عمليًا في البداية. لا أحد يضطر لانتظار الصلاحيات. لا أحد يحتاج لطلب المساعدة لنشر إصلاح.

لكن هذا النهج يخلق مشكلتين. الأولى: المساءلة تصبح غير واضحة. عندما يحدث عطل في الإنتاج وكان الجميع يمتلكون صلاحية الوصول، يستغرق العثور على السبب الجذري وقتًا أطول. عليك التحقق من قام بتشغيل أي أمر، ومن أي جهاز، وفي أي وقت. الثانية: نصف قطر الانفجار للخطأ يتسع. يمكن لمطور يعمل على فرع ميزة أن يتسبب عن طريق الخطأ في نشر إلى الإنتاج. خطأ مطبعي في ملف إعدادات يمكن أن يعطل خدمة يعتمد عليها مئات المستخدمين.

الحل ليس في تقييد كل شيء بشدة بحيث لا يستطيع أحد العمل. الحل هو إنشاء حدود صلاحيات واضحة بين البيئات.

ما هي حدود الصلاحيات؟

حدود الصلاحيات هي فصل واضح لمن يمكنه فعل ماذا في كل بيئة. الأمر لا يتعلق فقط بالصلاحيات في أداة معينة. بل يتعلق بكيفية هيكلة الواجهة الخلفية للحالة (state backend)، والمستودع، وتكوين خط الأنابيب (pipeline configuration).

على سبيل المثال، يجب أن يكون ملف الحالة (state file) للإنتاج في موقع مختلف عن ملف الحالة للتطوير. إذا كنت تستخدم Terraform، يمكن أن تكون الواجهة الخلفية لحالة الإنتاج عبارة عن حاوية S3 منفصلة بسياسات IAM أكثر صرامة. فقط عدد قليل من الأشخاص في الفريق لديهم حق الوصول إلى تلك الحاوية. بينما يمكن أن تكون الواجهة الخلفية لحالة التطوير في حاوية مشتركة يمكن للجميع في الفريق القراءة والكتابة فيها.

المبدأ هنا هو "الأقل صلاحية" (least privilege). كل شخص أو نظام يحصل فقط على الصلاحيات التي يحتاجها لأداء وظيفته. قد يحتاج المطور إلى صلاحية كاملة لبيئة التطوير. وقد يحتاج إلى صلاحية قراءة فقط لحالة الإنتاج لفهم ما يعمل. ولكن إذا احتاج إلى إجراء تغيير في الإنتاج، فيجب أن يمر هذا التغيير عبر عملية أكثر رسمية: طلب سحب (pull request) يراجعه عضو آخر في الفريق، أو خط أنابيب يتطلب موافقة.

الملكية تجعل الحدود ملموسة

تعمل حدود الصلاحيات بشكل أفضل عندما يكون لكل بيئة مالك واضح. المالك هو الشخص أو الفريق المسؤول عند حدوث خطأ ما في تلك البيئة. الملكية ليست حول السيطرة. إنها حول المساءلة.

عمليًا، غالبًا ما تبدو الملكية كما يلي:

  • فريق هندسة المنصة (platform engineering) يملك بيئة الإنتاج. هم مسؤولون عن استقرارها وأدائها وأمنها.
  • فريق تطوير التطبيقات يملك بيئة الاختبار (staging). يستخدمونها للتحقق من صحة تغييراتهم قبل طلب النشر إلى الإنتاج.
  • المطورون الأفراد يملكون بيئات التطوير الشخصية الخاصة بهم. يمكنهم كسرها وإعادة بنائها والتجربة بحرية.

هذا التقسيم لا يعني أن المطورين لا يمكنهم لمس الإنتاج. بل يعني أنه عندما يفعلون ذلك، فإنهم يتبعون عملية تشمل مالك الإنتاج. يقوم المالك بمراجعة التغيير، ويفهم المخاطر، ويوافق على النشر أو يرفضه.

كيفية تطبيق حدود الصلاحيات عمليًا

تظهر حدود الصلاحيات في ثلاثة أماكن: هيكل المستودع، وتكوين خط الأنابيب، والواجهة الخلفية للحالة.

هيكل المستودع

أبسط طريقة لفرض الحدود هي من خلال هيكل الدليل وحماية الفروع. يمكن أن تعيش تكوينات الإنتاج في دليل منفصل أو حتى في مستودع منفصل. إذا كانت في نفس المستودع، فيجب حماية دليل الإنتاج. فقط أعضاء محددون في الفريق يمكنهم دفع التغييرات إليه. تتطلب طلبات السحب التي تعدل تكوينات الإنتاج موافقة من مالك الإنتاج.

يوضح مخطط التدفق التالي كيفية تدفق طلب التغيير عبر حدود الصلاحيات بناءً على من يقوم بالتغيير والبيئة المستهدفة.

flowchart TD A[طلب تغيير] --> B{من يقوم بالتغيير؟} B -->|مطور| C{البيئة المستهدفة؟} B -->|مسؤول/أوبس| D{البيئة المستهدفة؟} C -->|تطوير/اختبار| E[إنشاء طلب سحب] C -->|إنتاج| F[ممنوع - التصعيد للمالك] D -->|تطوير/اختبار| G[إنشاء طلب سحب] D -->|إنتاج| H[إنشاء طلب سحب مع مراجعة المالك] E --> I[خطوة التخطيط] G --> I H --> J[خطوة التخطيط + موافقة المالك] I --> K[تطبيق على التطوير/الاختبار] J --> L[تطبيق على الإنتاج]

تكوين خط الأنابيب

خط أنابيب CI/CD الخاص بك هو المكان الذي تصبح فيه الحدود قابلة للتطبيق. يجب أن يعمل خط أنابيب الإنتاج فقط عند استيفاء شروط معينة. على سبيل المثال، قد يتم تشغيله فقط من فرع محمي. قد يتطلب موافقة يدوية من شخص معين. قد يقوم بتشغيل خطوات تحقق إضافية يتخطاها خط أنابيب التطوير.

تذهب بعض الفرق إلى أبعد من ذلك. يقومون بتكوين خط أنابيب الإنتاج ليعمل فقط من مشغل CI/CD محدد لديه حق الوصول إلى الواجهة الخلفية لحالة الإنتاج. لا يمكن للمطورين تشغيل خط أنابيب الإنتاج من أجهزة الكمبيوتر المحمولة الخاصة بهم لأن أجهزتهم المحلية لا تحتوي على بيانات الاعتماد المطلوبة.

الواجهة الخلفية للحالة

الواجهة الخلفية للحالة هي المكان الذي تخزن فيه أدوات البنية التحتية كرمز (IaC) الحالة الحالية لبيئاتك. إذا كنت تستخدم Terraform، فيجب أن يكون ملف الحالة للإنتاج في واجهة خلفية منفصلة مع ضوابط وصول صارمة. يجب أن تسمح سياسة IAM لتلك الواجهة الخلفية فقط بالعمليات من خط أنابيب الإنتاج، وليس من حسابات المطورين الفردية.

على سبيل المثال، يمكنك تكوين الواجهة الخلفية لحالة الإنتاج بسياسة تقول: "فقط حساب خدمة CI/CD يمكنه الكتابة إلى ملف الحالة هذا. الجميع يمكنهم القراءة فقط." بهذه الطريقة، حتى إذا قام مطور عن طريق الخطأ بتشغيل أمر Terraform ضد الإنتاج، فإن الأمر يفشل لأنه لا يمكنه الحصول على قفل الحالة.

فيما يلي سياسة IAM لـ Terraform تفرض هذه الحدود من خلال السماح بالكتابة فقط لملفات حالة التطوير مع منع الكتابة لملفات حالة الإنتاج:

data "aws_iam_policy_document" "state_access" {
  statement {
    sid    = "AllowDevWrite"
    effect = "Allow"
    actions = [
      "s3:PutObject",
      "s3:GetObject",
      "s3:DeleteObject"
    ]
    resources = [
      "arn:aws:s3:::my-tf-state-bucket/env:/dev/*"
    ]
  }

  statement {
    sid    = "DenyProdWrite"
    effect = "Deny"
    actions = [
      "s3:PutObject",
      "s3:DeleteObject"
    ]
    resources = [
      "arn:aws:s3:::my-tf-state-bucket/env:/prod/*"
    ]
  }
}

الحدود ليست عن عدم الثقة

تقاوم بعض الفرق حدود الصلاحيات لأنها تشعر أنها علامة على عدم الثقة. "لقد وظفنا أشخاصًا أذكياء. لماذا لا نثق بهم في الوصول إلى الإنتاج؟"

هذا الإطار يخطئ الهدف. حدود الصلاحيات ليست عن الثقة. إنها عن الوضوح والمساءلة. عندما يمتلك الجميع صلاحية الوصول إلى كل شيء، لا أحد يعرف من يتصل عندما يحدث عطل. عندما تكون الحدود واضحة، يعرف الفريق بالضبط من يملك كل بيئة وما هي العملية التي يجب اتباعها.

الحدود تحمي أيضًا الأشخاص الذين يرتكبون الأخطاء. المطور الذي يكسر الإنتاج عن طريق الخطأ لأنه كان لديه وصول غير مقيد يشعر بالسوء. كما أنه يضيع وقت الفريق بينما يحقق الجميع في الحادث. مع حدود واضحة، كان سيتم إيقاف نفس المطور قبل أن يصل التغيير إلى الإنتاج. النظام يلتقط الخطأ، وليس الشخص.

قائمة مراجعة سريعة لإعداد حدود الصلاحيات

إذا كنت تراجع إعدادك الحالي، فإليك بعض الأشياء للتحقق منها:

  • هل الواجهة الخلفية لحالة الإنتاج منفصلة عن التطوير والاختبار؟
  • هل يمكن للمطورين الكتابة إلى حالة الإنتاج من أجهزة الكمبيوتر المحمولة الخاصة بهم؟
  • هل يتطلب خط أنابيب الإنتاج موافقة يدوية؟
  • هل هناك مالك واضح لكل بيئة؟
  • هل تتم مراجعة التغييرات على تكوينات الإنتاج من قبل المالك قبل النشر؟

هذه الفحوصات ليست شاملة، لكنها تغطي الفجوات الأكثر شيوعًا التي تؤدي إلى حوادث الإنتاج.

ما التالي

بمجرد أن تكون لديك حدود الصلاحيات والملكية في مكانها، التحدي التالي هو الحفاظ على دقة حالة البنية التحتية الخاصة بك. في بعض الأحيان تحدث تغييرات خارج أدوات البنية التحتية كرمز. يقوم شخص ما بتعديل تكوين خادم مباشرة من وحدة التحكم السحابية. يطبق أحد أعضاء الفريق إصلاحًا سريعًا يدويًا أثناء حادث. هذه التغييرات تخلق انحرافًا (drift) بين حالتك والواقع. الانحراف يقوض موثوقية البنية التحتية الخاصة بك ويجعل التغييرات المستقبلية غير متوقعة. هذا موضوع يستحق الاستكشاف بشكل منفصل، ولكن في الوقت الحالي، الخطوة المهمة هي إنشاء حدود واضحة أولاً. بدونها، يصبح اكتشاف الانحراف ومعالجته أكثر صعوبة.