Synchroniser les artefacts OCI à partir d'Artifact Registry

Cette page vous explique comment créer et publier votre image dans un dépôt Artifact Registry avec crane et oras.

Vous pouvez configurer Config Sync pour qu'il se synchronise à partir d'images OCI à l'aide d'Artifact Registry. Pour utiliser cette fonctionnalité, vous devez activer les API RootSync et RepoSync.

À propos d'Artifact Registry

Artifact Registry est un service entièrement géré compatible avec les images de conteneurs et les artefacts non issus de conteneurs. Nous vous recommandons d'utiliser Artifact Registry pour stocker et gérer vos images de conteneurs sur Cloud de Confiance by S3NS. Plusieurs outils permettent de transférer des artefacts vers Artifact Registry. Par exemple, vous pouvez transférer une image Docker ou utiliser la bibliothèque go-containerregistry pour travailler avec des registres de conteneurs. Choisissez l'outil qui vous convient le mieux.

Avant de commencer

  1. Installez la Google Cloud CLI.

  2. Configurez la gcloud CLI afin d'utiliser votre identité fédérée.

    Pour en savoir plus, consultez Se connecter à la gcloud CLI avec votre identité fédérée.

  3. Pour initialiser la gcloud CLI, exécutez la commande suivante :

    gcloud init
  4. Créez ou sélectionnez un projet Cloud de Confiance .

    Rôles requis pour sélectionner ou créer un projet

    • Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
    • Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (roles/resourcemanager.projectCreator), qui contient l'autorisation resourcemanager.projects.create. Découvrez comment attribuer des rôles.
    • Créez un projet Cloud de Confiance  :

      gcloud projects create PROJECT_ID

      Remplacez PROJECT_ID par le nom du projet Cloud de Confiance que vous créez.

    • Sélectionnez le projet Cloud de Confiance que vous avez créé :

      gcloud config set project PROJECT_ID

      Remplacez PROJECT_ID par le nom de votre projet Cloud de Confiance .

  5. Vérifiez que la facturation est activée pour votre projet Cloud de Confiance .

  6. Activez les API GKE, Config Sync et Artifact Registry :

    Rôles requis pour activer les API

    Pour activer les API, vous avez besoin du rôle IAM Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin), qui contient l'autorisation serviceusage.services.enable. Découvrez comment attribuer des rôles.

    gcloud services enable container.googleapis.com  anthosconfigmanagement.googleapis.com  artifactregistry.googleapis.com
  7. Créez un cluster répondant aux exigences de Config Sync et utilisant la dernière version de Config Sync, ou assurez-vous d'y avoir accès.
  8. Installez la CLI nomos ou mettez-la à niveau vers la dernière version.
  9. (Facultatif) Si vous souhaitez utiliser Cosign pour valider les signatures d'images OCI, installez les éléments suivants :
    • Cosign pour signer les images OCI.
    • OpenSSL pour générer des identifiants pour le serveur de webhook.
    • Docker pour créer et transmettre l'image du serveur Admission Webhook.

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Cloud de Confiance by S3NS :

Créer un dépôt Artifact Registry

Dans cette section, vous allez créer un dépôt Artifact Registry. Pour en savoir plus sur la création de dépôts Artifact Registry, consultez la section Créer des dépôts.

  1. Créer un dépôt Artifact Registry :

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

Remplacez les éléments suivants :

  • PROJECT_ID : ID de projet de l'organisation.
  • AR_REPO_NAME : ID du dépôt.
  • AR_REGION : emplacement régional ou multirégional du dépôt.

Variables utilisées dans les sections suivantes :

  • FLEET_HOST_PROJECT_ID : si vous utilisez la fédération d'identité de charge de travail GKE pour GKE, cette valeur est identique à PROJECT_ID. Si vous utilisez la Workload Identity Federation pour GKE pour votre parc, il s'agit de l'ID du projet dans lequel votre cluster est enregistré.
  • GSA_NAME : nom du compte de service Google personnalisé que vous souhaitez utiliser pour vous connecter à Artifact Registry.
  • KSA_NAME : compte de service Kubernetes pour le rapprochement.
    • Pour les dépôts racine, si le nom RootSync est root-sync, ajoutez root-reconciler. Sinon, ajoutez root-reconciler-ROOT_SYNC_NAME.
    • Pour les dépôts d'espaces de noms, si le nom RepoSync est repo-sync, ajoutez ns-reconciler-NAMESPACE. Sinon, ajoutez ns-reconciler-NAMESPACE-REPO_SYNC_NAME-REPO_SYNC_NAME_LENGTH, où REPO_SYNC_NAME_LENGTH correspond au nombre de caractères dans REPO_SYNC_NAME.

Accorder l'autorisation de lecture

Pour vous authentifier auprès d'Artifact Registry à l'aide d'un compte de service Kubernetes, procédez comme suit :

Attribuez le rôle IAM de lecteur Artifact Registry (roles/artifactregistry.reader) au compte de service Kubernetes associé au pool Workload Identity Federation for 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

Transférer une image vers le dépôt Artifact Registry

Dans cette section, vous allez créer une image OCI et la transférer dans Artifact Registry.

  1. Créez un fichier manifeste Namespace :

    cat <<EOF> test-namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: test
    EOF
    
  2. Connectez-vous à Artifact Registry :

    gcloud auth configure-docker AR_REGION-docker.pkg.dev
    
  3. Empaquetez et transférez l'image vers Artifact Registry :

    crane

    Les commandes de cette section utilisent crane pour interagir avec les images et registres distants.

    1. Empaquetez le fichier :

      tar -cf test-namespace.tar test-namespace.yaml
      
    2. Installez l'outil crane.

    3. Transférez l'image vers Artifact Registry :

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

    oras

    Les commandes de cette section utilisent oras pour interagir avec les images et registres distants.

    1. Empaquetez le fichier :

      tar -czf test-namespace.tar.gz test-namespace.yaml
      
    2. Installez l'outil oras.

    3. Transférez l'image vers Artifact Registry :

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

Configurer Config Sync pour la synchronisation à partir de votre image

Dans cette section, vous allez créer un objet RootSync et configurer Config Sync pour la synchronisation à partir de l'image OCI.

  1. Créez un objet RootSync avec un nom unique :

    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
    

    Remplacez ROOT_SYNC_NAME par le nom de votre objet RootSync. Le nom doit être unique dans le cluster et ne pas dépasser 26 caractères. Pour obtenir la liste complète des options de configuration des objets RootSync, consultez les champs RootSync et RepoSync.

  2. Appliquez l'objet RootSync :

    kubectl apply -f ROOT_SYNC_NAME.yaml
    
  3. Vérifiez que Config Sync est synchronisé à partir de l'image :

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

    Un résultat semblable aux lignes suivantes doit s'afficher :

    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
    

    Vous venez de synchroniser une image avec votre cluster.

(Facultatif) Valider les signatures de la source OCI

Vous pouvez vérifier l'authenticité des images sources OCI avant que les configurations ne soient appliquées à vos clusters. Cette méthode utilise un objet ValidatingWebhookConfiguration et un serveur de webhook de validation pour intercepter les demandes de mise à jour des objets RootSync et RepoSync. Config Sync met à jour l'annotation configsync.gke.io/image-to-sync des objets RootSync et RepoSync après avoir récupéré un nouveau résumé d'image. Le serveur de webhook de validation compare les valeurs entre l'ancienne et la nouvelle annotation, et exécute la validation avec un outil de validation tel que Cosign lorsqu'une modification est détectée.

Configurer un serveur de validation de signature

Pour garantir l'authenticité de vos sources OCI, vous avez besoin d'un serveur HTTP pour valider les signatures. Vous pouvez utiliser les exemples du dépôt d'exemples Config Sync ou votre propre image Docker.

  1. Si vous souhaitez utiliser l'exemple fourni, procédez comme suit :

    1. Clonez l'exemple de dépôt :

      git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples/
      
    2. Accédez au répertoire contenant les exemples de serveur de validation de signature :

      cd anthos-config-management-samples/tree/main/pre-sync/oci-image-verification
      
  2. Pour créer une image Docker pour le serveur de validation de signature et la transférer vers un registre d'images, exécutez la commande suivante :

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

    Remplacez SIGNATURE_VERIFICATION_SERVER_IMAGE_URL par l'URL de l'image de votre serveur de validation de signature.

S'authentifier auprès des services

Pour configurer votre serveur de validation de signature, vous devez vous authentifier auprès d'Artifact Registry, du client Cosign et du serveur de webhook.

  1. Créez un espace de noms :

    kubectl create ns signature-verification
    
  2. Pour vous authentifier auprès d'Artifact Registry avec un compte de service Kubernetes, procédez comme suit :

    1. Créez un ServiceAccount Kubernetes dans l'espace de noms que vous avez créé :

      kubectl create sa signature-verification-sa -n signature-verification
      
    2. Ajoutez la liaison de stratégie IAM pour le rôle Lecteur Artifact Registry (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
      

      Remplacez les éléments suivants :

      • REPOSITORY_NAME : nom de votre dépôt Artifact Registry dans lequel vous stockez vos images OCI.
      • REPOSITORY_LOCATION : emplacement de votre dépôt Artifact Registry.
  3. Pour vous authentifier auprès du client Cosign, procédez comme suit :

    1. Générez une paire de clés Cosign. Cette commande génère une clé publique et une clé privée :

      cosign generate-key-pair
      
    2. Stockez la clé publique dans un secret Kubernetes dans l'espace de noms que vous avez créé :

      kubectl create secret generic cosign-key --from-file=cosign.pub -n signature-verification
      
  4. Pour authentifier le serveur de validation des signatures, procédez comme suit :

    1. Pour chiffrer la communication au sein du serveur de validation des signatures, générez un certificat TLS et une clé privée avec 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. Stockez les identifiants que vous avez générés dans un secret Kubernetes :

      kubectl create secret tls webhook-tls --cert=tls.crt --key=tls.key -n signature-verification
      
    3. Obtenez le contenu encodé en base64 de tls.cert. Cette étape est requise pour la configuration du webhook de validation que vous allez créer dans la section suivante :

      cat tls.crt | base64 -w 0.
      

Déployer le webhook d'admission

Vous pouvez utiliser les exemples suivants pour créer un déploiement pour le serveur de validation de signature et une configuration de webhook de validation.

  1. Créez un déploiement pour le serveur de validation de signature en enregistrant le fichier suivant :

    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

    Remplacez SIGNATURE_VERIFICATION_SERVER_IMAGE_URL par l'URL complète de l'image du serveur de validation de la signature.

  2. Appliquez le déploiement au cluster :

    kubectl apply -f signature-verification-deployment.yaml -n signature-verification
    
  3. Créez une configuration de webhook de validation en enregistrant le fichier suivant :

    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

    Remplacez CA_BUNDLE par le contenu encodé en base64 de tls.cert.

  4. Appliquez la configuration du webhook de validation au cluster :

    kubectl apply -f signature-verification-validatingwebhookconfiguration.yaml
    

Rechercher les erreurs de validation des images dans les journaux

Une fois que vous avez configuré votre serveur de validation d'images, toute tentative de synchronisation à partir d'images OCI non signées devrait échouer.

Pour rechercher les erreurs de validation de la signature, consultez les journaux du serveur de validation de la signature en exécutant les commandes suivantes :

  1. Consultez les journaux kubectl :

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

    Les erreurs de kubectl liées à la validation de la signature ressemblent à ce qui suit :

    main.go:69: error during command execution: no signatures found
    
  2. Vérifiez les journaux Config Sync :

    nomos status
    

    Les erreurs de Config Sync liées à la validation de la signature ressemblent à ce qui suit :

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

Si aucune erreur ne s'affiche, vous pouvez confirmer que l'image signée est l'objet synchronisé en inspectant votre configuration RootSync ou RepoSync :

RootSync

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

Remplacez ROOTSYNC_NAME par le nom de votre RootSync.

RepoSync

 kubectl get reposync REPOSYNC_NAME -n REPOSYNC_NAMESPACE -oyaml

Remplacez les éléments suivants :

  • REPOSYNC_NAME : nom de votre RepoSync.
  • REPOSYNC_NAMESPACE : nom de l'espace de noms associé à votre RepoSync.

L'annotation configsync.gke.io/image-to-sync doit être ajoutée à votre objet RootSync ou RepoSync. L'annotation contient l'URL de l'image OCI source et le dernier condensé récupéré par Config Sync.

Étapes suivantes