تمرين عملي: تأمين خطوط أنابيب GitLab CI — Protected Variables و Runners و Environments

نظرة عامة

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

في هذا التمرين العملي ستمر بستة تمارين تُؤمّن خط أنابيب GitLab CI بشكل تدريجي. ستبدأ بتكوين غير آمن عمدًا حيث تكون جميع المتغيرات مرئية لكل فرع، وتتعامل shared runners مع جميع المهام، ولا توجد بوابات بيئية. بنهاية التمرين سيكون لديك خط أنابيب يفرض وصولًا محدودًا للمتغيرات وفق مبدأ الحد الأدنى من الصلاحيات، وrunners مخصصة النطاق، وبيئات محمية مع موافقات على النشر، وتقييد وصول CI_JOB_TOKEN، وخطوط أنابيب merge request آمنة، وضوابط تقوية إضافية تشمل كشف الأسرار.

كل أمر ومقطع YAML ومسار واجهة مستخدم في هذا التمرين مبني على GitLab 16.x / 17.x ويعمل على الطبقة المجانية من GitLab.com.

المتطلبات الأساسية

  • حساب GitLab — الطبقة المجانية على gitlab.com كافية لجميع التمارين.
  • مشروع تجريبي يحتوي على تطبيق بسيط (حتى ملف index.html واحد يكفي) وملف .gitlab-ci.yml في جذر المستودع.
  • إلمام أساسي بـصيغة GitLab CI: المراحل (stages)، والمهام (jobs)، والسكربتات (scripts)، والقواعد (rules).
  • (اختياري) جهاز Linux أو macOS إذا كنت تخطط لتسجيل GitLab Runner خاص بك في التمرين 2.

إعداد البيئة

الخطوة 1 — إنشاء مشروع GitLab جديد

  1. انتقل إلى GitLab > New Project > Create blank project.
  2. سمّه secure-pipeline-lab، واضبط الرؤية على Private، وقم بتهيئته مع ملف README.
  3. تحت Settings > Repository > Protected branches، تأكد أن main مُدرج كفرع محمي (هذا هو الإعداد الافتراضي).

الخطوة 2 — إضافة تطبيق بسيط

أنشئ ملف index.html في جذر المستودع:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Secure Pipeline Lab</title></head>
<body><h1>Hello, GitLab CI!</h1></body>
</html>

الخطوة 3 — إنشاء خط الأنابيب الأولي (غير الآمن)

أضف ملف .gitlab-ci.yml التالي. هذا غير آمن عمدًا — إنه نقطة البداية التي سنقوم بتقويتها خلال التمرين:

# .gitlab-ci.yml — INSECURE starting point
stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - echo "Building the application..."
    - echo "DB_PASSWORD is $DB_PASSWORD"   # Variable printed to logs!

test-job:
  stage: test
  script:
    - echo "Running tests..."
    - echo "API_KEY is $API_KEY"            # Variable printed to logs!

deploy-job:
  stage: deploy
  script:
    - echo "Deploying to production..."
    - echo "DEPLOY_TOKEN is $DEPLOY_TOKEN" # Variable printed to logs!

يعاني خط الأنابيب هذا من عدة مشاكل:

  • جميع متغيرات CI/CD متاحة لـكل فرع، بما في ذلك الفروع التي ينشئها مساهمون خارجيون.
  • يتم طباعة المتغيرات مباشرة في سجلات المهام — أي شخص لديه وصول للسجلات يمكنه قراءتها.
  • تعمل المهام على shared runners بدون ضمانات عزل.
  • لا توجد بوابات بيئية — تعمل مهمة النشر تلقائيًا عند كل دفع.

قم بإيداع هذا الملف في main وتحقق من تشغيل خط الأنابيب. الآن لنقم بإصلاح كل من هذه المشاكل.

التمرين 1: Protected Variables و Masked Variables

تدعم متغيرات GitLab CI/CD ثلاث علامات حماية تقلل بشكل كبير من نطاق الضرر في حالة اختراق فرع أو fork.

فهم العلامات الثلاث

العلامة التأثير
Protected يتم حقن المتغير فقط في خطوط الأنابيب التي تعمل على الفروع أو الوسوم المحمية. لن يرى خط أنابيب يعمل من فرع ميزة أو fork القيمة أبدًا.
Masked يحجب GitLab قيمة المتغير من سجلات المهام. إذا طبع سكربت القيمة عن طريق الخطأ، يعرض السجل [MASKED] بدلاً منها.
Hidden (GitLab 17+) لا يمكن كشف قيمة المتغير في واجهة المستخدم بعد إنشائه — حتى من قبل مشرفي المشروع. مفيد للأسرار التي يديرها فريق المنصة والتي لا يجب أن يراها المطورون بنص واضح أبدًا.

الخطوة 1 — إنشاء المتغيرات

  1. اذهب إلى Settings > CI/CD > Variables > Expand > Add variable.
  2. أنشئ المتغيرات التالية:
المفتاح القيمة (مثال) Protected Masked Hidden
DEPLOY_TOKEN glpat-xxxxxxxxxxxxxxxxxxxx نعم نعم لا
DB_PASSWORD S3cur3P@ssw0rd!2024 نعم نعم نعم
API_KEY sk-test-abc123def456 لا نعم لا

الخطوة 2 — تحديث خط الأنابيب

# .gitlab-ci.yml — Exercise 1
stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - echo "Building the application..."
    - echo "API_KEY value length = ${#API_KEY}"  # Safe: prints length, not value

test-job:
  stage: test
  script:
    - echo "Running tests..."
    # Attempting to print a masked variable:
    - echo "DB_PASSWORD is $DB_PASSWORD"
    # Output will show: DB_PASSWORD is [MASKED]

deploy-job:
  stage: deploy
  script:
    - echo "Deploying with DEPLOY_TOKEN..."
    - echo "Token is $DEPLOY_TOKEN"
    # On main (protected): Token is [MASKED]
    # On feature branch: Token is <empty — variable not injected>
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

الخطوة 3 — التحقق من سلوك الحماية

  1. ادفع على main — تعمل مهمة النشر ويتم حقن DEPLOY_TOKEN (يعرض السجل [MASKED]).
  2. أنشئ فرعًا feature/test-vars، وادفع إيداعًا — لا تعمل مهمة النشر (القواعد تقيدها بـ main). حتى لو عدّلت القواعد للسماح بتشغيلها، فإن DEPLOY_TOKEN وDB_PASSWORD فارغان لأن الفرع غير محمي.
  3. API_KEY، المحجوب لكن غير المحمي، متاح على كلا الفرعين — يتم تنقيح قيمته في السجلات.

الدرس الأساسي: قم دائمًا بتعيين بيانات اعتماد النشر على أنها Protected وMasked معًا. استخدم Hidden للأسرار التي لا يجب أن يستردها المطورون من واجهة المستخدم أبدًا.

التمرين 2: أمان Runner وتحديد النطاق

تُعد Runners محركات الحوسبة التي تنفذ مهام CI الخاصة بك. اختيار نوع Runner المناسب — وتحديد نطاقه بشكل صحيح — هو أحد أكثر القرارات الأمنية تأثيرًا التي يمكنك اتخاذها.

أنواع Runner

النوع النطاق الوضع الأمني
Instance (shared) متاح لكل مشروع على نسخة GitLab متعدد المستأجرين. قد تعمل مهام مشاريع أخرى على نفس الجهاز. خطر تسرب البيانات عبر نظام الملفات المشترك أو Docker socket أو الطبقات المخزنة مؤقتًا.
Group متاح لكل مشروع في مجموعة محددة عزل أفضل من instance runners، لكنه لا يزال مشتركًا عبر المشاريع داخل المجموعة.
Project متاح لمشروع واحد فقط أفضل عزل. أنت تتحكم في الجهاز وتكوين Docker والوصول للشبكة.

الخطوة 1 — تسجيل Runner خاص بالمشروع

على جهاز تتحكم فيه (جهاز افتراضي أو خادم احتياطي أو حتى مضيف Docker محلي)، قم بتثبيت GitLab Runner وتسجيله:

# Install GitLab Runner (Linux amd64)
sudo curl -L --output /usr/local/bin/gitlab-runner \
  https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
sudo chmod +x /usr/local/bin/gitlab-runner
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start

# Register the runner
# Find your registration token: Settings > CI/CD > Runners > Expand > New project runner
sudo gitlab-runner register \
  --non-interactive \
  --url https://gitlab.com/ \
  --token "$RUNNER_TOKEN" \
  --executor docker \
  --docker-image alpine:latest \
  --description "secure-deploy-runner" \
  --tag-list "secure-deploy" \
  --access-level ref_protected

العلامة الحاسمة هي --access-level ref_protected. تُخبر هذه GitLab أن Runner سيقوم فقط بالتقاط المهام من الفروع أو الوسوم المحمية. لن يتم جدولة خط أنابيب يُشغَّل بواسطة فرع ميزة أو merge request من fork على هذا الـ Runner أبدًا.

الخطوة 2 — تعطيل Shared Runners للمهام الحساسة

اذهب إلى Settings > CI/CD > Runners وقم بتبديل Enable shared runners for this project إلى إيقاف — أو اتركها مفعلة للمراحل غير الحساسة واستخدم الوسوم لتوجيه المهام الحساسة إلى runner المشروع الخاص بك.

الخطوة 3 — تحديث خط الأنابيب مع اختيار Runner بناءً على الوسوم

# .gitlab-ci.yml — Exercise 2
stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  # Runs on any available runner (shared is fine for builds)
  script:
    - echo "Building the application..."

test-job:
  stage: test
  script:
    - echo "Running tests..."

deploy-job:
  stage: deploy
  tags:
    - secure-deploy            # Only runs on runner(s) with this tag
  script:
    - echo "Deploying with DEPLOY_TOKEN..."
    - |
      curl --fail --silent --header "PRIVATE-TOKEN: $DEPLOY_TOKEN" \
        https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/releases
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

بما أن runner secure-deploy مسجل بوصول ref_protected، فإن مهمة النشر هذه ستعمل فقط على runner المشروع المخصص و فقط عندما ينشأ خط الأنابيب من مرجع محمي.

التمرين 3: Protected Environments وموافقات النشر

حتى مع protected variables وrunners محددة النطاق، قد ترغب في بوابة بشرية قبل وصول الكود إلى الإنتاج. توفر protected environments في GitLab ذلك بالضبط.

الخطوة 1 — إنشاء البيئات

  1. انتقل إلى Operate > Environments > New environment.
  2. أنشئ بيئتين: staging وproduction.

الخطوة 2 — حماية بيئة Production

  1. اذهب إلى Settings > CI/CD > Protected environments (متاح على Premium/Ultimate، أو على النسخة المُدارة ذاتيًا المجانية).
  2. اختر production.
  3. تحت Allowed to deploy، قيّد الوصول إلى Maintainers (أو مستخدم محدد).
  4. تحت Required approvals، اضبطها على 1 (أو أكثر، حسب سياستك).
  5. أضف المُوافِق (المُوافِقين) المعيّنين.

الخطوة 3 — تحديث خط الأنابيب مع تعريفات البيئة

# .gitlab-ci.yml — Exercise 3
stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - echo "Building the application..."

test-job:
  stage: test
  script:
    - echo "Running tests..."

deploy-staging:
  stage: deploy
  environment:
    name: staging
    url: https://staging.example.com
  script:
    - echo "Deploying to staging..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

deploy-production:
  stage: deploy
  tags:
    - secure-deploy
  environment:
    name: production
    url: https://prod.example.com
  script:
    - echo "Deploying to production..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual           # Requires a human click
  allow_failure: false        # Pipeline stays blocked until approved

كيف تعمل الموافقة

  1. دفع إلى main يُشغّل خط الأنابيب.
  2. deploy-staging يعمل تلقائيًا.
  3. deploy-production يُظهر زر Play في واجهة خط الأنابيب.
  4. النقر على Play لا يُشغّل المهمة فورًا — يتحقق GitLab من قواعد حماية البيئة ويعرض مربع حوار الموافقة على المُوافِق (المُوافِقين) المعيّنين.
  5. فقط بعد الحصول على العدد المطلوب من الموافقات تبدأ المهمة.

هذه البوابة ذات الطبقتين — when: manual بالإضافة إلى موافقة البيئة — تضمن أنه لا يمكن لشخص واحد دفع الكود مباشرة إلى الإنتاج دون مراجعة.

التمرين 4: تحديد نطاق CI_JOB_TOKEN

تحصل كل مهمة في GitLab CI على رمز تلقائي في متغير CI_JOB_TOKEN. يُصادق هذا الرمز طلبات API وGit باسم مشروع خط الأنابيب. بشكل افتراضي، نطاقه واسع بشكل خطير.

المخاطر

بدون قيود، يمكن لمهمة في المشروع A استخدام CI_JOB_TOKEN لاستنساخ أو استدعاء API لـأي مشروع آخر في نفس المجموعة (أو النسخة، حسب الإعدادات). إذا حقن مساهم خبيث سكربتًا في مهمة CI، يمكنه تسريب الكود من مستودعات غير ذات صلة.

الخطوة 1 — تقييد نطاق الرمز

  1. اذهب إلى Settings > CI/CD > Token Access.
  2. بدّل Limit access to this project إلى Enabled.
  3. تحت Allow CI job tokens from the following projects to access this project، أضف فقط المشاريع التي تحتاج فعلاً إلى الوصول (نموذج القائمة البيضاء).
  4. تحت Limit CI_JOB_TOKEN access to the following projects (الصادر)، أضف فقط المشاريع التي يحتاج خط الأنابيب للوصول إليها.

الخطوة 2 — اختبار الوصول

# .gitlab-ci.yml — Exercise 4
stages:
  - test

test-token-allowed:
  stage: test
  script:
    - echo "Cloning an allowed project..."
    - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/my-group/allowed-project.git
    - echo "Success — access permitted"

test-token-denied:
  stage: test
  script:
    - echo "Cloning a non-allowed project..."
    - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/my-group/restricted-project.git
    # Expected output: remote: HTTP Basic: Access denied
    # fatal: Authentication failed — 403 Forbidden
  allow_failure: true

الخطوة 3 — التحقق

  1. شغّل خط الأنابيب. test-token-allowed ينجح ويستنسخ المشروع المسموح به.
  2. test-token-denied يفشل بخطأ 403 Forbidden لأن restricted-project ليس في القائمة البيضاء.

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

التمرين 5: أمان خطوط أنابيب Merge Request

تعمل خطوط أنابيب merge request (MR) عندما يفتح مساهم أو يُحدّث merge request. وهي ضرورية لجودة الكود — لكنها يمكن أن تكون أيضًا ناقل هجوم إذا لم يتم تكوينها بعناية.

المخاطر

عندما يقوم مساهم خارجي بعمل fork لمشروعك ويفتح MR، يمكن لـ GitLab تشغيل خط أنابيب على ذلك الـ MR. إذا كان خط الأنابيب يملك وصولاً إلى protected variables أو runners ذات صلاحيات عالية، يمكن لكود المساهم تسريب الأسرار.

الخطوة 1 — تكوين قواعد خط أنابيب MR

# .gitlab-ci.yml — Exercise 5
stages:
  - validate
  - build
  - deploy

# --- Jobs that are safe to run on MR pipelines (no secrets needed) ---
lint:
  stage: validate
  script:
    - echo "Linting code..."
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

unit-tests:
  stage: validate
  script:
    - echo "Running unit tests..."
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

# --- Jobs that require secrets — never run on MR pipelines ---
build-image:
  stage: build
  script:
    - echo "Building and pushing Docker image..."
    - echo "Using REGISTRY_TOKEN = $REGISTRY_TOKEN"  # Protected + Masked
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

deploy-production:
  stage: deploy
  tags:
    - secure-deploy
  environment:
    name: production
    url: https://prod.example.com
  script:
    - echo "Deploying to production..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual

كيف يتعامل GitLab مع خطوط أنابيب Fork MR

  • خطوط الأنابيب التي يتم تشغيلها بواسطة merge_request_event من fork تعمل تلقائيًا بـصلاحيات محدودة.
  • لا يتم حقن protected variables أبدًا في خطوط أنابيب fork MR.
  • CI_JOB_TOKEN في خطوط أنابيب fork له نطاق مخفض — يمكنه فقط الوصول إلى المشروع المصدر (fork)، وليس المشروع الهدف.

بفصل مهامك إلى “آمنة لـ MR” (lint، test) و”تتطلب أسرارًا” (build، deploy)، تضمن أن المساهمين يمكنهم التحقق من كودهم دون كشف بيانات الاعتماد.

أفضل الممارسات لخطوط أنابيب MR

  • لا تستخدم only/except أبدًا — فضّل rules: للوضوح والصحة.
  • قيّد المهام التي تعتمد على الأسرار بـ if: $CI_COMMIT_BRANCH == "main" (أو مرجع محمي آخر).
  • فكّر في تفعيل Pipelines must succeed تحت Settings > Merge requests لاشتراط نجاح خط أنابيب MR قبل الدمج.
  • فعّل Merged results pipelines لاختبار نتيجة الدمج بدلاً من الفرع المصدر فقط — هذا يكشف مشاكل التكامل مبكرًا.

التمرين 6: تقوية إضافية

مع تأمين المتغيرات وrunners والبيئات والرموز وخطوط أنابيب MR، توفر عدة ضوابط إضافية وضعًا أمنيًا بمستوى الإنتاج لخط الأنابيب الخاص بك.

مهلة المهام

يمكن استغلال المهام غير المحدودة للتعدين على العملات المشفرة أو للحفاظ على وصول دائم. حدد مهلات صريحة:

deploy-production:
  stage: deploy
  timeout: 10 minutes
  script:
    - echo "Deploying..."

خطوط الأنابيب القابلة للمقاطعة

امنع إهدار الموارد وحدّ من نافذة المهام الخبيثة طويلة التشغيل بتعيين المهام غير الحرجة كقابلة للمقاطعة:

lint:
  stage: validate
  interruptible: true     # Auto-cancelled if a newer pipeline starts
  script:
    - echo "Linting..."

Push Rules (تقييد إنشاء خطوط الأنابيب)

تحت Settings > Repository > Push rules، يمكنك:

  • رفض الإيداعات غير الموقّعة — يضمن أن كل إيداع موقّع بـ GPG.
  • تقييد أسماء الفروع — فرض اتفاقية تسمية (مثل feature/*، bugfix/*).
  • منع دفع الأسرار — يمكن لقاعدة الدفع المدمجة في GitLab حظر الملفات التي تطابق أنماط الأسرار الشائعة.

كشف الأسرار مع GitLab SAST

أضف قالب Secret Detection المدمج في GitLab للكشف عن بيانات الاعتماد المودعة عن طريق الخطأ:

include:
  - template: Security/Secret-Detection.gitlab-ci.yml

يضيف هذا مهمة secret_detection تفحص كل إيداع بحثًا عن مفاتيح API والرموز وكلمات المرور وأنماط الأسرار الأخرى. تظهر النتائج في علامة تبويب Security في merge requests.

خط الأنابيب النهائي المُقوّى

فيما يلي ملف .gitlab-ci.yml الكامل الذي يجمع كل ضوابط الأمان من هذا التمرين. كل سطر متعلق بالأمان مُعلّق عليه.

# .gitlab-ci.yml — Fully Hardened GitLab CI Pipeline

# Include GitLab's built-in secret detection scanner
include:
  - template: Security/Secret-Detection.gitlab-ci.yml  # Scans for leaked secrets

stages:
  - validate
  - build
  - deploy

# --- Default settings applied to all jobs ---
default:
  timeout: 10 minutes        # Prevent runaway/abused jobs

# --- Safe for merge request pipelines (no secrets required) ---
lint:
  stage: validate
  interruptible: true        # Cancel if a newer pipeline starts
  script:
    - echo "Linting source code..."
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"  # Run on MRs
    - if: $CI_COMMIT_BRANCH == "main"                    # Run on main

unit-tests:
  stage: validate
  interruptible: true
  script:
    - echo "Running unit tests..."
    - echo "API_KEY length = ${#API_KEY}"  # Safe: prints length only
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

# --- Requires secrets — only runs on protected branch ---
build-image:
  stage: build
  script:
    - echo "Building Docker image..."
    - echo "Authenticating to registry..."  # Uses REGISTRY_TOKEN (Protected + Masked)
  rules:
    - if: $CI_COMMIT_BRANCH == "main"       # Only on protected branch

# --- Staging deployment — automatic on main ---
deploy-staging:
  stage: deploy
  environment:
    name: staging                            # Tracked environment
    url: https://staging.example.com
  script:
    - echo "Deploying to staging..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

# --- Production deployment — manual + approval required ---
deploy-production:
  stage: deploy
  tags:
    - secure-deploy                          # Runs on project-specific runner only
  environment:
    name: production                         # Protected environment with approvals
    url: https://prod.example.com
  script:
    - echo "Deploying to production..."
    - |
      curl --fail --silent \
        --header "PRIVATE-TOKEN: $DEPLOY_TOKEN" \   # Protected + Masked variable
        --request POST \
        "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/deployments"
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual                           # Requires human trigger
  allow_failure: false                       # Pipeline blocks until approved
  timeout: 5 minutes                         # Tighter timeout for deploys

التنظيف

بعد إكمال التمرين، قم بتنظيف الموارد التجريبية:

  1. احذف أو أرشف المشروع التجريبي: اذهب إلى Settings > General > Advanced > Delete project.
  2. أزل متغيرات CI/CD: إذا كنت تخطط للاحتفاظ بالمشروع، اذهب إلى Settings > CI/CD > Variables واحذف المتغيرات التجريبية (DEPLOY_TOKEN، DB_PASSWORD، API_KEY).
  3. ألغِ تسجيل runner التجريبي:
# List registered runners
sudo gitlab-runner list

# Unregister the test runner
sudo gitlab-runner unregister --name "secure-deploy-runner"

# Optionally remove GitLab Runner entirely
sudo gitlab-runner stop
sudo gitlab-runner uninstall
sudo rm /usr/local/bin/gitlab-runner

النقاط الرئيسية

  • قم بحماية وحجب كل متغير سري. يتم حقن Protected variables فقط على الفروع المحمية، والحجب يمنع التعرض العرضي في السجلات. استخدم علامة Hidden للأسرار التي لا يجب أن تكون قابلة للقراءة في واجهة المستخدم أبدًا.
  • حدد نطاق runners إلى أدنى مستوى ثقة مطلوب. استخدم runners خاصة بالمشروع مع وصول ref_protected لمهام النشر. احتفظ بـ shared runners للخطوات غير الحساسة من البناء والاختبار.
  • قيّد عمليات نشر الإنتاج ببوابات حماية البيئة والموافقات. الجمع بين when: manual مع بيئة محمية وموافقين مطلوبين يضمن عدم قدرة شخص واحد على الدفع للإنتاج دون مراجعة.
  • قيّد CI_JOB_TOKEN بقائمة بيضاء صريحة. النطاق الافتراضي واسع جدًا. حدد الوصول الوارد والصادر إلى المشاريع التي يحتاجها خط الأنابيب فعلاً فقط.
  • افصل مهام خط أنابيب MR عن مهام النشر. مهام lint والاختبار آمنة لخطوط أنابيب merge request؛ مهام البناء والنشر التي تحتاج أسرارًا يجب أن تعمل فقط على الفروع المحمية.
  • أضف طبقات ضوابط إضافية: المهلات، والمهام القابلة للمقاطعة، وقواعد الدفع، وكشف الأسرار. كل طبقة تعالج ناقل هجوم مختلف ومعًا تُنشئ دفاعًا متعدد الطبقات.

الخطوات التالية

واصل بناء معرفتك بأمان CI/CD مع هذه الأدلة ذات الصلة: