סנכרון פריטי מידע שנוצרו בתהליך פיתוח (Artifact) של OCI מ-Artifact Registry

בדף הזה מוסבר איך ליצור ולפרסם את התמונה במאגר ב-Artifact Registry באמצעות crane ו-oras.

אתם יכולים להגדיר את Config Sync כך שיסנכרן תמונות מ-OCI באמצעות Artifact Registry. כדי להשתמש בתכונה הזו, צריך להפעיל את ממשקי ה-API של RootSync ו-RepoSync.

מידע על Artifact Registry

‫Artifact Registry הוא שירות מנוהל באופן מלא עם תמיכה בקובצי אימג' של קונטיינרים ובפריטי מידע שאינם קונטיינרים. אנחנו ממליצים להשתמש ב-Artifact Registry לאחסון ולניהול של קובצי אימג' של קונטיינר ב- Cloud de Confiance by S3NS. יש הרבה כלים שאפשר להשתמש בהם כדי להעלות פריטי מידע שנוצרים בתהליך פיתוח (Artifact) אל Artifact Registry. לדוגמה, אתם יכולים להעביר בדחיפה קובץ אימג' של Docker או להשתמש בספריית go-containerregistry כדי לעבוד עם מאגרי קונטיינרים. בוחרים את הכלי שהכי מתאים לכם.

לפני שמתחילים

  1. התקינו את ה-CLI של Google Cloud.

  2. הגדירו שה-CLI של gcloud ישתמש בזהות המאוחדת שלכם.

    איך נכנסים ל-CLI של gcloud באמצעות הזהות המאוחדת?

  3. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  4. יוצרים או בוחרים Cloud de Confiance פרויקט.

    תפקידים שנדרשים כדי לבחור או ליצור פרויקט

    • Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
    • יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (יצירת פרויקטים) (roles/resourcemanager.projectCreator), שכולל את ההרשאה resourcemanager.projects.create. איך מקצים תפקידים
    • יוצרים Cloud de Confiance פרויקט:

      gcloud projects create PROJECT_ID

      מחליפים את PROJECT_ID בשם של פרויקט Cloud de Confiance שיוצרים.

    • בוחרים את הפרויקט שיצרתם: Cloud de Confiance

      gcloud config set project PROJECT_ID

      מחליפים את PROJECT_ID בשם הפרויקט ב- Cloud de Confiance .

  5. מוודאים שהחיוב מופעל בפרויקט Cloud de Confiance .

  6. מפעילים את ממשקי ה-API של GKE,‏ סנכרון תצורות ו-Artifact Registry:

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    gcloud services enable container.googleapis.com  anthosconfigmanagement.googleapis.com  artifactregistry.googleapis.com
  7. ליצור אשכול שעומד בדרישות של סנכרון תצורות או לקבל גישה לאשכול כזה, ולוודא שהוא פועל בגרסה העדכנית של סנכרון תצורות.
  8. מתקינים את nomos CLI או משדרגים אותו לגרסה העדכנית.
  9. (אופציונלי) אם רוצים להשתמש ב-Cosign כדי לאמת חתימות של תמונות OCI, צריך להתקין את הרכיבים הבאים:
    • Cosign כדי לחתום על תמונות OCI.
    • OpenSSL כדי ליצור אישורים לשרת ה-webhook.
    • Docker כדי ליצור את קובץ האימג' של שרת ה-Webhook של בקרת הכניסה ולהעביר אותו בדחיפה.

עלויות

במסמך הזה משתמשים ברכיבים הבאים של Cloud de Confiance by S3NS, והשימוש בהם כרוך בתשלום:

יצירת מאגר Artifact Registry

בקטע הזה, יוצרים מאגר ב-Artifact Registry. מידע נוסף על יצירת מאגרי Artifact Registry זמין במאמר יצירת מאגרים.

  1. יוצרים מאגר Artifact Registry:

    gcloud artifacts repositories create AR_REPO_NAME \
       --repository-format=docker \
       --location=AR_REGION \
       --description="Config Sync repo" \
       --project=PROJECT_ID
    

מחליפים את מה שכתוב בשדות הבאים:

  • PROJECT_ID: מזהה הפרויקט של הארגון.
  • AR_REPO_NAME: מזהה המאגר.
  • AR_REGION: המיקום האזורי או הרב-אזורי של המאגר.

משתנים שנעשה בהם שימוש בקטעים הבאים:

  • FLEET_HOST_PROJECT_ID: אם אתם משתמשים באיחוד זהויות של עומסי עבודה ל-GKE, הערך הזה זהה לערך של PROJECT_ID. אם אתם משתמשים באיחוד זהויות של עומסי עבודה ל-GKE, זהו מזהה הפרויקט של ה-Fleet שהאשכול רשום בו.
  • GSA_NAME: השם של חשבון השירות המותאם אישית של Google שרוצים להשתמש בו כדי להתחבר ל-Artifact Registry.
  • KSA_NAME: חשבון השירות של Kubernetes עבור ה-reconciler.
    • אם שם המאגר RootSync הוא root-sync, מוסיפים root-reconciler למאגרי הבסיס. אחרת, מוסיפים את root-reconciler-ROOT_SYNC_NAME.
    • אם שם מאגר מרחב השמות הוא RepoSync, צריך להוסיף ns-reconciler-NAMESPACE. repo-sync אחרת, מוסיפים ns-reconciler-NAMESPACE-REPO_SYNC_NAME-REPO_SYNC_NAME_LENGTH כאשר REPO_SYNC_NAME_LENGTH הוא מספר התווים ב-REPO_SYNC_NAME.

מתן הרשאת קריאה

כדי לבצע אימות ל-Artifact Registry באמצעות חשבון שירות של Kubernetes, פועלים לפי השלבים הבאים:

מקצים את תפקיד הקורא ב-Artifact Registry ‏ (roles/artifactregistry.reader) ב-IAM לחשבון השירות ב-Kubernetes שיש לו מאגר של איחוד זהויות של עומסי עבודה ל-GKE:

gcloud artifacts repositories add-iam-policy-binding AR_REPO_NAME \
   --location=AR_REGION \
   --member="serviceAccount:FLEET_HOST_PROJECT_ID.s3ns.svc.id.goog[config-management-system/KSA_NAME]" \
   --role=roles/artifactregistry.reader \
   --project=PROJECT_ID

העברת תמונה למאגר Artifact Registry

בקטע הזה, יוצרים תמונת OCI ומעבירים אותה בדחיפה ל-Artifact Registry.

  1. יוצרים קובץ מניפסט Namespace:

    cat <<EOF> test-namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: test
    EOF
    
  2. נכנסים ל-Artifact Registry:

    gcloud auth configure-docker AR_REGION-docker.pkg.dev
    
  3. אורזים את התמונה ומעבירים אותה בדחיפה ל-Artifact Registry:

    crane

    הפקודות בקטע הזה משתמשות ב-crane כדי ליצור אינטראקציה עם תמונות ועם רישומים מרוחקים.

    1. אורזים את הקובץ:

      tar -cf test-namespace.tar test-namespace.yaml
      
    2. מתקינים את הכלי crane.

    3. מעבירים את האימג' ל-Artifact Registry:

      crane append -f test-namespace.tar -t AR_REGION-docker.pkg.dev/PROJECT_ID/AR_REPO_NAME/test-namespace:v1
      

    oras

    הפקודות בקטע הזה משתמשות ב-oras כדי ליצור אינטראקציה עם תמונות ועם רישומים מרוחקים.

    1. אורזים את הקובץ:

      tar -czf test-namespace.tar.gz test-namespace.yaml
      
    2. מתקינים את הכלי oras.

    3. מעבירים את האימג' ל-Artifact Registry:

      oras push AR_REGION-docker.pkg.dev/PROJECT_ID/AR_REPO_NAME/test-namespace:v1 test-namespace.tar.gz
      

הגדרת סנכרון תצורות לסנכרון מהתמונה

בקטע הזה, יוצרים אובייקט RootSync ומגדירים את סנכרון תצורות לסנכרון מהתמונה של OCI.

  1. יוצרים אובייקט RootSync עם שם ייחודי:

    cat <<EOF>> ROOT_SYNC_NAME.yaml
    apiVersion: configsync.gke.io/v1beta1
    kind: RootSync
    metadata:
      name: ROOT_SYNC_NAME
      namespace: config-management-system
    spec:
      sourceFormat: unstructured
      sourceType: oci
      oci:
        image: AR_REGION-docker.pkg.dev/PROJECT_ID/AR_REPO_NAME/test-namespace:v1
        dir: .
        auth: k8sserviceaccount
    EOF
    

    מחליפים את ROOT_SYNC_NAME בשם של אובייקט RootSync. השם צריך להיות ייחודי באשכול ולא יכול להיות ארוך מ-26 תווים. רשימת האפשרויות המלאה להגדרת אובייקטים של RootSync מופיעה במאמר שדות של RootSync ושל RepoSync.

  2. החלת אובייקט RootSync:

    kubectl apply -f ROOT_SYNC_NAME.yaml
    
  3. מוודאים ש-Config Sync מסנכרן מהתמונה:

    nomos status --contexts=$(kubectl config current-context)
    

    הפלט אמור להיראות כך:

    Connecting to clusters...
    
    *publish-config-registry
       --------------------
       <root>:root-sync-test   AR_REGION-docker.pkg.dev/PROJECT_ID/AR_REPO_NAME/test-namespace:v1   
       SYNCED                  05e6a6b77de7a62286387cfea833d45290105fe84383224938d7b3ab151a55a1
       Managed resources:
          NAMESPACE   NAME             STATUS    SOURCEHASH
                      namespace/test   Current   05e6a6b
    

    התמונה סונכרנה בהצלחה לאשכול.

(אופציונלי) אימות חתימות של מקור OCI

אתם יכולים לאמת את האותנטיות של תמונות מקוריות של OCI לפני שההגדרות מוחלות על האשכולות שלכם. השיטה הזו משתמשת באובייקט ValidatingWebhookConfiguration ובשרת webhook לאימות כדי ליירט בקשות עדכון לאובייקטים RootSync ו-RepoSync. סנכרון תצורות מעדכן את האנוטציה configsync.gke.io/image-to-sync של אובייקטים מסוג RootSync ו-RepoSync אחרי שהוא מאחזר בהצלחה תקציר של תמונה חדשה. שרת ה-webhook של האימות משווה בין הערכים של ההערה הישנה לבין ההערה החדשה, ומריץ את האימות באמצעות כלי אימות כמו Cosign כשמזוהה שינוי.

הגדרת שרת לאימות חתימות

כדי לוודא שהמקורות של OCI אותנטיים, צריך שרת HTTP לאימות החתימות. אפשר להשתמש בדוגמאות במאגר הדוגמאות של Config Sync או להשתמש בקובץ אימג' משלכם של Docker.

  1. כדי להשתמש בדוגמה שסיפקנו, פועלים לפי השלבים הבאים:

    1. משכפלים את המאגר לדוגמה:

      git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples/
      
    2. עוברים לספרייה שמכילה את הדוגמאות של שרת אימות החתימה:

      cd anthos-config-management-samples/tree/main/pre-sync/oci-image-verification
      
  2. כדי ליצור קובץ אימג' של Docker לשרת אימות החתימות ולהעביר אותו בדחיפה למרשם קובצי אימג', מריצים את הפקודה הבאה:

    docker build -t SIGNATURE_VERIFICATION_SERVER_IMAGE_URL:latest . && docker push SIGNATURE_VERIFICATION_SERVER_IMAGE_URL:latest
    

    מחליפים את SIGNATURE_VERIFICATION_SERVER_IMAGE_URL בכתובת ה-URL של תמונת שרת אימות החתימה.

אימות לשירותים

כדי להגדיר את שרת אימות החתימה, צריך לבצע אימות ב-Artifact Registry, בלקוח Cosign ובשרת ה-webhook.

  1. יוצרים מרחב שמות:

    kubectl create ns signature-verification
    
  2. כדי לבצע אימות ל-Artifact Registry באמצעות חשבון שירות של Kubernetes, מבצעים את השלבים הבאים:

    1. יוצרים Kubernetes ServiceAccount במרחב השמות שיצרתם:

      kubectl create sa signature-verification-sa -n signature-verification
      
    2. מוסיפים את הקישור של מדיניות ה-IAM לתפקיד Artifact Registry Reader ‏(roles/artifactregistry.reader):

      gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
         --location=REPOSITORY_LOCATION \
         --member="serviceAccount:PROJECT_ID.s3ns.svc.id.goog[signature-verification/signature-verification-sa]" \
         --role=roles/artifactregistry.reader \
         --project=PROJECT_ID
      

      מחליפים את מה שכתוב בשדות הבאים:

      • REPOSITORY_NAME: השם של מאגר Artifact Registry שבו מאוחסנים תמונות OCI.
      • REPOSITORY_LOCATION: המיקום של מאגר Artifact Registry.
  3. כדי לבצע אימות ללקוח Cosign, צריך לבצע את השלבים הבאים:

    1. יוצרים זוג מפתחות Cosign. הפקודה הזו יוצרת מפתח ציבורי ומפתח פרטי:

      cosign generate-key-pair
      
    2. מאחסנים את המפתח הציבורי ב-Kubernetes Secret במרחב השמות שיצרתם:

      kubectl create secret generic cosign-key --from-file=cosign.pub -n signature-verification
      
  4. כדי לאמת את שרת אימות החתימה:

    1. כדי להצפין את התקשורת בתוך שרת אימות החתימה, צריך ליצור אישור TLS ומפתח פרטי באמצעות OpenSSL:

      openssl req -nodes -x509 -sha256 -newkey rsa:4096 \
      -keyout tls.key \
      -out tls.crt \
      -days 356 \
      -subj "/CN=signature-verification-service.signature-verification.svc"  \
      -addext "subjectAltName = DNS:signature-verification-service,DNS:signature-verification-service.signature-verification.svc,DNS:signature-verification-service.signature-verification"
      
    2. שומרים את פרטי הכניסה שיצרתם ב-Kubernetes Secret:

      kubectl create secret tls webhook-tls --cert=tls.crt --key=tls.key -n signature-verification
      
    3. מקבלים את התוכן בקידוד base64 של tls.cert. ההגדרה הזו נדרשת עבור אימות ההגדרות של ה-webhook שיוצרים בקטע הבא:

      cat tls.crt | base64 -w 0.
      

פריסת ה-webhook של אישור הבקשות

אפשר להשתמש בדוגמאות הבאות כדי ליצור פריסה לשרת אימות החתימה ולהגדיר webhook לאימות.

  1. יוצרים פריסה לשרת אימות החתימה על ידי שמירת הקובץ הבא:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: signature-verification-server
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: signature-verification-server
      template:
        metadata:
          labels:
            app: signature-verification-server
        spec:
          serviceAccountName: signature-verification-sa
          containers:
          - name: signature-verification-server
            command:
            - /signature-verification-server
            image: SIGNATURE_VERIFICATION_SERVER_IMAGE_URL
            imagePullPolicy: Always
            ports:
            - containerPort: 10250
            volumeMounts:
            - name: tls-certs
              mountPath: "/tls"
            - name: cosign-key
              mountPath: "/cosign-key"
          volumes:
          - name: cosign-key
            secret:
              secretName: cosign-key
          - name: tls-certs
            secret:
              secretName: webhook-tls
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: signature-verification-service
    spec:
      ports:
      - port: 10250
        targetPort: 10250
      selector:
        app: signature-verification-server

    מחליפים את SIGNATURE_VERIFICATION_SERVER_IMAGE_URL בכתובת ה-URL המלאה של תמונת שרת אימות החתימה.

  2. מחילים את הפריסה על האשכול:

    kubectl apply -f signature-verification-deployment.yaml -n signature-verification
    
  3. יוצרים הגדרת webhook לאימות על ידי שמירת הקובץ הבא:

    apiVersion: admissionregistration.k8s.io/v1
    kind: ValidatingWebhookConfiguration
    metadata:
      name: image-verification-webhook
    webhooks:
    - name: imageverification.webhook.com
      clientConfig:
        service:
          name: signature-verification-service
          namespace: signature-verification
          path: "/validate"
          port: 10250
        caBundle: CA_BUNDLE
      rules:
      - apiGroups:
        - configsync.gke.io
        apiVersions:
        - v1beta1
        - v1alpha1
        operations:
        - UPDATE
        resources:
        - 'rootsyncs'
        - 'reposyncs'
        scope: '*'
      admissionReviewVersions: ["v1", "v1beta1"]
      sideEffects: None

    מחליפים את CA_BUNDLE בתוכן בקידוד Base64 מתוך tls.cert.

  4. מחילים את ההגדרות האישיות לתגובה לפעולה מאתר אחר (Webhook) על האשכול:

    kubectl apply -f signature-verification-validatingwebhookconfiguration.yaml
    

בדיקת יומנים לאיתור שגיאות באימות תמונות

אחרי שמגדירים את שרת אימות התמונות, כל ניסיון לסנכרן תמונות OCI לא חתומות ייכשל.

כדי לבדוק אם יש שגיאות באימות החתימה, מציגים את היומנים משרת אימות החתימה על ידי הפעלת הפקודות הבאות:

  1. בדיקה של יומני kubectl:

    kubectl logs deployment  signature-verification-server -n  signature-verification
    

    שגיאות מ-kubectl שקשורות לאימות חתימה נראות כך:

    main.go:69: error during command execution: no signatures found
    
  2. בדיקה של יומני סנכרון תצורות:

    nomos status
    

    שגיאות מ-Config Sync שקשורות לאימות חתימה נראות כך:

    Error:   KNV2002: admission webhook "imageverification.webhook.com" denied the request: Image validation failed: cosign verification failed: exit status 10, output: Error: no signatures found
    

אם לא מופיעות שגיאות, אפשר לוודא שהתמונה החתומה היא האובייקט שמסונכרן על ידי בדיקת ההגדרה של RootSync או RepoSync:

RootSync

 kubectl get rootsync ROOTSYNC_NAME -n config-management-system -oyaml

מחליפים את ROOTSYNC_NAME בשם של RootSync.

RepoSync

 kubectl get reposync REPOSYNC_NAME -n REPOSYNC_NAMESPACE -oyaml

מחליפים את מה שכתוב בשדות הבאים:

  • REPOSYNC_NAME: השם של RepoSync.
  • REPOSYNC_NAMESPACE: השם של מרחב השמות שמשויך ל-RepoSync.

ההערה configsync.gke.io/image-to-sync אמורה להופיע באובייקט RootSync או RepoSync. האנוטציה מכילה את כתובת ה-URL של תמונת ה-OCI של המקור ואת ה-digest העדכני ביותר שאוחזר על ידי סנכרון תצורות.

המאמרים הבאים