Créer des attestations avec Kritis Signer

Ce tutoriel explique comment créer Kritis Signer et comment l'utiliser pour rechercher les failles des images de conteneurs avant de créer des attestations d'autorisation binaire.

Présentation

Kritis Signer est un outil de ligne de commande Open Source qui peut créer des attestations d'autorisation binaire en fonction d'une stratégie que vous configurez. Vous pouvez également utiliser Kritis Signer pour créer des attestations après avoir vérifié une image pour détecter des failles identifiées par Container Analysis.

De plus, Cloud Build peut exécuter Kritis Signer en tant que compilateur personnalisé dans un pipeline de compilation.

Dans ce tutoriel, vous allez effectuer une compilation unique du compilateur personnalisé Kritis Signer, puis exécuter des exemples de pipelines de compilation. Chaque exemple de pipeline contient les étapes de compilation suivantes :

  1. Créer un exemple d'image de conteneur
  2. Stocker l'image dans Container Registry
  3. Vérifiez et signez l'image : utilisez Kritis Signer pour créer une attestation basée sur la stratégie.

À l'étape de compilation du processus de vérification de chaque pipeline, Kritis Signer effectue les opérations suivantes :

  1. Analyse l'image nouvellement créée avec Container Analysis et récupère une liste de failles.
  2. Vérifie la liste des failles par rapport aux règles de signature des failles dans la stratégie, puis effectue les opérations suivantes :
    1. Si toutes les failles identifiées respectent les règles de signature des failles, Kritis Signer crée l'attestation.
    2. Si l'une des failles identifiées ne respecte pas les règles de signature des failles, Kritis Signer ne crée pas l'attestation.

Au moment du déploiement, l'outil d'application de l'autorisation binaire recherche une attestation vérifiable. Sans cela, l'outil d'application bloque le déploiement de l'image.

Ce tutoriel explique également comment exécuter Kritis Signer en mode test uniquement dans un pipeline Cloud Build. Dans ce mode, Kritis Signer ne crée pas d'attestation. Il vérifie uniquement si les résultats de faille respectent les règles de signature des failles dans la stratégie. Si c'est le cas, l'étape de compilation de Kritis Signer aboutit et le pipeline continue de s'exécuter. Sinon, l'étape échoue et le pipeline se ferme.

Objectifs

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

  1. configurer Kritis Signer en tant que compilateur personnalisé Cloud Build ;
  2. Affichez une stratégie contenant des règles de signature des failles.
  3. Exécutez Kritis Signer dans des attestations de création basées sur les résultats de l'analyse des failles.
  4. Exécutez Kritis Signer en mode test uniquement.

Coûts

Ce tutoriel utilise les produits Google Cloud suivants.

  • Container Registry
  • Container Analysis
  • Cloud Build
  • Cloud Key Management Service

Utilisez le simulateur de coût pour générer une estimation des coûts en fonction de votre utilisation prévue.

Avant de commencer

Dans cette section, vous allez effectuer une configuration unique du système.

Configurer votre environnement

  1. Stockez votre projet Google Cloud dans une variable d'environnement.

    export PROJECT_ID=PROJECT_ID
    

    Remplacez PROJECT_ID par votre projet Google Cloud.

  2. Définissez l'ID de projet par défaut sur votre projet Google Cloud :

    gcloud config set project $PROJECT_ID
    
  3. Stockez le numéro de projet dans une variable d'environnement pour les étapes suivantes :

    export PROJECT_NUMBER=$(gcloud projects list --filter="${PROJECT_ID}" \
     --format="value(PROJECT_NUMBER)")
    
  4. Activez les API :

    Pour vous assurer que les services requis pour ce guide sont activés, exécutez la commande suivante :

    gcloud services enable \
      cloudbuild.googleapis.com \
      containerregistry.googleapis.com \
      containerscanning.googleapis.com \
      cloudkms.googleapis.com
    

Configurer les rôles IAM

Exécutez les commandes suivantes pour configurer les rôles suivants sur le compte de service Cloud Build :

  • containeranalysis.notes.editor : ajoute le rôle Éditeur de notes Container Analysis pour gérer le certificateur.
  • containeranalysis.notes.occurrences.viewer : ajoute le rôle Lecteur d'occurrences Container Analysis pour les notes afin de gérer à la fois les occurrences de failles et d'attestation.
  • roles/containeranalysis.occurrences.editor : ajoute le rôle Éditeur d'occurrences Container Analysis pour créer des occurrences d'attestation dans Container Analysis.
  • cloudkms.signer : ajoute le rôle Signataire de CryptoKeys Cloud KMS qui permet au compte de service d'accéder au service de signature Cloud KMS.

    gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role roles/containeranalysis.notes.editor
    gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role roles/containeranalysis.notes.occurrences.viewer
    gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role roles/containeranalysis.occurrences.editor
    gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role roles/cloudkms.signer
    

Configurer le compilateur personnalisé Kritis Signer

Dans cette section, vous allez effectuer une configuration unique du compilateur personnalisé Kritis Signer. Une fois que vous avez obtenu, compilé et transféré Kritis Signer, vous pouvez ensuite l'utiliser dans n'importe quel pipeline Cloud Build.

Cette section vous explique comment :

  • cloner le dépôt Kritis ;
  • créer le compilateur personnalisé Cloud Build Kritis Signer ;
  • transférer Kritis Signer vers Container Registry pour le rendre disponible en tant qu'étape de compilation Cloud Build.

Exécutez les commandes suivantes pour obtenir le code et les fichiers de configuration utilisés dans ce guide :

  1. Cloner le dépôt Kritis :

    git clone https://github.com/grafeas/kritis.git
    

    Ce dépôt contient les éléments suivants :

    • Le code source de Kritis, incluant également Kritis Signer
    • Un fichier de configuration Cloud Build utilisé par Cloud Build pour créer le compilateur personnalisé Kritis Signer
    • Un exemple de stratégie contenant des règles de signature des failles.
    • Des exemples de fichiers de configuration Cloud Build. Chaque fichier de configuration utilise Kritis Signer dans un pipeline d'analyse des failles.
  2. Accédez au répertoire kritis/ :

    cd kritis
    
  3. Créez et enregistrez le compilateur personnalisé Kritis Signer.

    Cette étape de configuration unique crée le compilateur personnalisé Kritis Signer et l'enregistre auprès de Cloud Build. Une fois enregistré, le compilateur personnalisé peut être utilisé dans n'importe quel pipeline Cloud Build.

    gcloud builds submit . --config deploy/kritis-signer/cloudbuild.yaml
    

Afficher une stratégie existante

Cette section présente un exemple de règle Kritis Signer.

Cette règle configure Kritis Signer pour demander à Container Analysis d'analyser l'image pour rechercher des failles. Une fois l'analyse terminée, Kritis Signer vérifie les résultats de failles renvoyés par rapport aux règles de signature des failles dans la stratégie.

Vous pouvez modifier les règles de signature des failles dans cette stratégie pour créer une attestation basée sur les éléments suivants :

  • Niveaux de gravité des failles identifiées
  • Failles spécifiques

Vous pouvez également définir la stratégie pour créer sans condition (ALLOW_ALL) ou ne pas créer (BLOCK_ALL) d'attestation.

Pour afficher la règle Kritis Signer, exécutez la commande suivante :

cat samples/signer/policy.yaml

La règle se présente comme suit :

apiVersion: kritis.grafeas.io/v1beta1
kind: VulnzSigningPolicy
metadata:
  name: my-vsp
spec:
  imageVulnerabilityRequirements:
    maximumFixableSeverity: MEDIUM
    maximumUnfixableSeverity: MEDIUM
    allowlistCVEs:
    - projects/goog-vulnz/notes/CVE-2021-20305
    - projects/goog-vulnz/notes/CVE-2020-10543
    - projects/goog-vulnz/notes/CVE-2020-10878
    - projects/goog-vulnz/notes/CVE-2020-14155
    - projects/goog-vulnz/notes/CVE-2019-25013
    - projects/goog-vulnz/notes/CVE-2021-33574
    - projects/goog-vulnz/notes/CVE-2021-3520

Où :

  • maximumUnfixableSeverity et maximumFixableSeverity définissent les seuils de gravité des failles et expositions communes (CVE, Common Vulnerabilities and Exposures) auxquels Kritis Signer crée des attestations. maximumUnfixableSeverity définit le seuil de gravité pour lequel un correctif n'est pas disponible actuellement. maximumFixableSeverity définit le seuil de gravité pour lequel un correctif est actuellement disponible. maximumUnfixableSeverity et maximumFixableSeverity peuvent être définis sur l'un des niveaux de gravité suivants :

    • CRITICAL
    • HIGH
    • MEDIUM
    • LOW

    Pour en savoir plus sur les niveaux de gravité, consultez la section Niveaux de gravité.

    Vous pouvez également définir maximumUnfixableSeverity et maximumFixableSeverity sur les éléments suivants :

    • BLOCK_ALL : l'attestation n'est pas créée si une faille est détectée.
    • ALLOW_ALL : l'attestation est toujours créée.
  • allowlistCVEs est une liste de CVE spécifiques à ajouter à la liste d'autorisation. Kritis Signer ignore les failles CVE de cette liste lors de l'évaluation de la création d'une attestation. Chaque entrée de la liste d'autorisation doit correspondre exactement au nom de la note Container Analysis pour la faille CVE. En savoir plus sur les sources de failles Container Analysis. Pour en savoir plus sur les notes, consultez la page Stockage de métadonnées.

Créer une clé de signature Cloud KMS

Les clés Cloud Key Management Service sont utilisées pour créer l'attestation.

  1. Créez un trousseau de clés Cloud KMS nommé kritis-signer-key-ring :

    gcloud kms keyrings create kritis-signer-key-ring \
       --location global
    
  2. Dans ce trousseau, créez une clé Cloud KMS appelée kritis-signer-key :

    gcloud kms keys create kritis-signer-key \
        --keyring kritis-signer-key-ring \
        --location global \
        --purpose "asymmetric-signing" \
        --default-algorithm "rsa-sign-pkcs1-2048-sha256"
    
  3. Stockez l'algorithme de condensé et la clé Cloud KMS dans une variable d'environnement pour les prochaines étapes :

    export KMS_DIGEST_ALG=SHA256
    export KMS_KEY_NAME=projects/$PROJECT_ID/locations/global/keyRings/kritis-signer-key-ring/cryptoKeys/kritis-signer-key/cryptoKeyVersions/1
    

Définir un nom de note

Toutes les attestations font référence à une note Container Analysis. Kritis Signer crée automatiquement une note pour un nom donné. Vous pouvez également réutiliser des noms de notes existants.

export NOTE_ID=my-signer-note
export NOTE_NAME=projects/${PROJECT_ID}/notes/${NOTE_ID}

Créer des attestations à l'aide de Kritis Signer dans un pipeline Cloud Build

Cette section explique comment utiliser le compilateur personnalisé Kritis Signer pour créer des attestations d'autorisation binaire basées sur les résultats de l'analyse des failles.

Les étapes suivantes montrent comment Kritis Signer utilise les exemples de fichiers de configuration de compilation du dépôt Kritis Signer. Chaque exemple de fichier de configuration contient les étapes de compilation suivantes :

  1. Une étape docker build qui crée une image de conteneur Docker
  2. Une étape docker push qui transfère l'image de conteneur nouvellement créée vers Container Registry
  3. Une étape vulnsign qui vérifie et signe l'image du conteneur en effectuant les opérations suivantes :

    1. Elle attend que Container Analysis renvoie les résultats des failles sur la nouvelle image de conteneur.
    2. Elle vérifie les résultats en fonction des règles de signature des failles.
    3. Elle crée l'attestation si les résultats respectent les règles sur les failles.

Vous envoyez chacun de ces exemples de compilation à Cloud Build. Chaque compilation produit un résultat de faille :

  • Exemple d'échec : dans la première compilation, le résultat de faille enfreint les règles de signature des failles. Cette compilation échoue.
  • Exemple de réussite : dans la deuxième compilation, le résultat de faille respecte les règles de signature des failles. Cette compilation réussit.

Envoyer l'exemple d'échec de la compilation

Cet exemple crée une image de conteneur basée sur Debian 9. Actuellement, l'image contient une faille qui ne respecte pas les règles de signature des failles. Le compilateur personnalisé Kritis Signer ne produit pas d'attestation.

  1. (Facultatif) Affichez le fichier de configuration de compilation pour le cas d'échec.

    cat samples/signer/cloudbuild-bad.yaml
    
  2. Envoyez la compilation :

    gcloud builds submit \
      --substitutions=_KMS_KEY_NAME=$KMS_KEY_NAME,_KMS_DIGEST_ALG=$KMS_DIGEST_ALG,_NOTE_NAME=$NOTE_NAME \
      --config=samples/signer/cloudbuild-bad.yaml samples/signer
    

    Un résultat semblable à celui-ci s'affiche :

    "ERROR: (gcloud.builds.submit) build BUILD_ID completed with status "FAILURE"
    
  3. Enregistrez l'ID de la dernière compilation :

    export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
    
  4. Vérifiez le résultat :

     gsutil cat gs://${PROJECT_NUMBER}.cloudbuild-logs.googleusercontent.com/log-${BUILD_ID}.txt | grep "does not pass VulnzSigningPolicy"
    

Envoyer l'exemple de réussite de la compilation

Cet exemple crée une image de conteneur contenant des failles qui n'enfreignent pas les règles de signature des failles. Le compilateur personnalisé Kritis Signer crée une attestation.

Pour envoyer l'exemple de réussite de la compilation dans Cloud Build, procédez comme suit :

  1. (Facultatif) Affichez le fichier de configuration de compilation pour le cas de réussite.

    cat samples/signer/cloudbuild-good.yaml
    
  2. Envoyez la compilation :

    gcloud builds submit \
      --substitutions=_KMS_KEY_NAME=$KMS_KEY_NAME,_KMS_DIGEST_ALG=$KMS_DIGEST_ALG,_NOTE_NAME=$NOTE_NAME \
      --config=samples/signer/cloudbuild-good.yaml samples/signer
    
  3. Enregistrez l'ID de la dernière compilation :

    export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
    
  4. Vérifiez le résultat :

    gcloud builds describe $BUILD_ID | grep status
    

Utiliser Kritis Signer en mode test uniquement

Cette section explique comment utiliser Kritis Signer en mode check-only. Dans ce mode, Kritis Signer ne crée pas d'attestation. Elle ne vérifie que les failles de l'image avant de réussir ou d'échouer à l'étape de compilation en fonction des règles de signature des failles.

Envoyer l'exemple d'échec de la compilation

  1. (Facultatif) Affichez le fichier de configuration de compilation pour le cas d'échec.

    cat samples/policy-check/cloudbuild-bad.yaml
    

    Dans l'étape de compilation de Kritis Signer, notez que l'option mode est définie sur check-only.

  2. Envoyez la compilation :

    gcloud builds submit \
      --config=samples/policy-check/cloudbuild-bad.yaml samples/policy-check
    

    Notez que la compilation échoue.

  3. Enregistrez l'ID de la dernière compilation :

    export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
    
  4. Vérifiez le résultat :

     gsutil cat gs://${PROJECT_NUMBER}.cloudbuild-logs.googleusercontent.com/log-${BUILD_ID}.txt | grep "does not pass VulnzSigningPolicy"
    

Envoyer l'exemple de réussite de la compilation

  1. (Facultatif) Affichez le fichier de configuration de compilation pour le cas d'échec.

    cat samples/policy-check/cloudbuild-good.yaml
    
  2. Envoyez la compilation :

    gcloud builds submit \
     --config=samples/policy-check/cloudbuild-good.yaml samples/policy-check
    
  3. Enregistrez l'ID de la dernière compilation :

    export BUILD_ID=$(gcloud builds list --limit=1 --format="value('ID')")
    
  4. Vérifiez le résultat :

    gcloud builds describe $BUILD_ID | grep status
    

Effectuer un nettoyage

Pour nettoyer les ressources utilisées dans ce document, vous pouvez supprimer le projet :

gcloud projects delete ${PROJECT_ID}

Étape suivante