Signer des images conteneur à l’aide de notation, d’Azure Key Vault et d’un certificat émis par une autorité de certification

Cet article fait partie d’une série visant à garantir l’intégrité et l’authenticité des images de conteneurs et d’autres artefacts de l'Open Container Initiative (OCI). Pour obtenir l’image complète, commencez par la vue d’ensemble, ce qui explique pourquoi la signature importe et présente les différents scénarios.

La signature et la vérification des images conteneur à l’aide d’un certificat d’une autorité de certification approuvée constituent une pratique de sécurité précieuse. Il vous aide à identifier, autoriser et valider de manière responsable l’identité de l’éditeur d’une image conteneur et de l’image conteneur elle-même. Les autorités de certification approuvées telles que GlobalSign, DigiCert et d’autres jouent un rôle crucial dans :

  • Validation de l’identité d’un utilisateur ou d’une organisation.
  • Maintien de la sécurité des certificats numériques.
  • Révocation de certificats immédiatement en cas de risque ou d’utilisation incorrecte.

Voici quelques composants essentiels qui vous aident à signer et à vérifier des images conteneur à l’aide d’un certificat d’une autorité de certification approuvée :

  • Notation est un outil de sécurité de la chaîne d’approvisionnement open source développé par la communauté du projet notarié et soutenu par Microsoft. Il prend en charge la signature et la vérification des images de conteneur et d’autres artefacts.
  • Azure Key Vault est un service cloud permettant de gérer les clés de chiffrement, les secrets et les certificats. Il vous aide à stocker et gérer en toute sécurité un certificat avec une clé de signature.
  • Le plug-in Key Vault (notation-azure-kv) est une extension de Notation. Il utilise les clés stockées dans Key Vault pour signer et vérifier les signatures numériques des images et artefacts conteneur.
  • Azure Container Registry est un registre privé que vous pouvez utiliser pour attacher des signatures à des images conteneur, ainsi que le stockage et la gestion de ces images.

Lorsque vous vérifiez une image, la signature est utilisée pour valider l’intégrité de l’image et l’identité du signataire. Cette validation permet de s’assurer que les images conteneur ne sont pas falsifiées et proviennent d’une source approuvée.

Dans cet article, vous allez apprendre à :

  • Installez l’interface de ligne de commande Notation (CLI) et le plug-in Key Vault.
  • Créez ou importez un certificat émis par une autorité de certification dans Key Vault.
  • Générez et envoyez (push) une image conteneur à l’aide de tâches Container Registry.
  • Signez une image-conteneur à l’aide de la CLI Notation et du plug-in Key Vault.
  • Vérifiez une signature d’image conteneur à l’aide de l’outil CLI Notation.
  • Utilisez l’horodatage.

Prérequis

  • Créez ou utilisez un registre de conteneurs pour stocker des images et des signatures conteneur.
  • Créez ou utilisez un coffre de clés. Nous vous recommandons de créer un coffre de clés pour le stockage des certificats uniquement.
  • Installez et configurez la dernière version d’Azure CLI ou exécutez des commandes dans Azure Cloud Shell.

Installer l’interface CLI Notation et le plug-in Key Vault.

  1. Installez Notation v1.3.2 dans un environnement Linux AMD64. Pour télécharger le package pour d’autres environnements, suivez le guide d’installation Notation.

    # Download, extract, and install
    curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.3.2/notation_1.3.2_linux_amd64.tar.gz
    tar xvzf notation.tar.gz
    
    # Copy the Notation CLI to the desired bin directory in PATH, for example
    cp ./notation /usr/local/bin
    
  2. Installez le plug-in Key Vault (notation-azure-kv) v1.2.1 dans un environnement LINUX AMD64.

    Remarque

    Vous trouverez l’URL et la somme de contrôle SHA256 pour le plug-in sur la page de publication du plug-in.

    notation plugin install --url https://github.com/Azure/notation-azure-kv/releases/download/v1.2.1/notation-azure-kv_1.2.1_linux_amd64.tar.gz --sha256sum 67c5ccaaf28dd44d2b6572684d84e344a02c2258af1d65ead3910b3156d3eaf5
    
  3. Répertoriez les plug-ins disponibles et vérifiez que le notation-azure-kv plug-in avec version 1.2.1 est inclus dans la liste :

    notation plugin ls
    

Configuration des variables d’environnement

Cet article utilise des variables d’environnement pour des raisons pratiques dans la configuration de Key Vault et de Container Registry. Mettez à jour les valeurs de ces variables d’environnement pour vos ressources spécifiques.

  1. Configurez les variables d’environnement pour Key Vault et les certificats :

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    AKV_NAME=myakv 
    
    # Name of the certificate created or imported in Key Vault 
    CERT_NAME=wabbit-networks-io 
    
    # X.509 certificate subject
    CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
    
  2. Configurez les variables d’environnement pour Container Registry et les images :

    ACR_SUB_ID=myAcrSubscriptionId
    ACR_RG=myAcrResourceGroup
    # Name of the existing registry example: myregistry.azurecr.io 
    ACR_NAME=myregistry 
    # Existing full domain of the container registry 
    REGISTRY=$ACR_NAME.azurecr.io 
    # Container name inside the container registry where the image will be stored 
    REPO=net-monitor 
    TAG=v1 
    # Source code directory that contains the Dockerfile to build 
    IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main  
    

Se connecter à l’aide d’Azure CLI

az login

Pour plus d’informations, consultez S’authentifier auprès d’Azure à l’aide d’Azure CLI.

Créer ou importer un certificat émis par une autorité de certification dans Key Vault

Comprendre les exigences de certificat

Lorsque vous créez des certificats pour la signature et la vérification, les certificats doivent répondre aux exigences de certificat du projet Notary.

Les conditions requises pour les certificats racines et intermédiaires sont les suivantes :

  • L’extension basicConstraints doit être présente et marquée comme critical. Le CA champ doit être défini sur true.
  • L’extension keyUsage doit être présente et marquée comme critical. Les positions de bits pour keyCertSign doivent être définies.

Voici les conditions requises pour les certificats qu’une autorité de certification émet :

  • Propriétés du certificat X.509 :
    • L’objet doit contenir le nom commun (CN), le pays/la région (C), l’état ou la province () et l’organisationST (O). Cet article utilise $CERT_SUBJECT comme sujet.
    • L’indicateur d’utilisation de la clé X.509 doit être uniquement DigitalSignature.
    • Les utilisations de clés étendues (EKUs) doivent être vides ou 1.3.6.1.5.5.7.3.3 (pour la signature de code).
  • Propriétés de la clé :
    • La propriété exportable doit être définie sur false.
    • Sélectionnez un type de clé et une taille pris en charge à partir de la spécification Notary Project.

Important

Pour garantir une intégration réussie à l’intégrité de l’image, le type de contenu du certificat doit être défini sur PEM.

Ce guide utilise la version 1.0.1 du plug-in Key Vault. Les versions antérieures du plug-in avaient une limitation qui nécessitait un ordre de certificat spécifique dans une chaîne de certificats. La version 1.0.1 du plug-in n’a pas cette limitation. Nous vous recommandons donc d’utiliser la version 1.0.1 ou ultérieure.

Créer un certificat émis par une autorité de certification

Créez une demande de signature de certificat (CSR) en suivant les instructions fournies dans Créer et fusionner une demande de signature de certificat dans Key Vault.

Lorsque vous fusionnez le CSR, veillez à fusionner l’ensemble de la chaîne que vous avez renvoyée depuis le fournisseur d’autorité de certification.

Importer le certificat dans Key Vault

Pour importer le certificat, procédez comme suit :

  1. Obtenez le fichier de certificat auprès du fournisseur d’autorité de certification avec l’ensemble de la chaîne de certificats.
  2. Importez le certificat dans Key Vault en suivant les instructions de l’instruction Importer un certificat dans Azure Key Vault.

Si le certificat ne contient pas de chaîne de certificats après la création ou l’importation, vous pouvez obtenir les certificats intermédiaires et racines auprès de votre fournisseur d’autorité de certification. Vous pouvez demander à votre fournisseur de vous fournir un fichier PEM qui contient les certificats intermédiaires (le cas échéant) et le certificat racine. Vous pouvez ensuite utiliser ce fichier lorsque vous signez des images de conteneur.

Signer une image conteneur à l’aide de l’interface Notation CLI et du plug-in Key Vault

Lorsque vous travaillez avec Container Registry et Key Vault, il est essentiel d’accorder les autorisations appropriées pour garantir un accès sécurisé et contrôlé. Vous pouvez autoriser l’accès pour différentes entités, telles que les principaux d’utilisateur, les principaux de service ou les identités managées, en fonction de vos scénarios spécifiques. Dans cet article, l’accès est autorisé pour un utilisateur Azure connecté.

Autoriser l’accès à Container Registry

Pour les registres activés pour le contrôle d'accès en fonction de l'attribut Microsoft Entra (ABAC), les rôles Container Registry Repository Reader et Container Registry Repository Writer sont requis pour générer et signer des images de conteneur dans le registre de conteneurs.

Pour les registres qui ne sont pas activés pour ABAC, les rôles AcrPull et AcrPush sont requis.

Pour plus d’informations sur ABAC, consultez le contrôle d’accès basé sur les attributs Microsoft Entra pour obtenir des autorisations de référentiel.

  1. Définissez l’abonnement qui contient la ressource Container Registry :

    az account set --subscription $ACR_SUB_ID
    
  2. Attribuez les rôles :

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    ROLE1="Container Registry Repository Reader" # For ABAC-enabled registries. Otherwise, use "AcrPull" for non-ABAC-enabled registries.
    ROLE2="Container Registry Repository Writer" # For ABAC-enabled registries. Otherwise, use "AcrPush" for non-ABAC-enabled registries.
    az role assignment create --role "$ROLE1" --role "$ROLE2" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"
    

Générer et envoyer (push) des images conteneur à Container Registry

  1. Authentifiez-vous auprès de votre registre de conteneurs à l’aide de votre identité Azure individuelle :

    az acr login --name $ACR_NAME
    

    Important

    Si Vous avez installé Docker sur votre système et que vous avez utilisé az acr login ou docker login pour vous authentifier auprès de votre registre de conteneurs, vos informations d’identification sont déjà stockées et disponibles pour notation. Dans ce cas, vous n’avez pas besoin de réexécuter notation login pour vous authentifier auprès de votre registre de conteneurs. Pour en savoir plus sur les options d’authentification pour notation, consultez Authentifier avec des registres conformes à OCI.

  2. Générez et envoyez (push) une nouvelle image à l’aide de tâches Container Registry. digest Utilisez toujours l’identification de l’image pour la signature, car les balises sont mutables et peuvent être remplacées.

    DIGEST=$(az acr build -r $ACR_NAME -t $REGISTRY/${REPO}:$TAG $IMAGE_SOURCE --no-logs --query "outputImages[0].digest" -o tsv)
    IMAGE=$REGISTRY/${REPO}@$DIGEST
    

    Dans cet article, si l’image est déjà générée et stockée dans le Registre, la balise sert d’identificateur pour cette image pour des raisons pratiques :

    IMAGE=$REGISTRY/${REPO}@$TAG
    

Autoriser l’accès à Key Vault

Cette section explore deux options pour autoriser l’accès à Key Vault.

  1. Définissez l’abonnement qui contient la ressource Key Vault :

    az account set --subscription $AKV_SUB_ID
    
  2. Attribuez les rôles.

    Si le certificat contient l’intégralité de la chaîne de certificats, le principal doit se voir attribuer les rôles suivants :

    • Key Vault Secrets User pour la lecture des secrets
    • Key Vault Certificates User pour lire des certificats
    • Key Vault Crypto User pour la signature des opérations
    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "Key Vault Secrets User" --role "Key Vault Certificates User" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    

    Si le certificat ne contient pas la chaîne, le principal doit se voir attribuer les rôles suivants :

    • Key Vault Certificates User pour lire des certificats
    • Key Vault Crypto User pour la signature des opérations
    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "Key Vault Certificates User" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    

Pour en savoir plus sur l’accès Key Vault avec le contrôle d’accès en fonction du rôle Azure (RBAC), consultez Fournir l’accès aux clés, certificats et secrets Key Vault à l’aide du contrôle d’accès en fonction du rôle Azure.

Utiliser une politique d'accès (hérité)

Pour définir l’abonnement qui contient les ressources Key Vault, exécutez la commande suivante :

az account set --subscription $AKV_SUB_ID

Si le certificat contient l’intégralité de la chaîne de certificats, le principal doit recevoir l’autorisation Signde clé, l’autorisation Getsecrète et l’autorisation Getde certificat. Pour accorder ces autorisations au principal, utilisez cette commande :

USER_ID=$(az ad signed-in-user show --query id -o tsv)
az keyvault set-policy -n $AKV_NAME --key-permissions sign --secret-permissions get --certificate-permissions get --object-id $USER_ID

Si le certificat ne contient pas la chaîne, le principal doit recevoir l’autorisation de clé Sign et les autorisations de certificat Get. Pour accorder ces autorisations au principal, utilisez cette commande :

USER_ID=$(az ad signed-in-user show --query id -o tsv)
az keyvault set-policy -n $AKV_NAME --key-permissions sign --certificate-permissions get --object-id $USER_ID

Pour en savoir plus sur l’affectation d’une stratégie à un principal, consultez Affecter une stratégie d’accès Key Vault (héritée).

Signer des images conteneur à l’aide du certificat dans Key Vault

  1. Obtenez l’ID de la clé du certificat. Un certificat dans Key Vault peut avoir plusieurs versions. La commande suivante obtient l’ID de clé pour la dernière version du $CERT_NAME certificat :

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv) 
    
  2. Signez l’image du conteneur avec le format de signature CBOR Object Signing and Encryption (COSE) en utilisant l'ID de clé.

    Si le certificat contient l’intégralité de la chaîne de certificats, exécutez la commande suivante :

    notation sign --signature-format cose $IMAGE --id $KEY_ID --plugin azure-kv 
    

    Si le certificat ne contient pas la chaîne, utilisez le --plugin-config ca_certs=<ca_bundle_file> paramètre pour transmettre les certificats d’autorité de certification dans un fichier PEM au plug-in Key Vault. Exécutez la commande suivante:

    notation sign --signature-format cose $IMAGE --id $KEY_ID --plugin azure-kv --plugin-config ca_certs=<ca_bundle_file> 
    

    Pour vous authentifier auprès de Key Vault, par défaut, les types d’informations d’identification suivants (si activé) sont essayés dans l’ordre :

    Si vous souhaitez spécifier un type d’informations d’identification, utilisez une configuration de plug-in supplémentaire appelée credential_type. Par exemple, vous pouvez définir credential_typeazurecli explicitement pour utiliser des informations d’identification Azure CLI, comme illustré dans cet exemple :

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config credential_type=azurecli $IMAGE
    

    Le tableau suivant montre les valeurs de credential_type pour différents types d'informations d'identification.

    Type d'informations d'identification Valeur pour credential_type
    Informations d’identification de l’environnement environment
    Informations d’identification de l’identité de la charge workloadid
    Informations d’identification d’identité managée managedid
    Informations d’identification d’Azure CLI azurecli
  3. Affichez le graphique des images signées et des signatures associées :

    notation ls $IMAGE
    

    Dans l’exemple de sortie suivant, une signature de type application/vnd.cncf.notary.signature identifiée par digest sha256:d7258166ca820f5ab7190247663464f2dcb149df4d1b6c4943dcaac59157de8e est associée à $IMAGE:

    myregistry.azurecr.io/net-monitor@sha256:17cc5dd7dfb8739e19e33e43680e43071f07497ed716814f3ac80bd4aac1b58f
    └── application/vnd.cncf.notary.signature
        └── sha256:d7258166ca820f5ab7190247663464f2dcb149df4d1b6c4943dcaac59157de8e
    

Remarque

Depuis Notation v1.2.0, Notation utilise le schéma de balise referrers OCI pour stocker la signature dans le Registre de Conteneurs par défaut. Vous pouvez également activer l’API OCI Referrers à l’aide de l’indicateur --force-referrers-tag false, si nécessaire. Les fonctionnalités de Container Registry prennent en charge l’API OCI Referrers, à l’exception du Registre chiffré via des clés gérées par le client (CMK).

Vérifier une image conteneur en utilisant l'interface en ligne de commande Notation.

  1. Ajoutez le certificat racine à un magasin de confiance nommé pour la vérification de la signature. Si vous n’avez pas le certificat racine, vous pouvez l’obtenir auprès de votre autorité de certification. L’exemple suivant ajoute le certificat $ROOT_CERT racine au magasin de certificats de confiance $STORE_NAME :

    STORE_TYPE="ca" 
    STORE_NAME="wabbit-networks.io" 
    notation cert add --type $STORE_TYPE --store $STORE_NAME $ROOT_CERT  
    
  2. Listez le certificat racine pour confirmer que le $ROOT_CERT a été ajouté correctement :

    notation cert ls 
    
  3. Configurez une stratégie d’approbation avant la vérification. Les stratégies d’approbation permettent aux utilisateurs de spécifier des stratégies de vérification affinées. Utilisez la commande suivante :

    cat <<EOF > ./trustpolicy.json
    {
        "version": "1.0",
        "trustPolicies": [
            {
                "name": "wabbit-networks-images",
                "registryScopes": [ "$REGISTRY/$REPO" ],
                "signatureVerification": {
                    "level" : "strict" 
                },
                "trustStores": [ "$STORE_TYPE:$STORE_NAME" ],
                "trustedIdentities": [
                    "x509.subject: $CERT_SUBJECT"
                ]
            }
        ]
    }
    EOF
    

    Le fichier précédent trustpolicy.json définit une stratégie d’approbation nommée wabbit-networks-images. Cette stratégie de confiance s’applique à tous les artefacts stockés dans les référentiels $REGISTRY/$REPO. Le magasin de confiance nommé $STORE_NAME de type $STORE_TYPE contient les certificats racines. Cette stratégie suppose également que l’utilisateur fait confiance à une identité spécifique avec le sujet X.509 $CERT_SUBJECT. Pour plus d’informations, consultez la spécification du magasin de confiance et de la politique de confiance.

  4. Utilisez notation policy pour importer la configuration de la politique de confiance à partir de trustpolicy.json.

    notation policy import ./trustpolicy.json
    
  5. Affichez la configuration de la politique de confiance pour vérifier son importation réussie.

    notation policy show
    
  6. Utilisez notation verify pour vérifier l’intégrité de l’image :

    notation verify $IMAGE
    

    Lors de la vérification réussie de l’image via la stratégie d’approbation, la synthèse SHA256 de l’image vérifiée est retournée dans un message de sortie réussi. Voici un exemple de sortie :

    Successfully verified signature for myregistry.azurecr.io/net-monitor@sha256:17cc5dd7dfb8739e19e33e43680e43071f07497ed716814f3ac80bd4aac1b58f

Utiliser l’horodatage

Depuis la version Notation v1.2.0, Notation prend en charge l’horodatage conforme à RFC 3161. Cette amélioration étend la confiance des signatures créées au sein de la période de validité du certificat en faisant confiance à une autorité d’horodatage (TSA). Cette approbation permet une vérification de signature réussie, même après l’expiration des certificats.

En tant que signataire d’image, vous devez veiller à signer les images conteneur avec des horodateurs générés par un TSA de confiance. En tant que vérificateur d’image, vous devez veiller à faire confiance à la fois au signataire de l’image et à au TSA associé, et à établir la confiance par le biais de magasins de confiance et de stratégies d’approbation.

L’horodatage réduit les coûts en éliminant la nécessité de réinscrire régulièrement des images en raison de l’expiration du certificat. Cette capacité est particulièrement critique lorsque vous utilisez des certificats de courte durée. Pour obtenir des instructions détaillées sur la façon de signer et de vérifier des images à l’aide de l’horodatage, reportez-vous au guide d'horodatage du projet Notary.

Questions fréquentes (FAQ)

  • Que dois-je faire si le certificat expire ?

    Si votre certificat expire, vous devez en obtenir un nouveau auprès d’un fournisseur d’autorité de certification approuvé, ainsi qu’une nouvelle clé privée. Vous ne pouvez pas utiliser de certificat expiré pour signer des images conteneur.

    Les images signées avant l’expiration du certificat peuvent toujours être validées correctement si elles ont été signées avec horodatage. Sans horodatage, la vérification de la signature échoue et vous devez réinscrire ces images avec le nouveau certificat pour une vérification réussie.

  • Que dois-je faire si le certificat est révoqué ?

    La révocation de votre certificat invalide la signature. Cette situation peut se produire pour plusieurs raisons, telles que la compromission de la clé privée ou les modifications apportées à l’affiliation du titulaire du certificat.

    Pour résoudre ce problème, vous devez d’abord vous assurer que votre code source et votre environnement de génération sont à jour et sécurisés. Ensuite, générez les images conteneur à partir du code source, obtenez un nouveau certificat auprès d’un fournisseur d’autorité de certification de confiance avec une nouvelle clé privée, puis signez les nouvelles images conteneur avec le nouveau certificat en suivant ce guide.

Notation fournit des solutions d’intégration continue et de livraison continue (CI/CD) sur Azure Pipelines et GitHub Actions.

Pour vous assurer que seules les images conteneur approuvées sont déployées sur Azure Kubernetes Service (AKS) :