معمل: توقيع والتحقق من صور الحاويات باستخدام Cosign في GitHub Actions

نظرة عامة

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

في هذا المعمل العملي ستقوم بـ:

  • توقيع صورة حاوية محلياً باستخدام زوج مفاتيح Cosign.
  • إعداد التوقيع بدون مفاتيح في GitHub Actions باستخدام بنية Sigstore التحتية (Fulcio و Rekor).
  • التحقق من التوقيعات محلياً مع فحوصات الشهادات المبنية على الهوية.
  • فرض التحقق من التوقيع عند القبول في Kubernetes باستخدام Kyverno.
  • إرفاق والتحقق من شهادة SBOM باستخدام Cosign و Syft.

بنهاية هذا المعمل سيكون لديك سير عمل GitHub Actions كامل يبني ويدفع ويوقع ويشهد كل صورة — وسياسة Kubernetes ترفض أي شيء غير موقع.

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

قبل البدء، تأكد من توفر ما يلي:

  • حساب GitHub مع صلاحية إنشاء مستودعات وتفعيل GitHub Actions.
  • حساب سجل حاويات — يستخدم هذا المعمل GitHub Container Registry (GHCR)، لكن Docker Hub يعمل أيضاً.
  • Docker مثبت وقيد التشغيل محلياً.
  • Cosign CLI مثبت محلياً:
# macOS (Homebrew)
brew install cosign

# Or install from source with Go
go install github.com/sigstore/cosign/v2/cmd/cosign@latest

# Verify installation
cosign version
  • kubectl و Helm مثبتان (لتمرين Kyverno).
  • Syft مثبت (لتمرين SBOM):
brew install syft

ستحتاج أيضاً إلى تطبيق بسيط لوضعه في حاوية. إليك تطبيق Go بسيط وملف Dockerfile الخاص به الذي سنستخدمه طوال المعمل.

main.go

package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello from a signed container!")
	})
	http.ListenAndServe(":8080", nil)
}

Dockerfile

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY main.go .
RUN go build -o server main.go

FROM alpine:3.19
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]

إعداد البيئة

ابدأ بإنشاء مستودع اختبار ودفع كود التطبيق.

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

# Create a new directory and initialize a Git repo
mkdir cosign-lab && cd cosign-lab
git init

# Create the Go application and Dockerfile from the prerequisites above
# Then push to GitHub
git add .
git commit -m "Initial commit: simple Go app"
gh repo create cosign-lab --public --source=. --push

الخطوة 2 — إنشاء سير العمل بدون توقيع

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

أنشئ .github/workflows/build.yml:

name: Build and Push (Unsigned)

on:
  push:
    tags:
      - 'v*'

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

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

قم بعمل commit ودفع سير العمل هذا. أنشئ وسم إصدار لتشغيله:

git add .
git commit -m "Add unsigned build workflow"
git push origin main
git tag v0.1.0
git push origin v0.1.0

بمجرد اكتمال سير العمل، ستكون صورتك في GHCR — لكنها لا تحمل أي توقيع تشفيري. يمكن لأي شخص لديه صلاحية الكتابة على السجل استبدالها، ولن يلاحظ أي شيء في المراحل اللاحقة.

التمرين 1: التوقيع المحلي بزوج مفاتيح

قبل الانتقال إلى التوقيع بدون مفاتيح في CI، من المفيد فهم الأساسيات من خلال توقيع صورة محلياً بزوج مفاتيح صريح.

الخطوة 1 — إنشاء زوج مفاتيح Cosign

cosign generate-key-pair

ينشئ هذا ملفين في دليلك الحالي:

  • cosign.key — المفتاح الخاص (مشفر بعبارة مرور تختارها).
  • cosign.pub — المفتاح العام الذي توزعه على المتحققين.

الخطوة 2 — بناء ودفع وتوقيع الصورة

# Build the image
docker build -t ghcr.io/<your-username>/cosign-lab:v1 .

# Push to GHCR
docker push ghcr.io/<your-username>/cosign-lab:v1

# Sign the image with your private key
cosign sign --key cosign.key ghcr.io/<your-username>/cosign-lab:v1

استبدل <your-username> باسم مستخدم GitHub الخاص بك. سيطلب Cosign عبارة المرور التي حددتها أثناء إنشاء المفتاح.

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

cosign verify --key cosign.pub ghcr.io/<your-username>/cosign-lab:v1

يجب أن ترى مخرجات مشابهة لـ:

Verification for ghcr.io/<your-username>/cosign-lab:v1 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key

[{"critical":{"identity":{"docker-reference":"ghcr.io/<your-username>/cosign-lab"},"image":{"docker-manifest-digest":"sha256:abc123..."},"type":"cosign container image signature"},"optional":null}]

أين يتم تخزين التوقيع؟

يخزن Cosign التوقيعات كقطع OCI في نفس السجل، بجانب الصورة. لصورة موسومة بـ sha256:abc123، يدفع Cosign التوقيع إلى وسم مشتق من ذلك الملخص — sha256-abc123.sig. هذا يعني:

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

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

التمرين 2: التوقيع بدون مفاتيح في GitHub Actions

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

كيف يعمل التوقيع بدون مفاتيح

  1. رمز OIDC — يصدر GitHub Actions رمز هوية OIDC يثبت هوية سير العمل (المستودع، ملف سير العمل، المرجع، والمزيد).
  2. شهادة Fulcio — يرسل Cosign رمز OIDC هذا إلى Fulcio، الذي يصدر شهادة توقيع X.509 قصيرة العمر مرتبطة بهوية سير العمل.
  3. التوقيع — يوقع Cosign ملخص الصورة بالمفتاح الخاص المؤقت المقابل لشهادة Fulcio.
  4. سجل شفافية Rekor — يتم تسجيل التوقيع والشهادة في Rekor حتى يتمكن أي شخص من مراجعة متى ومن قام بتوقيع الصورة.
  5. التخلص من المفتاح — يتم التخلص من المفتاح الخاص المؤقت فوراً. يستخدم التحقق الشهادة وإدخال Rekor، وليس مفتاحاً عاماً طويل العمر.

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

أنشئ .github/workflows/sign.yml:

name: Build, Push, and Sign

on:
  push:
    tags:
      - 'v*'

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

jobs:
  build-and-sign:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write   # Required for keyless signing via OIDC

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

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

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

      - name: Build and push
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

      - name: Sign the image
        run: |
          cosign sign --yes \
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}

التفاصيل الرئيسية في سير العمل هذا

  • id-token: write — هذا الإذن يسمح للمشغل بطلب رمز OIDC من GitHub، الذي يستخدمه Fulcio لإصدار شهادة التوقيع.
  • packages: write — مطلوب لدفع الصورة وتوقيعها إلى GHCR.
  • cosign sign --yes — علم --yes يؤكد الوضع غير التفاعلي (بدون طلب موافقة التوقيع بدون مفاتيح). عدم وجود علم --key يعني أن Cosign يستخدم تلقائياً التوقيع بدون مفاتيح.
  • نوقع بالملخص (@sha256:...) بدلاً من الوسم لضمان توقيع الصورة نفسها التي بنيناها للتو.

الخطوة 2 — الدفع وتشغيل سير العمل

git add .github/workflows/sign.yml
git commit -m "Add keyless signing workflow"
git push origin main
git tag v1.0.0
git push origin v1.0.0

الخطوة 3 — مراجعة سجلات Actions

في خطوة “Sign the image” سترى مخرجات مشابهة لـ:

Generating ephemeral keys...
Retrieving signed certificate...

        The sigstore community wants to hear from you! Connect with us at
        https://links.sigstore.dev/slack-invite

Successfully verified SCT...
tlog entry created with index: 45678901
Pushing signature to: ghcr.io/<your-username>/cosign-lab:sha256-a1b2c3d4.sig

الصورة الآن موقعة بشهادة تربطها تشفيرياً بهوية سير عمل GitHub Actions الخاص بك. التوقيع والشهادة مسجلان بشكل دائم في سجل شفافية Rekor.

التمرين 3: التحقق من التوقيعات محلياً

يتطلب التحقق من صورة موقعة بدون مفاتيح معلومتين: هوية الشهادة (من وقع) و مُصدر OIDC (من ضمن تلك الهوية).

الخطوة 1 — التحقق من الصورة الموقعة

cosign verify \
  --certificate-identity "https://github.com/<your-username>/cosign-lab/.github/workflows/sign.yml@refs/tags/v1.0.0" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/<your-username>/cosign-lab:v1.0.0

المخرجات الناجحة:

Verification for ghcr.io/<your-username>/cosign-lab:v1.0.0 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The code-signing certificate was verified using trusted certificate authority
  - The signatures were verified against the specified public key
  - The signature was verified against a valid Fulcio certificate

[{"critical":{"identity":{"docker-reference":"ghcr.io/<your-username>/cosign-lab"},"image":{"docker-manifest-digest":"sha256:a1b2c3d4..."},"type":"cosign container image signature"},"optional":{...}}]

الخطوة 2 — التحقق بهوية غير صحيحة (توقع الفشل)

cosign verify \
  --certificate-identity "https://github.com/attacker/malicious-repo/.github/workflows/build.yml@refs/tags/v1.0.0" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/<your-username>/cosign-lab:v1.0.0

المخرجات:

Error: no matching signatures:
none of the expected identities matched what was in the certificate

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

الخطوة 3 — التحقق من صورة غير موقعة (توقع الفشل)

cosign verify \
  --certificate-identity "https://github.com/<your-username>/cosign-lab/.github/workflows/sign.yml@refs/tags/v0.1.0" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/<your-username>/cosign-lab:v0.1.0

المخرجات:

Error: no matching signatures
no signatures found for image

صورة v0.1.0 تم بناؤها بسير العمل غير الموقع من قسم إعداد البيئة، لذلك لا يوجد توقيع.

فهم حقول الشهادة

عند التحقق من توقيع بدون مفاتيح، يفحص Cosign عدة حقول مضمنة في شهادة Fulcio:

  • المُصدر (certificate-oidc-issuer) — مزود OIDC الذي صادق على الموقِّع. بالنسبة لـ GitHub Actions هذا دائماً https://token.actions.githubusercontent.com.
  • الموضوع / الهوية (certificate-identity) — مرجع سير العمل الكامل بما في ذلك المستودع ومسار ملف سير العمل ومرجع Git. هذا يربط التوقيع بسير عمل محدد عند commit أو وسم محدد.
  • امتدادات GitHub Workflow — تحتوي الشهادة أيضاً على امتدادات OID مخصصة للمستودع و SHA لسير العمل وحدث التشغيل وبيئة المشغل. تسمح هذه بسياسات تحقق دقيقة.

يمكنك أيضاً استخدام مطابقة regex لسياسات أكثر مرونة:

cosign verify \
  --certificate-identity-regexp "https://github.com/<your-username>/cosign-lab/.*" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/<your-username>/cosign-lab:v1.0.0

هذا مفيد عندما تريد قبول التوقيعات من أي سير عمل في مستودع، أو من أي وسم.

التمرين 4: التحقق في Kubernetes باستخدام Kyverno

التحقق المحلي مفيد لتصحيح الأخطاء، لكن مجموعات الإنتاج تحتاج إلى فرض آلي. Kyverno هو وحدة تحكم قبول في Kubernetes يمكنها التحقق من توقيعات Cosign على كل طلب قبول pod.

الخطوة 1 — تثبيت Kyverno

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno -n kyverno --create-namespace

انتظر حتى تصبح pods الخاصة بـ Kyverno جاهزة:

kubectl wait --for=condition=ready pod -l app.kubernetes.io/instance=kyverno -n kyverno --timeout=120s

الخطوة 2 — إنشاء سياسة التحقق من الصور

احفظ ما يلي باسم require-signed-images.yml:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-cosign-signature
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: verify-cosign-signature
      match:
        any:
          - resources:
              kinds:
                - Pod
      verifyImages:
        - imageReferences:
            - "ghcr.io/<your-username>/cosign-lab:*"
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/<your-username>/cosign-lab/.github/workflows/sign.yml@refs/tags/*"
                    issuer: "https://token.actions.githubusercontent.com"
                    rekor:
                      url: "https://rekor.sigstore.dev"

طبق السياسة:

kubectl apply -f require-signed-images.yml

الخطوة 3 — اختبار بصورة موقعة (يجب أن ينجح)

kubectl run signed-app \
  --image=ghcr.io/<your-username>/cosign-lab:v1.0.0 \
  --restart=Never

المخرجات المتوقعة:

pod/signed-app created

الخطوة 4 — اختبار بصورة غير موقعة (يجب أن يفشل)

kubectl run unsigned-app \
  --image=ghcr.io/<your-username>/cosign-lab:v0.1.0 \
  --restart=Never

المخرجات المتوقعة:

Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request:
resource Pod/default/unsigned-app was blocked due to the following policies:

require-cosign-signature:
  verify-cosign-signature: |
    image verification failed for ghcr.io/<your-username>/cosign-lab:v0.1.0:
    no matching signatures found

هذا هو بالضبط حلقة الفرض التي تريدها: فقط الصور الموقعة من سير عمل GitHub Actions الموثوق الخاص بك يُسمح لها بالدخول إلى المجموعة.

التمرين 5: إرفاق SBOM

التوقيع يثبت من بنى الصورة. شهادة SBOM تثبت ما بداخلها. الجمع بينهما يمنحك سلسلة ثقة كاملة: الهوية والنزاهة وشفافية المحتوى.

الخطوة 1 — إنشاء SBOM باستخدام Syft

syft ghcr.io/<your-username>/cosign-lab:v1.0.0 -o spdx-json > sbom.spdx.json

يقوم هذا بمسح طبقات الصورة وإنتاج مستند JSON بتنسيق SPDX يسرد كل حزمة ومكتبة وتبعية داخل الصورة.

الخطوة 2 — إرفاق SBOM كشهادة

cosign attest \
  --predicate sbom.spdx.json \
  --type spdxjson \
  --yes \
  ghcr.io/<your-username>/cosign-lab:v1.0.0

مثل التوقيع بدون مفاتيح، يستخدم هذا الهوية المبنية على OIDC عند التشغيل في GitHub Actions أو يطلب المصادقة التفاعلية عند التشغيل محلياً. يتم تخزين الشهادة كقطعة OCI بجانب الصورة.

الخطوة 3 — التحقق من الشهادة

cosign verify-attestation \
  --type spdxjson \
  --certificate-identity "https://github.com/<your-username>/cosign-lab/.github/workflows/sign.yml@refs/tags/v1.0.0" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/<your-username>/cosign-lab:v1.0.0

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

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

إليك سير العمل النهائي الذي يجمع كل شيء: البناء والدفع والتوقيع وإنشاء SBOM وتوثيقه. احفظ هذا باسم .github/workflows/sign-and-attest.yml:

name: Build, Sign, and Attest

on:
  push:
    tags:
      - 'v*'

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

jobs:
  build-sign-attest:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

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

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

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

      - name: Build and push
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

      - name: Sign the image
        run: |
          cosign sign --yes \
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}

      - name: Generate SBOM
        run: |
          syft ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }} \
            -o spdx-json > sbom.spdx.json

      - name: Attest SBOM
        run: |
          cosign attest --yes \
            --predicate sbom.spdx.json \
            --type spdxjson \
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}

      - name: Verify signature
        run: |
          cosign verify \
            --certificate-identity-regexp "https://github.com/${{ github.repository }}/.*" \
            --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}

      - name: Verify SBOM attestation
        run: |
          cosign verify-attestation \
            --type spdxjson \
            --certificate-identity-regexp "https://github.com/${{ github.repository }}/.*" \
            --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}

يمنحك سير العمل هذا سلسلة ثقة كاملة لكل إصدار موسوم: الصورة موقعة، ومحتوياتها موثقة في SBOM، و SBOM مشهود عليه تشفيرياً — كل ذلك بدون إدارة مفتاح واحد طويل العمر.

التنظيف

عند الانتهاء من المعمل، نظف الموارد التي أنشأتها.

حذف صور الاختبار من GHCR

انتقل إلى https://github.com/<your-username>?tab=packages واحذف حزمة cosign-lab، أو استخدم GitHub CLI:

# List package versions
gh api user/packages/container/cosign-lab/versions | jq '.[].id'

# Delete each version
gh api --method DELETE user/packages/container/cosign-lab/versions/<version-id>

إزالة Kyverno

kubectl delete clusterpolicy require-cosign-signature
helm uninstall kyverno -n kyverno
kubectl delete namespace kyverno

حذف مستودع الاختبار

gh repo delete <your-username>/cosign-lab --yes

إزالة الملفات المحلية

cd .. && rm -rf cosign-lab
rm -f cosign.key cosign.pub

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

  • التوقيع بدون مفاتيح يزيل إدارة المفاتيح. باستخدام رموز هوية OIDC من GitHub Actions وشهادات Fulcio قصيرة العمر، تتجنب العبء التشغيلي لإنشاء وتخزين وتدوير وتوزيع مفاتيح التوقيع.
  • التوقيعات مرتبطة بالهوية، وليس بالمفتاح. يتحقق التحقق من الذي وقع الصورة (أي سير عمل، في أي مستودع، عند أي مرجع) بدلاً من أي مفتاح تم استخدامه. هذا يجعل السياسات أكثر سهولة وقابلية للمراجعة.
  • سجل شفافية Rekor يوفر مسار مراجعة مقاوم للتلاعب. كل توقيع مسجل علنياً، حتى تتمكن من إثبات متى تم توقيع الصورة واكتشاف أي محاولة لتأخير التاريخ أو إزالة التوقيعات.
  • وحدات تحكم القبول تفرض سياسات التوقيع عند وقت النشر. Kyverno (أو بدائل مثل Connaisseur أو Sigstore Policy Controller) يضمن أن الصور غير الموقعة أو الموقعة بشكل غير صحيح لا تعمل أبداً في مجموعتك.
  • شهادات SBOM توسع سلسلة الثقة. التوقيع يثبت من بنى الصورة؛ إرفاق SBOM موقع يثبت ما بداخلها. معاً، يوفران مصدراً كاملاً من المصدر إلى وقت التشغيل.
  • وقّع بالملخص، وليس بالوسم. الوسوم قابلة للتغيير — يمكن لشخص ما نقل وسم إلى صورة مختلفة. الملخصات هي عناوين محتوى ثابتة، لذا التوقيع بالملخص يضمن أنك وقعت بالضبط الصورة التي بنيتها.

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

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