Premiers pas avec Google Cloud CLI (GKE)


Ce tutoriel explique comment configurer et tester une stratégie d'autorisation binaire exigeant des attestations. Ce type de stratégie sécurise votre chaîne d'approvisionnement logicielle basée sur des conteneurs en vérifiant qu'une image de conteneur dispose d'une attestation signée avant d'autoriser son déploiement.

Au moment du déploiement, l'autorisation binaire utilise des certificateurs pour valider les signatures numériques figurant dans les attestations. Les attestations sont créées par des signataires, généralement dans le cadre d'un pipeline d'intégration continue (CI).

Dans ce tutoriel, le cluster GKE, les attestations et les certificateurs se trouvent tous dans le même projet. L'intérêt d'une configuration à projet unique est principalement de tester et réaliser des expériences avec le service. Pour obtenir un exemple plus concret, consultez la page Configuration multiprojets.

Les étapes ci-dessous décrivent les tâches que vous effectuez en ligne de commande. Pour effectuer ces étapes avec la console Google Cloud, consultez la page Premiers pas avec la console Google Cloud.

Objectifs

Dans ce tutoriel, vous allez apprendre à effectuer les opérations suivantes :

  • Créer un cluster Google Kubernetes Engine (GKE) avec l'autorisation binaire activée
  • Créer un certificateur utilisé par l'outil d'application de l'autorisation binaire pour valider la signature d'une attestation
  • Configurer une stratégie exigeant une attestation
  • Créer une paire de clés cryptographiques pour signer les attestations puis les valider
  • Signer un condensé d'image de conteneur pour générer une signature
  • Créer une attestation à l'aide de la signature
  • Tester la stratégie en déployant une image de conteneur sur GKE

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Avant de commencer

  1. Connectez-vous à votre compte Google Cloud. Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits gratuits pour exécuter, tester et déployer des charges de travail.
  2. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  3. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  4. Installez Google Cloud CLI.
  5. Pour initialiser gcloudCLI, exécutez la commande suivante :

    gcloud init
  6. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  7. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  8. Installez Google Cloud CLI.
  9. Pour initialiser gcloudCLI, exécutez la commande suivante :

    gcloud init
  10. Installez kubectl pour interagir avec GKE.

Activer l'autorisation binaire

Définir le projet par défaut

La première étape consiste à définir le projet Google Cloud par défaut utilisé par la commande gcloud :

PROJECT_ID=PROJECT_ID
gcloud config set project ${PROJECT_ID}

PROJECT_ID correspond au nom de votre projet.

Activer les API requises

Activez les API pour :

Container Registry

gcloud --project=${PROJECT_ID} \
    services enable\
    container.googleapis.com\
    containerregistry.googleapis.com\
    binaryauthorization.googleapis.com

Artifact Registry

gcloud --project=${PROJECT_ID} \
    services enable\
    container.googleapis.com\
    artifactregistry.googleapis.com\
    binaryauthorization.googleapis.com

Créer un cluster avec l'autorisation binaire activée

Créer le cluster

Créer un cluster GKE avec l'autorisation binaire activée Il s'agit du cluster dans lequel vous souhaitez exécuter les images de conteneur que vous déployez. Lorsque vous créez le cluster, vous transmettez l'option --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE à la commande gcloud container clusters create.

Pour créer le cluster, procédez comme suit :

gcloud container clusters create \
    --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
    --zone us-central1-a \
    test-cluster

Ici, vous créez un cluster nommé test-cluster dans la zone GKE us-central1-a.

Configurer kubectl

Vous devez également mettre à jour le fichier kubeconfig local pour votre installation kubectl. Cela fournit les identifiants et les informations de point de terminaison requis pour accéder au cluster dans GKE.

Pour mettre à jour le fichier kubeconfig local, exécutez la commande suivante :

gcloud container clusters get-credentials \
    --zone us-central1-a \
    test-cluster

Afficher la stratégie par défaut

Dans l'autorisation binaire, une stratégie est un ensemble de règles régissant le déploiement d'une ou plusieurs images de conteneurs. Vous pouvez définir une stratégie par projet. Par défaut, la stratégie est configurée pour autoriser le déploiement de toutes les images de conteneurs.

L'autorisation binaire vous permet d'exporter et d'importer un fichier de stratégie au format YAML. Ce format reflète la structure d'une stratégie telle qu'elle est stockée par le service. Lorsque vous configurez une stratégie à l'aide des commandes gcloud, vous modifiez ce fichier.

Pour afficher la stratégie par défaut, exportez le fichier YAML de stratégie :

gcloud container binauthz policy export

Par défaut, ce fichier comporte les éléments suivants :

admissionWhitelistPatterns:
- namePattern: gcr.io/google_containers/*
- namePattern: gcr.io/google-containers/*
- namePattern: k8s.gcr.io/**
- namePattern: gke.gcr.io/**
- namePattern: gcr.io/stackdriver-agents/*
globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_ALLOW
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/${PROJECT_ID}/policy

La liste par défaut contient le registre Open Source appartenant à la communauté k8s.gcr.io, remplacé par registry.k8s.io et conservé dans la liste pour assurer la rétrocompatibilité. Le registre de remplacement registry.k8s.io n'est pas inclus dans la liste par défaut. Lorsque vous effectuez une migration depuis k8s.gcr.io, accédez au registre que vous contrôlez ou ajoutez le registre de remplacement registry.k8s.io à cette liste.

Ici, la règle par défaut est définie dans le nœud defaultAdmissionRule. evaluationMode indique que la stratégie autorise toutes les tentatives lors du déploiement de l'image. Dans ce tutoriel, vous allez mettre à jour la règle par défaut afin d'exiger des attestations.

Pour en savoir plus sur la structure d'une stratégie, consultez la documentation de référence sur les fichiers YAML de stratégie.

Créer un certificateur

Un certificateur est l'autorité de validation utilisée par l'outil d'application de l'autorisation binaire au moment du déploiement pour décider d'autoriser ou non GKE à déployer l'image de conteneur signée correspondante. Le certificateur contient la clé publique et, en règle générale, il est géré par les personnes qui, dans votre organisation, sont responsables de la sécurité de la chaîne d'approvisionnement logicielle.

Pour créer un certificateur, vous devez effectuer les actions suivantes :

  • Créer une note dans Artifact Analysis pour stocker les métadonnées de confiance utilisées dans le processus d'autorisation.
  • Créer le certificat proprement dit dans l'autorisation binaire et lui associer la note que vous avez créée.

Pour ce tutoriel, vous disposez d'un certificateur nommé test-attestor et d'une note Container Analysis nommée test-attestor-note. Dans un scénario réel, vous pouvez avoir un nombre illimité de certificateurs, chacun représentant une partie prenante du processus d'autorisation de l'image de conteneur.

Créer la note Artifact Analysis

  1. Définissez des variables qui stockent le nom de votre certificateur et la note Artifact Analysis :

    ATTESTOR_NAME=test-attestor
    NOTE_ID=test-attestor-note
    

    Remplacez :

    • test-attestor : nom du certificateur de votre choix.
    • attestor-note : nom de la note de certificateur de votre choix.
  2. Créez un fichier JSON décrivant la note Container Analysis dans /tmp/note_payload.json :

    cat > /tmp/note_payload.json << EOM
    {
      "name": "projects/${PROJECT_ID}/notes/${NOTE_ID}",
      "attestation": {
        "hint": {
          "human_readable_name": "Attestor Note"
        }
      }
    }
    EOM
    
  3. Créez la note en envoyant une requête HTTP à l'API REST Artifact Analysis :

    curl -X POST \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
        --data-binary @/tmp/note_payload.json  \
        "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
    
  4. Vérifiez que la note a bien été créée :

    curl \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
    

Créer le certificateur

Vous pouvez maintenant créer le certificateur.

  1. Créez le certificateur dans l'autorisation binaire :

    gcloud container binauthz attestors create ${ATTESTOR_NAME} \
    --attestation-authority-note=${NOTE_ID} \
    --attestation-authority-note-project=${PROJECT_ID}
    
  2. Vérifiez que le certificateur a bien été créé :

    gcloud container binauthz attestors list
    

Le certificateur que vous avez créé n'est pas utilisable sans paire de clés PKIX associée. Vous allez la créer ci-dessous.

Générer une paire de clés

L'autorisation binaire utilise des clés cryptographiques pour vérifier de manière sécurisée l'identité des signataires. Cela garantit que seules les images de conteneurs autorisées peuvent être déployées. La paire de clés comprend une clé privée et une clé publique. Le signataire utilise la clé privée pour signer le condensé de l'image de conteneur, produisant ainsi une signature qui est ensuite stockée dans une attestation. La clé publique est stockée dans le certificateur. Au moment du déploiement, l'outil d'application de l'autorisation binaire utilise la clé publique du certificateur pour valider la signature figurant dans l'attestation, avant d'autoriser le déploiement du conteneur.

Dans ce tutoriel, vous allez utiliser le format d'infrastructure à clé publique X.509 (PKIX) pour les clés cryptographiques. Ce tutoriel utilise l'algorithme de signature numérique à courbe elliptique (ECDSA) recommandé pour générer une paire de clés PKIX. Vous pouvez également utiliser des clés RSA ou PGP pour la signature.

Consultez la page Objectifs et algorithmes des clés pour plus d'informations sur les algorithmes de signature.

Les clés générées et stockées par le service Cloud Key Management Service (Cloud KMS) sont compatibles avec PKIX. Consultez la page Créer des certificateurs à l'aide de la CLI gcloud pour plus d'informations sur l'utilisation des clés PKIX et de Cloud KMS.

PKIX (Cloud KMS)

Pour créer la paire de clés dans Cloud KMS, procédez comme suit :

  1. Configurez les variables d'environnement nécessaires à la création de la paire de clés.

    KMS_KEY_PROJECT_ID=${PROJECT_ID}
    KMS_KEYRING_NAME=my-binauthz-keyring
    KMS_KEY_NAME=my-binauthz-kms-key-name
    KMS_KEY_LOCATION=global
    KMS_KEY_PURPOSE=asymmetric-signing
    KMS_KEY_ALGORITHM=ec-sign-p256-sha256
    KMS_PROTECTION_LEVEL=software
    KMS_KEY_VERSION=1
    
  2. Pour créer le trousseau, exécutez la commande suivante :

    gcloud kms keyrings create ${KMS_KEYRING_NAME} \
      --location ${KMS_KEY_LOCATION}
    
  3. Pour créer la clé, exécutez la commande suivante :

    gcloud kms keys create ${KMS_KEY_NAME} \
      --location ${KMS_KEY_LOCATION} \
      --keyring ${KMS_KEYRING_NAME}  \
      --purpose ${KMS_KEY_PURPOSE} \
      --default-algorithm ${KMS_KEY_ALGORITHM} \
      --protection-level ${KMS_PROTECTION_LEVEL}
    
  4. Pour ajouter la clé publique au certificateur, exécutez la commande suivante :

    gcloud --project="${PROJECT_ID}" \
        container binauthz attestors public-keys add \
        --attestor="${ATTESTOR_NAME}" \
        --keyversion-project="${KMS_KEY_PROJECT_ID}" \
        --keyversion-location="${KMS_KEY_LOCATION}" \
        --keyversion-keyring="${KMS_KEYRING_NAME}" \
        --keyversion-key="${KMS_KEY_NAME}" \
        --keyversion="${KMS_KEY_VERSION}"
    
  5. Obtenez l'ID de clé publique auprès du certificateur comme suit :

    Vous pouvez afficher l'ID de votre clé publique à tout moment à l'aide de la commande gcloud container binauthz attestors describe <var>ATTESTOR_NAME</var>.

    Pour enregistrer votre ID de clé publique dans une variable d'environnement, saisissez la commande suivante :

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
    --format='value(userOwnedGrafeasNote.publicKeys[0].id)' --project ${PROJECT_ID})
    

PKIX (clé locale)

Pour générer une paire de clés PKIX, procédez comme suit :

  1. Créez la clé privée :

    PRIVATE_KEY_FILE="/tmp/ec_private.pem"
    openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
    
  2. Extrayez la clé publique de la clé privée :

    PUBLIC_KEY_FILE="/tmp/ec_public.pem"
    openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
    
  3. Ajoutez la clé publique au certificateur.

    Ajoutez maintenant au certificateur la clé publique que vous avez exportée, pour qu'elle puisse être utilisée par l'autorisation binaire pour la validation de l'identité :

    gcloud --project="${PROJECT_ID}" \
        beta container binauthz attestors public-keys add \
        --attestor="${ATTESTOR_NAME}" \
        --pkix-public-key-file=${PUBLIC_KEY_FILE} \
        --pkix-public-key-algorithm=ecdsa-p256-sha256
    
  4. Enregistrez l'ID de la clé publique.

    Pour enregistrer l'ID de clé publique, vous pouvez le copier à partir du résultat de la commande public-keys add figurant ci-dessus. Pour afficher l'ID de clé publique de votre certificateur après son ajout, utilisez la commande gcloud container binauthz attestors describe ${ATTESTOR_NAME} :

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
    

Configurer la stratégie

Vous pouvez maintenant configurer votre stratégie. Au cours de cette étape, vous exportez le fichier YAML de stratégie vers votre système local et modifiez la règle par défaut de sorte qu'elle nécessite une attestation de la part du certificateur que vous avez défini ci-dessus.

Pour configurer la stratégie, procédez comme suit :

  1. Créez un fichier de stratégie qui autorise les images système gérées par Google, définit evaluationMode sur REQUIRE_ATTESTATION et ajoute un nœud nommé requireAttestationsBy qui référence le certificateur que vous avez créé :

    cat > /tmp/policy.yaml << EOM
        globalPolicyEvaluationMode: ENABLE
        defaultAdmissionRule:
          evaluationMode: REQUIRE_ATTESTATION
          enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
          requireAttestationsBy:
            - projects/${PROJECT_ID}/attestors/${ATTESTOR_NAME}
        name: projects/${PROJECT_ID}/policy
    EOM
    
  2. Importez le fichier YAML de stratégie dans l'autorisation binaire :

    gcloud container binauthz policy import /tmp/policy.yaml
    

Pour plus d'informations sur la configuration des stratégies, consultez la page Configurer une stratégie à l'aide de la CLI gcloud.

Tester la stratégie

Vous pouvez tester la stratégie que vous avez configurée ci-dessus en essayant de déployer un exemple d'image de conteneur sur le cluster. La stratégie va bloquer le déploiement, car l'attestation requise n'a pas été réalisée.

Pour ce tutoriel, vous pouvez utiliser des exemples d'images de Container Registry et d'Artifact Registry. L'image de Container Registry se trouve dans le chemin gcr.io/google-samples/hello-app:1.0. L'image d'Artifact Registry se trouve dans le chemin us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0. Les deux chemins d'accès contiennent une image publique créée par Google et contenant un exemple d'application "Hello, World!".

Commencez par essayer de déployer l'image :

kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080

Maintenant, vérifiez que le déploiement a été bloqué par l'autorisation binaire :

kubectl get pods

La commande affiche le message suivant, qui indique que l'image n'a pas été déployée :

No resources found.

Vous pouvez obtenir plus de détails sur le déploiement avec la commande suivante :

kubectl get event --template \
'{{range.items}}{{"\033[0;36m"}}{{.reason}}:{{"\033[0m"}}\{{.message}}{{"\n"}}{{end}}'

Une réponse semblable à celle-ci s'affiche :

FailedCreate: Error creating: pods POD_NAME is forbidden: admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image IMAGE_NAME denied by Binary Authorization default admission rule. Image IMAGE_NAME denied by attestor ATTESTOR_NAME: No attestations found

Dans ce résultat :

  • POD_NAME : nom du pod.
  • IMAGE_NAME : nom de l'image.
  • ATTESTOR_NAME : nom du certificateur.

Veillez à supprimer le déploiement pour pouvoir passer à l'étape suivante :

kubectl delete deployment hello-server

Créez un certificat

Une attestation est un document numérique créé par un signataire certifiant que GKE est autorisé à déployer l'image de conteneur associée. Le processus de création d'une attestation est parfois appelé "signature d'une image". Un signataire peut être une personne ou, plus souvent, un processus automatisé qui s'exécute à la création d'une image de conteneur. La signature est créée à l'aide de la clé privée provenant d'une paire de clés. Au moment du déploiement, l'outil d'application de l'autorisation binaire utilise la clé publique du certificateur pour valider la signature dans l'attestation.

Dans ce tutoriel, votre attestation indique simplement que vous autorisez l'image en vue du déploiement.

Pour créer une attestation, procédez comme suit :

  1. Définissez les variables qui stockent le chemin d'accès au registre et le condensé de l'image :

    Container Registry

    IMAGE_PATH="gcr.io/google-samples/hello-app"
    IMAGE_DIGEST="sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea882eb722c3be4"
    IMAGE_TO_ATTEST=${IMAGE_PATH}@${IMAGE_DIGEST}
    

    Artifact Registry

    IMAGE_PATH="us-docker.pkg.dev/google-samples/containers/gke/hello-app"
    IMAGE_DIGEST="sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567"
    IMAGE_TO_ATTEST=${IMAGE_PATH}@${IMAGE_DIGEST}
    
  2. Pour créer l'attestation, procédez comme suit :

    PKIX Cloud KMS

    Pour créer l'attestation à l'aide de la clé Cloud KMS, exécutez la commande suivante :

    gcloud beta container binauthz attestations sign-and-create \
        --project="${PROJECT_ID}" \
        --artifact-url="${IMAGE_TO_ATTEST}" \
        --attestor="${ATTESTOR_NAME}" \
        --attestor-project="${PROJECT_ID}" \
        --keyversion-project="${KMS_KEY_PROJECT_ID}" \
        --keyversion-location="${KMS_KEY_LOCATION}" \
        --keyversion-keyring="${KMS_KEYRING_NAME}" \
        --keyversion-key="${KMS_KEY_NAME}" \
        --keyversion="${KMS_KEY_VERSION}"
    

    PKIX (clé locale)

    Pour créer l'attestation à l'aide de la clé locale, procédez comme suit :

    1. Générez la charge utile de l'attestation :

      gcloud container binauthz create-signature-payload \
      --artifact-url=${IMAGE_TO_ATTEST} > /tmp/generated_payload.json
      

      Le contenu du fichier JSON de charge utile obtenu est le suivant :

      {
      "critical": {
        "identity": {
          "docker-reference": "gcr.io/google-samples/hello-app"
        },
        "image": {
          "docker-manifest-digest": "sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea
      882eb722c3be4"
        },
        "type": "Google cloud binauthz container signature"
      }
      }
      
    2. Pour signer la charge utile avec votre clé privée PKIX et générer un fichier de signature, exécutez la commande suivante :

      openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
      

      Le fichier de signature est la version signée du fichier JSON de charge utile que vous avez créé précédemment dans ce guide.

    3. Créez et validez l'attestation :

      gcloud container binauthz attestations create \
        --project="${PROJECT_ID}" \
        --artifact-url="${IMAGE_TO_ATTEST}" \
        --attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR_NAME}" \
        --signature-file=/tmp/ec_signature \
        --public-key-id="${PUBLIC_KEY_ID}" \
        --validate
      

      Remplacez PUBLIC_KEY_ID par l'ID de clé publique que vous avez déterminé à la section Générer une paire de clés PKIX ci-dessus.

      L'option validate vérifie que l'attestation peut être validée par le certificateur que vous avez configuré dans votre stratégie.

  3. Vérifiez que l'attestation a bien été créée :

    gcloud container binauthz attestations list \
        --attestor=$ATTESTOR_NAME --attestor-project=$PROJECT_ID
    

Pour en savoir plus sur la création d'attestations, consultez la page Créer des attestations.

Tester une nouvelle fois la stratégie

Testez une nouvelle fois la stratégie en déployant un exemple d'image de conteneur sur le cluster. Cette fois, vous devez déployer l'image à l'aide du condensé au lieu d'un tag tel que 1.0 ou latest, car l'autorisation binaire utilise à la fois le chemin d'accès de l'image et le condensé afin de rechercher les attestations. Ici, l'autorisation binaire permet le déploiement de l'image, car l'attestation requise a été réalisée.

Pour déployer l'image, exécutez la commande suivante :

kubectl run hello-server --image ${IMAGE_TO_ATTEST} --port 8080

Pour vérifier que l'image a été déployée :

kubectl get pods

La commande imprime un message semblable à celui ci-dessous, indiquant que le déploiement a bien été effectué :

NAME                            READY     STATUS    RESTARTS   AGE
hello-server-579859fb5b-h2k8s   1/1       Running   0          1m

Effectuer un nettoyage

Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

Supprimez le cluster que vous avez créé dans GKE :

gcloud container clusters delete \
    --zone=us-central1-a \
    test-cluster

Étape suivante