مختبر: بناء خط أنابيب SBOM — التوليد والتصديق والتحقق باستخدام Syft وCosign

نظرة عامة

أصبحت قوائم مكونات البرمجيات (SBOMs) بسرعة عنصرًا إلزاميًا لشفافية سلسلة توريد البرمجيات. تتطلب الأوامر التنفيذية والأطر التنظيمية مثل NIST SSDF والمعايير الصناعية الآن من المؤسسات إنتاج وتوزيع والتحقق من SBOMs لكل إصدار برمجي. تسرد SBOM كل مكون ومكتبة وتبعية داخل برنامجك — مما يمنح المستهلكين القدرة على تقييم المخاطر وتتبع الثغرات والتحقق من المصدر.

في هذا المختبر العملي، ستبني خط أنابيب SBOM كامل من الصفر. بنهاية هذا المختبر، ستكون قادرًا على:

  • توليد SBOMs بتنسيقي SPDX وCycloneDX باستخدام Syft
  • فحص SBOMs بحثًا عن الثغرات المعروفة باستخدام Grype
  • إرفاق SBOMs كتصديقات موقعة لصور الحاويات باستخدام Cosign
  • أتمتة سير العمل بالكامل في GitHub Actions وGitLab CI
  • فرض متطلبات تصديق SBOM عند النشر باستخدام Kyverno
  • مقارنة SBOMs بين الإصدارات لاكتشاف تغييرات التبعيات

يحاكي هذا المختبر سير العمل الإنتاجي الحقيقي الذي تستخدمه الفرق التي تتبنى SLSA وin-toto وأمان سلسلة التوريد المبني على Sigstore.

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

قبل البدء، تأكد من تثبيت وتكوين الأدوات التالية:

الأداة الغرض التثبيت
Syft توليد SBOM curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
Grype فحص الثغرات curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
Cosign التوقيع والتصديق go install github.com/sigstore/cosign/v2/cmd/cosign@latest
Docker بناء الحاويات docs.docker.com
GitHub CLI (gh) الوصول إلى المستودع وGHCR brew install gh أو cli.github.com

تحتاج أيضًا إلى حساب GitHub مع إمكانية الوصول إلى GitHub Container Registry (GHCR)، وتطبيق أساسي يحتوي على Dockerfile.

إعداد البيئة

سننشئ تطبيق Node.js بسيط، ونحوله إلى حاوية، وندفعه إلى GHCR. تصبح هذه الصورة الهدف لجميع تمارين SBOM اللاحقة.

الخطوة 1: إنشاء مستودع الاختبار

mkdir sbom-pipeline-lab && cd sbom-pipeline-lab
git init

الخطوة 2: إنشاء تطبيق Node.js بسيط

cat > package.json <<'EOF'
{
  "name": "sbom-lab-app",
  "version": "1.0.0",
  "description": "SBOM pipeline lab application",
  "main": "server.js",
  "dependencies": {
    "express": "^4.18.2",
    "lodash": "^4.17.21",
    "axios": "^1.6.0"
  }
}
EOF
cat > server.js <<'EOF'
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.json({ status: 'ok', message: 'SBOM Pipeline Lab' });
});

app.listen(3000, () => console.log('Listening on port 3000'));
EOF

الخطوة 3: إنشاء Dockerfile

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

الخطوة 4: بناء صورة الحاوية ودفعها

# المصادقة على GHCR
echo $GITHUB_TOKEN | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin

# بناء الصورة
docker build -t ghcr.io/YOUR_GITHUB_USERNAME/sbom-lab-app:v1.0.0 .

# الدفع إلى GHCR
docker push ghcr.io/YOUR_GITHUB_USERNAME/sbom-lab-app:v1.0.0

استبدل YOUR_GITHUB_USERNAME باسم مستخدم GitHub الفعلي الخاص بك في جميع أنحاء هذا المختبر. بعد اكتمال الدفع، سجل ملخص الصورة الكامل — ستحتاج إليه لعمليات التوقيع.

# التقاط ملخص الصورة
export IMAGE=$(docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/YOUR_GITHUB_USERNAME/sbom-lab-app:v1.0.0)
echo $IMAGE
# Output: ghcr.io/YOUR_GITHUB_USERNAME/sbom-lab-app@sha256:abc123...

التمرين 1: توليد SBOM باستخدام Syft

Syft هي أداة مفتوحة المصدر من Anchore تولد SBOMs عن طريق تحليل صور الحاويات وأنظمة الملفات والأرشيفات. تدعم تنسيقات إخراج متعددة بما في ذلك SPDX وCycloneDX — المعياران المهيمنان لـ SBOM.

توليد SBOM بتنسيق SPDX

syft $IMAGE -o spdx-json=sbom.spdx.json

فحص المخرجات:

cat sbom.spdx.json | jq '.packages | length'
# Output: 287 (count varies based on image content)

# عرض الحزم المكتشفة
cat sbom.spdx.json | jq '.packages[] | {name: .name, version: .versionInfo, license: .licenseDeclared}' | head -40

توليد SBOM بتنسيق CycloneDX

syft $IMAGE -o cyclonedx-json=sbom.cyclonedx.json

فحص مخرجات CycloneDX:

cat sbom.cyclonedx.json | jq '.components | length'

# عرض المكونات مع التراخيص
cat sbom.cyclonedx.json | jq '.components[] | {name: .name, version: .version, type: .type}' | head -40

SPDX مقابل CycloneDX: الفروق الرئيسية

الميزة SPDX CycloneDX
الأصل Linux Foundation OWASP
التركيز الأساسي الامتثال للتراخيص والملكية الفكرية الأمان وتحليل المخاطر
معيار ISO ISO/IEC 5962:2021 ECMA-424
بيانات الثغرات دعم أصلي محدود حقل vulnerabilities من الدرجة الأولى
التنسيقات JSON, RDF, XML, YAML, tag-value JSON, XML, Protobuf
الأفضل لـ الامتثال التنظيمي، تدقيق التراخيص DevSecOps، تتبع الثغرات

في هذا المختبر، نستخدم بشكل أساسي SPDX JSON لأنه التنسيق المطلوب من قبل العديد من معايير المشتريات الحكومية ويتوافق بشكل جيد مع تصديقات Cosign. ومع ذلك، فإن كلا التنسيقين مدعومان من Grype وCosign.

توليد ملخص قابل للقراءة

syft $IMAGE -o syft-table

يطبع هذا جدولًا بجميع الحزم مع الاسم والإصدار والنوع — مفيد للمراجعة السريعة أثناء التطوير.

التمرين 2: فحص SBOM بحثًا عن الثغرات باستخدام Grype

Grype هو ماسح الثغرات من Anchore. يمكنه فحص صور الحاويات مباشرة، لكنه يمكنه أيضًا فحص ملف SBOM — وهو أسرع بشكل ملحوظ لأنه يتخطى خطوة تحليل الصورة.

فحص SBOM

grype sbom:./sbom.spdx.json

نموذج المخرجات:

NAME          INSTALLED  FIXED-IN   TYPE  VULNERABILITY   SEVERITY
lodash        4.17.21               npm   CVE-2025-XXXXX  Medium
node          20.10.0    20.11.1    apk   CVE-2024-22019  High
libcrypto3    3.1.4-r1   3.1.4-r3   apk   CVE-2024-0727   Medium

التصفية حسب الخطورة

# عرض الثغرات الحرجة والعالية فقط
grype sbom:./sbom.spdx.json --fail-on critical

# إخراج النتائج بتنسيق JSON للمعالجة في CI
grype sbom:./sbom.spdx.json -o json > vulnerabilities.json

# عد الثغرات حسب الخطورة
cat vulnerabilities.json | jq '[.matches[].vulnerability.severity] | group_by(.) | map({severity: .[0], count: length})'

فحص الصورة مقابل فحص SBOM

هناك فرق مهم بين فحص الصورة مباشرة وفحص SBOM:

# فحص مباشر للصورة — يسحب Grype طبقات الصورة ويحللها
grype $IMAGE

# فحص SBOM — يقرأ Grype قائمة الحزم المولدة مسبقًا
grype sbom:./sbom.spdx.json
النهج السرعة الدقة حالة الاستخدام
فحص مباشر للصورة أبطأ (يسحب الطبقات) يكتشف جميع الحزم التحليل الأولي، التطوير المحلي
فحص SBOM سريع (يقرأ ملف JSON) محدود بمحتويات SBOM خطوط أنابيب CI، الفحوصات المتكررة، التدقيق

فحص SBOM يكون شاملًا بقدر شمولية SBOM نفسها. إذا أغفل Syft حزمة ما (مثل ملف ثنائي مُجمَّع بشكل ثابت)، فلن يجد Grype ثغرات لها. للحصول على أقصى تغطية، قم بتوليد SBOM باستخدام خيار --catalogers all في Syft.

التمرين 3: إرفاق SBOM كتصديق Cosign

التصديق هو بيان موقع حول أداة برمجية. من خلال إرفاق SBOM كتصديق، فإنك تربط SBOM بشكل تشفيري بملخص الصورة المحدد — يمكن لأي شخص التحقق من أن SBOM قد تم إنتاجها لتلك الصورة بالتحديد ولم يتم التلاعب بها.

إرفاق تصديق SBOM

باستخدام تدفق Cosign بدون مفاتيح (Sigstore Fulcio):

cosign attest --predicate sbom.spdx.json \
  --type spdxjson \
  --yes \
  $IMAGE

يقوم هذا الأمر بما يلي:

  1. يفتح متصفحًا للمصادقة عبر OIDC (توقيع بدون مفاتيح عبر Fulcio)
  2. ينشئ تصديق in-toto مع SBOM الخاص بك كمسند
  3. يوقع التصديق ويسجله في سجل الشفافية Rekor
  4. يدفع التصديق إلى السجل بجانب الصورة

التحقق من التصديق

cosign verify-attestation \
  --type spdxjson \
  --certificate-identity=YOUR_EMAIL@example.com \
  --certificate-oidc-issuer=https://accounts.google.com \
  $IMAGE | jq '.payload | @base64d | fromjson | .predicate'

استبدل هوية الشهادة ومُصدر OIDC بالقيم المطابقة لهوية Sigstore الخاصة بك. في بيئات CI (GitHub Actions)، ستكون هذه:

--certificate-identity=https://github.com/YOUR_ORG/YOUR_REPO/.github/workflows/build.yml@refs/heads/main
--certificate-oidc-issuer=https://token.actions.githubusercontent.com

فحص التصديق في السجل

# سرد المراجع (سجلات OCI 1.1)
cosign tree $IMAGE

يجب أن ترى التصديق مدرجًا كمرجع مرفق ببيان الصورة. يتم تخزين التصديق كأداة OCI في نفس المستودع، مُعلَّم باتفاقية sha256-<digest>.att.

التمرين 4: بناء خط الأنابيب الكامل في GitHub Actions

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

أنشئ .github/workflows/sbom-pipeline.yml:

name: SBOM Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

permissions:
  contents: read
  packages: write
  id-token: write  # Required for Cosign keyless signing
  attestations: write

jobs:
  build-and-attest:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push image
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

      - name: Get image digest
        id: digest
        run: |
          echo "image=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT

      - name: Install Syft
        uses: anchore/sbom-action/download-syft@v0

      - name: Generate SPDX SBOM
        run: |
          syft ${{ steps.digest.outputs.image }} -o spdx-json=sbom.spdx.json
          echo "### SBOM Summary" >> $GITHUB_STEP_SUMMARY
          echo "Package count: $(cat sbom.spdx.json | jq '.packages | length')" >> $GITHUB_STEP_SUMMARY

      - name: Install Grype
        uses: anchore/scan-action/download-grype@v4

      - name: Scan SBOM for vulnerabilities
        run: |
          grype sbom:./sbom.spdx.json -o json > vulnerabilities.json
          grype sbom:./sbom.spdx.json -o table >> $GITHUB_STEP_SUMMARY

          # Fail if critical vulnerabilities are found
          CRITICAL_COUNT=$(cat vulnerabilities.json | jq '[.matches[] | select(.vulnerability.severity=="Critical")] | length')
          echo "Critical vulnerabilities: $CRITICAL_COUNT"
          if [ "$CRITICAL_COUNT" -gt 0 ]; then
            echo "::error::Found $CRITICAL_COUNT critical vulnerabilities. Failing pipeline."
            exit 1
          fi

      - name: Install Cosign
        uses: sigstore/cosign-installer@v3

      - name: Attest SBOM
        run: |
          cosign attest --predicate sbom.spdx.json \
            --type spdxjson \
            --yes \
            ${{ steps.digest.outputs.image }}

      - name: Verify attestation
        run: |
          cosign verify-attestation \
            --type spdxjson \
            --certificate-identity-regexp="https://github.com/${{ github.repository }}/" \
            --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
            ${{ steps.digest.outputs.image }}

      - name: Upload SBOM as artifact
        uses: actions/upload-artifact@v4
        with:
          name: sbom-spdx
          path: sbom.spdx.json
          retention-days: 90

      - name: Upload vulnerability report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: vulnerability-report
          path: vulnerabilities.json
          retention-days: 90

يستخدم سير العمل هذا التوقيع بدون مفاتيح عبر هوية OIDC الخاصة بـ GitHub Actions. لا يتم تخزين مفاتيح خاصة في الأسرار — يحصل Cosign على شهادة قصيرة العمر من Fulcio CA التابعة لـ Sigstore، ويتم تسجيل حدث التوقيع في سجل الشفافية Rekor.

يفشل خط الأنابيب إذا تم اكتشاف أي ثغرات حرجة. قم بتعديل الحد عن طريق تغيير مرشح الخطورة في خطوة فحص Grype.

التمرين 5: بناء خط الأنابيب في GitLab CI

خط الأنابيب المكافئ في GitLab CI يستخدم نفس الأدوات لكنه يتكيف مع نموذج GitLab القائم على المراحل وسجل الحاويات المدمج فيه.

أنشئ .gitlab-ci.yml:

stages:
  - build
  - sbom
  - scan
  - attest

variables:
  IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  IMAGE_DIGEST: ""

build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $IMAGE .
    - docker push $IMAGE
    - |
      DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' $IMAGE)
      echo "IMAGE_DIGEST=$DIGEST" >> build.env
  artifacts:
    reports:
      dotenv: build.env

generate-sbom:
  stage: sbom
  image: alpine:3.19
  needs: [build]
  before_script:
    - apk add --no-cache curl jq
    - curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
  script:
    - syft $IMAGE_DIGEST -o spdx-json=sbom.spdx.json
    - echo "Package count:" $(cat sbom.spdx.json | jq '.packages | length')
  artifacts:
    paths:
      - sbom.spdx.json
    expire_in: 90 days

scan-vulnerabilities:
  stage: scan
  image: alpine:3.19
  needs: [generate-sbom]
  before_script:
    - apk add --no-cache curl jq
    - curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
  script:
    - grype sbom:./sbom.spdx.json -o json > vulnerabilities.json
    - grype sbom:./sbom.spdx.json -o table
    - |
      CRITICAL_COUNT=$(cat vulnerabilities.json | jq '[.matches[] | select(.vulnerability.severity=="Critical")] | length')
      echo "Critical vulnerabilities found: $CRITICAL_COUNT"
      if [ "$CRITICAL_COUNT" -gt 0 ]; then
        echo "ERROR: Critical vulnerabilities detected. Failing pipeline."
        exit 1
      fi
  artifacts:
    paths:
      - vulnerabilities.json
    expire_in: 90 days
    when: always

attest-sbom:
  stage: attest
  image: alpine:3.19
  needs: [build, generate-sbom, scan-vulnerabilities]
  id_tokens:
    SIGSTORE_ID_TOKEN:
      aud: sigstore
  before_script:
    - apk add --no-cache curl
    - curl -sSfL https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o /usr/local/bin/cosign
    - chmod +x /usr/local/bin/cosign
  script:
    - cosign attest --predicate sbom.spdx.json
        --type spdxjson
        --yes
        $IMAGE_DIGEST
    - cosign verify-attestation
        --type spdxjson
        --certificate-identity-regexp="https://gitlab.com/$CI_PROJECT_PATH//"
        --certificate-oidc-issuer=https://gitlab.com
        $IMAGE_DIGEST

الفروق الرئيسية عن إصدار GitHub Actions:

  • يستخدم GitLab المراحل بدلاً من وظيفة واحدة بخطوات
  • يتم تمرير ملخص الصورة بين المراحل عبر أدوات dotenv
  • يتم كشف رمز OIDC الخاص بـ GitLab عبر id_tokens ومتغير SIGSTORE_ID_TOKEN
  • مُصدر OIDC للتحقق هو https://gitlab.com

التمرين 6: التحقق من SBOM عند النشر

توليد SBOMs وتصديقها هو نصف القصة فقط. الفائدة الأمنية الحقيقية تأتي من فرض التحقق في وقت النشر — رفض أي صورة تفتقر إلى تصديق SBOM صالح.

الخيار أ: التحقق في سكريبت النشر

#!/bin/bash
# deploy.sh — التحقق من تصديق SBOM قبل النشر
set -euo pipefail

IMAGE="$1"

echo "Verifying SBOM attestation for: $IMAGE"

cosign verify-attestation \
  --type spdxjson \
  --certificate-identity-regexp="https://github.com/YOUR_ORG/YOUR_REPO/" \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  "$IMAGE" > /dev/null 2>&1

if [ $? -eq 0 ]; then
  echo "SBOM attestation verified successfully."
  kubectl set image deployment/myapp myapp="$IMAGE"
else
  echo "ERROR: SBOM attestation verification failed. Deployment blocked."
  exit 1
fi

الخيار ب: الفرض باستخدام Kyverno في Kubernetes

Kyverno هو محرك سياسات أصلي لـ Kubernetes يمكنه التحقق من توقيعات الصور والتصديقات في وقت القبول. تقوم السياسة التالية برفض أي pod لا تحتوي صورته على تصديق SBOM صالح.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-sbom-attestation
spec:
  validationFailureAction: Enforce
  webhookTimeoutSeconds: 30
  rules:
    - name: check-sbom-attestation
      match:
        any:
          - resources:
              kinds:
                - Pod
      verifyImages:
        - imageReferences:
            - "ghcr.io/YOUR_ORG/*"
          attestations:
            - type: spdxjson
              attestors:
                - entries:
                    - keyless:
                        subject: "https://github.com/YOUR_ORG/YOUR_REPO/.github/workflows/sbom-pipeline.yml@refs/heads/main"
                        issuer: "https://token.actions.githubusercontent.com"
                        rekor:
                          url: https://rekor.sigstore.dev
              conditions:
                - all:
                    - key: "{{ len(spdxVersion) }}"
                      operator: GreaterThan
                      value: "0"

تطبيق السياسة:

kubectl apply -f require-sbom-attestation.yaml

اختبار القبول: صورة مع تصديق

# يجب أن يتم قبول هذا
kubectl run test-admitted \
  --image=ghcr.io/YOUR_ORG/sbom-lab-app@sha256:abc123... \
  --restart=Never

# المخرج المتوقع:
# pod/test-admitted created

اختبار القبول: صورة بدون تصديق

# يجب أن يتم رفض هذا
kubectl run test-rejected \
  --image=ghcr.io/YOUR_ORG/sbom-lab-app:unattested \
  --restart=Never

# المخرج المتوقع:
# Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request:
# resource Pod/default/test-rejected was blocked due to the following policies:
# require-sbom-attestation:
#   check-sbom-attestation: 'image verification failed for ghcr.io/YOUR_ORG/sbom-lab-app:unattested:
#     attestation spdxjson not found'

هذه هي حلقة الفرض التي تجعل SBOMs ذات معنى تشغيلي — بدون التحقق عند النشر، يبقى توليد SBOM مجرد توثيق فقط.

التمرين 7: مقارنة SBOM بين الإصدارات

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

الخطوة 1: توليد SBOMs لإصدارين

# توليد SBOM للإصدار v1.0.0
syft ghcr.io/YOUR_GITHUB_USERNAME/sbom-lab-app:v1.0.0 -o spdx-json=sbom-v1.spdx.json

# توليد SBOM للإصدار v1.1.0 (بعد تحديث التبعيات)
syft ghcr.io/YOUR_GITHUB_USERNAME/sbom-lab-app:v1.1.0 -o spdx-json=sbom-v2.spdx.json

الخطوة 2: استخراج قوائم الحزم

# استخراج قوائم الحزم المرتبة
cat sbom-v1.spdx.json | jq -r '.packages[] | "\(.name)@\(.versionInfo)"' | sort > packages-v1.txt
cat sbom-v2.spdx.json | jq -r '.packages[] | "\(.name)@\(.versionInfo)"' | sort > packages-v2.txt

الخطوة 3: مقارنة قوائم الحزم

diff --unified packages-v1.txt packages-v2.txt

نموذج المخرجات:

--- packages-v1.txt
+++ packages-v2.txt
@@ -12,7 +12,8 @@
  express@4.18.2
  lodash@4.17.21
- axios@1.6.0
+ axios@1.7.2
+ helmet@7.1.0
  mime-types@2.1.35

الخطوة 4: تحديد الثغرات المكتشفة حديثًا

# فحص الحزم الجديدة/المتغيرة فقط
grype sbom:./sbom-v2.spdx.json -o json > vulns-v2.json
grype sbom:./sbom-v1.spdx.json -o json > vulns-v1.json

# مقارنة أعداد الثغرات
echo "v1.0.0 vulnerabilities: $(cat vulns-v1.json | jq '.matches | length')"
echo "v1.1.0 vulnerabilities: $(cat vulns-v2.json | jq '.matches | length')"

# العثور على الثغرات الجديدة في v1.1.0
comm -13 \
  <(cat vulns-v1.json | jq -r '.matches[].vulnerability.id' | sort -u) \
  <(cat vulns-v2.json | jq -r '.matches[].vulnerability.id' | sort -u)

يمكن أتمتة عملية المقارنة هذه في CI للتعليق على طلبات السحب بتغييرات التبعيات، مما يمنح المراجعين رؤية لتأثير سلسلة التوريد قبل الدمج.

التنظيف

احذف الموارد التي تم إنشاؤها أثناء هذا المختبر:

# حذف الملفات المحلية
rm -f sbom.spdx.json sbom.cyclonedx.json vulnerabilities.json
rm -f sbom-v1.spdx.json sbom-v2.spdx.json packages-v1.txt packages-v2.txt
rm -f vulns-v1.json vulns-v2.json

# حذف صورة الاختبار من GHCR (يتطلب gh CLI)
gh api -X DELETE /user/packages/container/sbom-lab-app/versions/PACKAGE_VERSION_ID

# حذف سياسة Kyverno
kubectl delete clusterpolicy require-sbom-attestation

# حذف pods الاختبار
kubectl delete pod test-admitted test-rejected --ignore-not-found

# حذف المستودع المحلي
cd .. && rm -rf sbom-pipeline-lab

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

  • SBOMs هي أساس أمان سلسلة التوريد — فهي توفر الجرد الذي يمكّن من فحص الثغرات والامتثال للتراخيص والتحقق من المصدر.
  • يولد Syft SBOMs بجميع التنسيقات الرئيسية — SPDX للامتثال التنظيمي، CycloneDX لسير عمل الأمان، وكلاهما مدعوم عبر النظام البيئي.
  • فحص SBOM أسرع من فحص الصورة — استخدم Grype مع بادئة sbom: في خطوط أنابيب CI للحصول على حلقات تغذية راجعة سريعة دون سحب طبقات الصورة.
  • تصديقات Cosign تربط SBOMs بالصور تشفيريًا — تثبت التصديقات الموقعة أن SBOM معينة تم إنتاجها لملخص صورة محدد، ومخزنة في السجل بجانب الصورة.
  • التحقق عند النشر هو ما يجعل SBOMs قابلة للفرض — بدون التحكم في القبول (Kyverno أو OPA Gatekeeper أو سكريبتات النشر)، تبقى SBOMs توثيقًا بلا قوة.
  • مقارنة SBOMs تكشف تغييرات سلسلة التوريد بين الإصدارات — أتمتة مقارنة التبعيات في CI تمنح الفرق رؤية للمخاطر الجديدة قبل وصول الكود إلى الإنتاج.

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

تابع بناء ممارسة أمان سلسلة التوريد الخاصة بك مع هذه الأدلة ذات الصلة: