فصل المهام وأقل صلاحية في خطوط أنابيب CI/CD

مقدمة

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

المشكلة ليست أن الفرق مهملة. المشكلة أن أدوات CI/CD تجعل من السهل منح صلاحيات مفرطة ومن الصعب تطبيق ضوابط دقيقة. المسار الافتراضي في معظم المنصات هو هوية واحدة ذات صلاحيات واسعة تشغّل كل مرحلة من مراحل خط الأنابيب. تبدو مبادئ الأمان مثل separation of duties (SoD) وleast privilege كأنها عبء بيروقراطي عندما تحاول إطلاق الميزات بسرعة.

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

لماذا تتراكم الصلاحيات في خطوط الأنابيب

قبل الغوص في الحلول، من المفيد فهم كيف ينتهي الأمر بخطوط الأنابيب بصلاحيات مفرطة في المقام الأول. النمط متسق بشكل ملحوظ عبر المؤسسات.

مشكلة حساب الخدمة الواحد

يبدأ الأمر بحساب خدمة واحد — غالبًا ما يُسمى شيئًا مثل ci-deployer أو pipeline-bot — يُنشأ أثناء الإعداد الأولي لنظام CI/CD. يحتاج هذا الحساب إلى سحب الشيفرة، فيحصل على صلاحية قراءة المستودع. ثم يحتاج إلى دفع صور Docker، فيحصل على صلاحية الكتابة في السجل. ثم يحتاج إلى النشر في بيئة الاختبار، ثم الإنتاج، ثم إدارة البنية التحتية. خلال أسابيع، يمكن لهذه الهوية الواحدة البناء والاختبار والنشر والوصول إلى بيانات الإنتاج. لقد أصبحت مفتاحًا رئيسيًا.

الرموز الخارقة (God tokens)

يرتبط بذلك ارتباطًا وثيقًا ما يُعرف بـ “god token” — وهو personal access token أو مفتاح API بصلاحيات قراءة/كتابة لكل شيء. غالبًا ما يُنشئ هذه الرموز مسؤول أثناء الإعداد، وتُخزّن كمتغير CI/CD، ولا تُجدَّد أبدًا. عادةً ما تعيش أطول من الشخص الذي أنشأها، ولا يتذكر أحد بالضبط ما هي الصلاحيات التي تحملها.

الراحة على حساب الأمان

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

غياب حدود الهوية بين المراحل

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

Separation of Duties في CI/CD

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

المبادئ الأساسية لـ SoD في خطوط الأنابيب

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

ربط SoD بمراحل خط الأنابيب

خط أنابيب مصمم بشكل جيد يربط separation of duties بمراحل منفصلة، لكل منها هويتها وصلاحياتها الخاصة:

  • Build — تجميع الشيفرة، وحل التبعيات، وإنتاج القطع البرمجية. يتطلب صلاحية قراءة الشيفرة المصدرية وسجلات التبعيات. لا وصول إلى أهداف النشر.
  • Test — تشغيل اختبارات الوحدة، واختبارات التكامل، وفحوصات الأمان. يتطلب صلاحية قراءة القطع البرمجية والبنية التحتية للاختبار. لا وصول إلى أسرار الإنتاج.
  • Sign — توقيع القطع البرمجية رقميًا بعد اجتياز جميع الفحوصات. يتطلب الوصول إلى مفاتيح التوقيع فقط. تعمل هذه المرحلة كبوابة.
  • Stage — النشر في بيئة اختبارية للتحقق النهائي. يتطلب صلاحية الكتابة في بيئة الاختبار فقط. لا تتوفر بيانات اعتماد الإنتاج.
  • Deploy — ترقية القطعة الموقّعة والمختبرة إلى الإنتاج. يتطلب صلاحية الكتابة في الإنتاج، مع بوابة موافقة يدوية. هوية مختلفة عن البناء.

كل حد بين المراحل هو حد ثقة. لا تتدفق بيانات الاعتماد بين المراحل إلا إذا مُنحت صراحةً.

أنماط Least Privilege

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

GitHub Actions: صلاحيات لكل وظيفة (job)

يوفر GitHub Actions كتلة permissions تتحكم في نطاقات GITHUB_TOKEN المُنشأ تلقائيًا. بشكل افتراضي، يمتلك هذا الرمز صلاحيات قراءة/كتابة واسعة. يجب عليك دائمًا تقييده.

عيّن إعدادات افتراضية مقيّدة على مستوى سير العمل وامنح صلاحيات إضافية فقط لوظائف محددة تحتاجها:

# .github/workflows/deploy.yml
name: Build and Deploy

# Restrict default permissions for ALL jobs in this workflow
permissions:
  contents: read

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    # This job inherits the workflow-level permissions: contents read only
    steps:
      - uses: actions/checkout@v4
      - run: make build
      - uses: actions/upload-artifact@v4
        with:
          name: app-binary
          path: dist/

  security-scan:
    needs: build
    runs-on: ubuntu-latest
    permissions:
      security-events: write  # Only this job can write security findings
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: github/codeql-action/analyze@v3

  deploy-staging:
    needs: [build, security-scan]
    runs-on: ubuntu-latest
    environment: staging  # Scoped to staging secrets only
    permissions:
      contents: read
      id-token: write  # OIDC token for cloud auth — no static credentials
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/staging-deployer
          aws-region: us-east-1
      - run: ./scripts/deploy.sh staging

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production  # Requires manual approval + different secrets
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/production-deployer
          aws-region: us-east-1
      - run: ./scripts/deploy.sh production

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

GitLab CI: المتغيرات المحمية والمشغّلات المحمية

يوفر GitLab CI مجموعة مختلفة ولكن بنفس القوة من الضوابط لتطبيق least privilege:

# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy-staging
  - deploy-production

build:
  stage: build
  tags:
    - shared-runners  # Non-privileged runners for build
  script:
    - make build
  artifacts:
    paths:
      - dist/

test:
  stage: test
  tags:
    - shared-runners
  script:
    - make test
  dependencies:
    - build

deploy-staging:
  stage: deploy-staging
  tags:
    - deploy-runners  # Dedicated runners with network access to staging
  environment:
    name: staging
  script:
    - ./scripts/deploy.sh staging
  # CI_JOB_TOKEN is automatically scoped to this project
  # Staging secrets are only available on protected branches
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

deploy-production:
  stage: deploy-production
  tags:
    - production-runners  # Isolated runners with production network access
  environment:
    name: production
  script:
    - ./scripts/deploy.sh production
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual  # Requires manual approval
  allow_failure: false  # Block the pipeline if not approved

في GitLab، استخدم protected variables بحيث تكون بيانات اعتماد الإنتاج متاحة فقط للفروع والعلامات المحمية. استخدم protected runners لضمان أن وظائف نشر الإنتاج تُنفّذ فقط على بنية تحتية معزولة ومؤمّنة. ضع علامة masked على أسرار الإنتاج لمنع كشفها عرضيًا في السجلات.

حسابات خدمة لكل مرحلة مع أدوار IAM محددة النطاق

بعيدًا عن منصة CI نفسها، طبّق least privilege على مستوى مزود الخدمة السحابية. يجب أن تتحقق كل مرحلة من خط الأنابيب كحساب خدمة مختلف بصلاحيات محددة بدقة:

  • مرحلة Build: صلاحية قراءة فقط لمستودعات الشيفرة المصدرية وسجلات التبعيات. صلاحية كتابة في مخزن القطع البرمجية (مثل S3 bucket أو container registry) فقط لا غير.
  • مرحلة Test: صلاحية قراءة فقط للقطع البرمجية. إذن لإنشاء وتدمير بنية تحتية اختبارية مؤقتة، لكن لا وصول إلى بيئة الاختبار أو الإنتاج.
  • مرحلة Deploy: صلاحية كتابة لهدف النشر المحدد (مثل Kubernetes namespace واحد أو خدمة ECS محددة). لا وصول إلى بيئات أو خدمات أخرى.

بيانات اعتماد قصيرة العمر عبر OIDC

بيانات الاعتماد الثابتة المخزنة كأسرار CI/CD تمثل مسؤولية أمنية. لا تنتهي صلاحيتها، ويصعب تجديدها، وهي أهداف جذابة للمهاجمين. النهج الحديث هو استخدام OIDC federation بحيث تستبدل منصة CI/CD الخاصة بك رمزًا موقّعًا قصير العمر ببيانات اعتماد سحابية مؤقتة:

  • يمكن لـ GitHub Actions أن يفترض أدوار AWS IAM أو حسابات خدمة GCP أو هويات Azure المُدارة باستخدام صلاحية id-token: write — دون الحاجة إلى أسرار مخزنة.
  • يدعم GitLab CI نظام OIDC أصلاً من خلال CI_JOB_JWT أو كلمة id_tokens المفتاحية، مما يتيح نفس النمط.
  • عادةً ما تستمر بيانات الاعتماد هذه من 15 إلى 60 دقيقة وتكون محددة النطاق للوظيفة المحددة التي طلبتها.

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

حماية تعريفات خط الأنابيب

Pipeline-as-code أداة قوية، لكنها تقدم مشكلة ثقة خفية: إذا تمكن مهاجم من تعديل تعريف خط الأنابيب، فإنه يتحكم في كيفية بناء الشيفرة واختبارها ونشرها. حماية ملفات تكوين خط الأنابيب لا تقل أهمية عن حماية شيفرة التطبيق نفسها.

CODEOWNERS لملفات سير العمل

استخدم ملف CODEOWNERS لإلزام فرق محددة بمراجعة التغييرات على تكوين CI/CD:

# .github/CODEOWNERS
/.github/workflows/   @your-org/platform-security
/.gitlab-ci.yml       @your-org/platform-security
/Jenkinsfile          @your-org/platform-security
/terraform/           @your-org/infrastructure

هذا يضمن أنه لا يمكن لأحد تعديل تعريفات خط الأنابيب دون موافقة الفريق المسؤول عن أمان CI/CD. ادمج هذا مع قواعد حماية الفرع التي تتطلب موافقة CODEOWNERS.

حماية الفروع على مجلدات تكوين خط الأنابيب

فرض قواعد حماية الفروع التي تمنع الدفع المباشر إلى الفروع التي تحتوي على تعريفات خط الأنابيب. كحد أدنى:

  • اشتراط مراجعات طلبات السحب قبل دمج التغييرات على ملفات سير العمل.
  • اشتراط نجاح فحوصات الحالة (بما في ذلك فحوصات الأمان لتغييرات سير العمل نفسها).
  • تعطيل الدفع القسري إلى الفروع المحمية.
  • اشتراط التزامات موقّعة للتغييرات على تكوين خط الأنابيب.

قوالب خط أنابيب غير قابلة للتغيير

يدعم كل من GitHub Actions وGitLab CI الإشارة إلى تعريفات خط الأنابيب من مستودعات خارجية مُدارة مركزيًا:

GitHub Actions reusable workflows:

# In your repository's workflow, reference a centrally managed template
jobs:
  deploy:
    uses: your-org/shared-workflows/.github/workflows/secure-deploy.yml@v2.1.0
    with:
      environment: production
      artifact-name: app-binary
    secrets: inherit

GitLab CI includes from protected repos:

# .gitlab-ci.yml
include:
  - project: 'platform-team/ci-templates'
    ref: 'v3.0.0'
    file: '/templates/secure-deploy.yml'

# Local jobs can use templates but cannot override protected stages
deploy-production:
  extends: .secure-deploy-template
  variables:
    TARGET_ENV: production

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

منع خطوط الأنابيب ذاتية التعديل

لا ينبغي لخط أنابيب أن يتمكن أبدًا من تعديل تعريفه الخاص. احترس من هذه الأنماط:

  • خطوات خط الأنابيب التي تكتب في .github/workflows/ أو .gitlab-ci.yml وتلتزم بالتغييرات.
  • توليد خط أنابيب ديناميكي يسحب التكوين من مصادر غير موثوقة.
  • متغيرات خط الأنابيب التي يمكنها تجاوز إعدادات حرجة أمنيًا مثل أي مشغّل يُستخدم أو أي بيئة يُنشر فيها.

إذا كنت تحتاج إلى سلوك ديناميكي لخط الأنابيب، استخدم قوالب معلمية مع مجموعة ثابتة من المدخلات المسموحة بدلاً من السماح بتعديل تعسفي لمنطق خط الأنابيب.

ضوابط النشر

ضوابط النشر هي البوابات بين مراحل خط الأنابيب التي تفرض الرقابة البشرية والامتثال للسياسات. إنها حيث يصبح separation of duties ملموسًا.

المراجعون المطلوبون والموافقات اليدوية

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

  • GitHub Environments تتيح لك تكوين مراجعين مطلوبين. عندما تشير وظيفة سير العمل إلى بيئة ذات قواعد حماية، يتوقف خط الأنابيب حتى يوافق مراجع مخوّل.
  • GitLab Protected Environments تقيّد المستخدمين أو المجموعات التي يمكنها تفعيل عمليات النشر في بيئات محددة. بالاقتران مع when: manual، يُنشئ هذا بوابة موافقة.

GitHub Environments مع قواعد الحماية

GitHub Environments آلية قوية لضوابط النشر. كوّنها بما يلي:

  • مراجعون مطلوبون: حدد أفرادًا أو فرقًا يجب أن يوافقوا قبل تشغيل الوظيفة. استخدم مراجعَين على الأقل للإنتاج.
  • مؤقت انتظار: أضف تأخيرًا بين الموافقة والتنفيذ، مما يمنح وقتًا لاكتشاف الأخطاء أو التنسيق مع نوافذ التغيير.
  • فروع النشر: قيّد الفروع التي يمكنها النشر في البيئة. يجب أن يقبل الإنتاج عمليات النشر من main أو release/* فقط.
  • أسرار البيئة: خزّن بيانات الاعتماد على مستوى البيئة، وليس على مستوى المستودع. هذا يضمن أن أسرار بيئة الاختبار غير متاحة لوظائف الإنتاج والعكس صحيح.

تجميد النشر ونوافذ التغيير

نفّذ تجميد النشر خلال فترات الأعمال الحرجة (مثل الجمعة البيضاء أو نهاية الربع) من خلال:

  • استخدام قواعد حماية البيئة المجدولة التي تحظر عمليات النشر تلقائيًا خلال النوافذ المحددة.
  • اشتراط موافقات إضافية خلال فترات التجميد بدلاً من الحظر الكامل — يجب أن تظل الإصلاحات الطارئة ممكنة مع رقابة مشددة.
  • تسجيل جميع تجاوزات التجميد لأغراض التدقيق.

النشر التدريجي (Canary) كآلية تحكم

استراتيجيات النشر التدريجي ليست مجرد مسألة توافرية — إنها ضابط أمني. إذا تجاوزت قطعة برمجية مخترقة جميع الفحوصات الأخرى، فإن نشر canary يحدّ من نطاق الضرر:

  • انشر على 1-5% من حركة المرور أولاً مع فحوصات صحية آلية.
  • اشترط موافقة يدوية ثانية للمتابعة بعد مرحلة canary.
  • أتمت التراجع إذا تجاوزت معدلات الأخطاء أو زمن الاستجابة العتبات المحددة.
  • عامل مرحلة canary كبيئة منفصلة بمتطلبات موافقة خاصة بها.

التدقيق والمساءلة

Separation of duties وleast privilege فعّالان فقط إذا كنت تستطيع التحقق من اتباعهما. التدقيق والمساءلة يغلقان الحلقة من خلال تقديم دليل على من فعل ماذا ومتى ولماذا.

سجلات تنفيذ خط الأنابيب كمسارات تدقيق

تحتفظ منصات CI/CD بسجلات مفصلة لكل عملية تنفيذ لخط الأنابيب. عامل هذه السجلات كبيانات تدقيق ذات صلة أمنية:

  • احتفظ بسجلات خط الأنابيب لمدة 90 يومًا على الأقل (أطول إذا تطلب إطار الامتثال الخاص بك ذلك).
  • صدّر السجلات إلى مخزن سجلات مركزي مقاوم للتلاعب (مثل SIEM أو CloudWatch Logs أو S3 bucket مخصص مع object lock).
  • تأكد أن السجلات تلتقط الهوية التي أطلقت خط الأنابيب، والأسرار التي تم الوصول إليها (دون قيمها)، والموافقات التي تم منحها.

ربط عمليات النشر بالالتزامات والموافقين

يجب أن يكون كل نشر إنتاجي قابلاً للتتبع إلى:

  • SHA الالتزام المحدد في Git الذي تم نشره.
  • طلب السحب الذي أدخل التغيير، بما في ذلك جميع المراجعين والموافقين.
  • معرّف تشغيل خط الأنابيب والشخص الذي وافق على بوابة النشر.
  • بصمة القطعة البرمجية (SHA صورة الحاوية، تجزئة الملف الثنائي) التي تم نشرها.

يجب أن تكون سلسلة التتبع هذه مؤتمتة. إذا سأل أحد “ما الذي يعمل في الإنتاج ومن وافق عليه”، يجب أن تكون الإجابة متاحة في ثوانٍ وليس ساعات.

سجلات التدقيق السحابية للتغييرات التي يبدأها خط الأنابيب

تترك إجراءات خط الأنابيب آثارًا في سجلات تدقيق مزود الخدمة السحابية. اربط هذه السجلات بسجلات CI/CD الخاصة بك:

  • AWS CloudTrail يسجل كل استدعاء API يقوم به دور IAM المفترض لخط الأنابيب. اربط معرّف تشغيل خط الأنابيب مع userIdentity.sessionContext في CloudTrail لربط التغييرات السحابية بعمليات تنفيذ محددة لخط الأنابيب.
  • GCP Cloud Audit Logs توفر تتبعًا مماثلاً لإجراءات حسابات الخدمة.
  • Azure Activity Logs تلتقط تعديلات الموارد التي تقوم بها service principals لخط الأنابيب.

التنبيه على تصعيد الصلاحيات أو تجاوز السياسات

أعد تنبيهات للأحداث التي تشير إلى أن ضوابطك يتم التحايل عليها:

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

أدخل هذه التنبيهات في سير عمل عمليات الأمان الخاصة بك وعاملها بنفس إلحاح حوادث الإنتاج.

الأنماط المضادة الشائعة

معرفة ما يجب تجنبه لا تقل أهمية عن معرفة ما يجب تطبيقه. هذه هي الأنماط المضادة التي نراها أكثر شيوعًا في تقييمات أمان CI/CD.

رمز مسؤول واحد لجميع عمليات CI/CD

Personal access token بنطاق admin، أنشأه مهندس كبير، مخزن كسر في المستودع، ويستخدمه كل وظيفة في كل خط أنابيب. عندما يغادر ذلك المهندس المؤسسة، لا أحد يلغي الرمز لأن لا أحد يعرف ما الذي سيتعطل. هذا هو النمط المضاد الأكثر شيوعًا والأكثر خطورة.

الحل: استبدله بحسابات خدمة لكل مرحلة باستخدام OIDC federation. لا رموز ثابتة، ولا هويات مشتركة.

تعطيل حماية الفرع “مؤقتًا”

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

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

مشغّلات مشتركة بين الإنتاج وأعباء عمل طلبات السحب

خطوط أنابيب طلبات السحب من النسخ المتفرعة (forks) تعمل على نفس البنية التحتية التي لديها وصول شبكي إلى أنظمة الإنتاج. يمكن لطلب سحب خبيث تسريب الأسرار، أو الوصول إلى الخدمات الداخلية، أو التمحور إلى بنية الإنتاج التحتية.

الحل: استخدم مجموعات مشغّلات منفصلة. الأعباء غير الموثوقة (طلبات السحب، خاصة من النسخ المتفرعة) تعمل على مشغّلات مؤقتة ومعزولة بدون وصول إلى البيئات الحساسة. مشغّلات نشر الإنتاج مقيّدة بالفروع المحمية فقط.

الوصول اليدوي عبر SSH عند فشل خطوط الأنابيب

عندما يفشل خط أنابيب النشر، يتصل مهندس مباشرة بخادم الإنتاج عبر SSH وينشر يدويًا. هذا يتجاوز كل ضابط في خط الأنابيب: مراجعة الشيفرة، والاختبار الآلي، وتوقيع القطع البرمجية، وموافقة النشر، وتسجيل التدقيق.

الحل: استثمر في موثوقية خط الأنابيب بحيث نادرًا ما يُحتاج إلى تدخل يدوي. عندما يُحتاج إليه، استخدم إجراء break-glass يتطلب موافقات متعددة، وينشئ مسار تدقيق، ويطلق مراجعة ما بعد الحادث.

الخلاصة

Separation of duties وleast privilege ليسا عبئًا بيروقراطيًا يفرضه فريق الامتثال. إنهما ضوابط هندسية تقلل مباشرة من نطاق الضرر الناجم عن الحوادث الأمنية في خط تسليم البرمجيات الخاص بك.

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

ابدأ بتدقيق صلاحيات خط الأنابيب الحالي. حدد كل حساب خدمة، وكل بيانات اعتماد مخزنة، وكل سر يمكن لخط الأنابيب الوصول إليه. اربط كل واحد منها بالمرحلة والمهمة المحددة التي تحتاجه. ثم ابدأ بتقليل النطاق: استبدل بيانات الاعتماد الثابتة بـ OIDC، وقسّم حسابات الخدمة الواحدة إلى هويات لكل مرحلة، وأضف بوابات موافقة لعمليات نشر الإنتاج، واحمِ تعريفات خط الأنابيب بـ CODEOWNERS وحماية الفروع.

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