Partager via


Signer des images conteneur à l’aide de notation, d’Azure Key Vault et d’un certificat auto-signé

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 d’images conteneur est un processus qui permet de garantir leur authenticité et leur intégrité. Une signature numérique ajoutée à une image conteneur est vérifiée pendant le déploiement. La signature permet de vérifier que l’image provient d’un éditeur approuvé et n’est pas modifiée.

Cet article décrit les outils suivants impliqués dans le processus de signature :

  • 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.

    Si vous souhaitez signer une image conteneur à l’aide de notation dans des pipelines d’intégration continue et de livraison continue (CI/CD), suivez les instructions pour Azure Pipelines ou GitHub Actions.

  • Azure Key Vault est un service permettant de stocker des certificats avec des clés de signature. Le système de notation peut utiliser ces clés via le plug-in Key Vault (notation-azure-kv) pour signer et vérifier des images de conteneur et d’autres artefacts.

  • Azure Container Registry est un registre privé que vous pouvez utiliser pour attacher des signatures à des images conteneur et d’autres artefacts, ainsi que l’affichage de ces signatures.

Dans cet article, vous allez apprendre à :

  • Installez l’interface de ligne de commande Notation (CLI) et le plug-in Key Vault.
  • Créez un certificat auto-signé 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.
  • Validez une image de conteneur par rapport à la signature en utilisant la CLI Notation.
  • Utilisez l’horodatage.

Prérequis

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 binary 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

Pour faciliter l’exécution de commandes dans cet article, fournissez des valeurs pour les ressources Azure afin qu’elles correspondent aux ressources Container Registry et Key Vault existantes.

  1. Configurer les noms de ressources Key Vault :

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    # Name of the existing key vault used to store the signing keys
    AKV_NAME=myakv
    # Name of the certificate created in the key vault
    CERT_NAME=wabbit-networks-io
    CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
    CERT_PATH=./${CERT_NAME}.pem
    
  2. Configurez Container Registry et les noms de ressources d’image :

    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
    IMAGE=$REGISTRY/${REPO}:$TAG
    # 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.

Accorder des autorisations d’accès à Container Registry et 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. Le rôle approprié à utiliser dans l’attribution de rôles varie selon que le registre est activé ou non ABAC.

    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"
    

Autoriser l’accès à Key Vault

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

Les rôles suivants sont requis pour la signature à l’aide de certificats auto-signés :

  • Key Vault Certificates Officer pour la création et la lecture de certificats
  • Key Vault Certificates User pour lire des certificats existants
  • Key Vault Crypto User pour la signature des opérations

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.

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

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

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "Key Vault Certificates Officer" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    

Attribuer une stratégie d’accès dans Key Vault (hérité)

Les autorisations suivantes sont requises pour une identité :

  • Autorisations Create pour la création d’un certificat
  • Autorisations Get pour la lecture de certificats existants
  • Autorisations Sign pour la signature d’opérations

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).

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

    az account set --subscription $AKV_SUB_ID
    
  2. Définissez la stratégie d’accès dans Key Vault :

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

Important

Cet exemple montre les autorisations minimales dont vous avez besoin pour créer un certificat et signer une image conteneur. Selon vos besoins, vous devrez peut-être accorder davantage d’autorisations.

Créer un certificat auto-signé dans Key Vault (Azure CLI)

Les étapes suivantes montrent comment créer un certificat auto-signé à des fins de test :

  1. Créez un fichier de stratégie de certificat

    Une fois que le fichier de stratégie de certificat est exécuté par le biais du code suivant, il crée un certificat valide compatible avec les exigences de certificat du projet notarié dans Key Vault. La valeur de ekus est destinée à la signature de code, mais elle n'est pas nécessaire à la notation pour signer des artefacts. Le sujet est utilisé ultérieurement en tant qu'identité de confiance pendant la vérification.

    cat <<EOF > ./my_policy.json
    {
        "issuerParameters": {
        "certificateTransparency": null,
        "name": "Self"
        },
        "keyProperties": {
          "exportable": false,
          "keySize": 2048,
          "keyType": "RSA",
          "reuseKey": true
        },
        "secretProperties": {
          "contentType": "application/x-pem-file"
        },
        "x509CertificateProperties": {
        "ekus": [
            "1.3.6.1.5.5.7.3.3"
        ],
        "keyUsage": [
            "digitalSignature"
        ],
        "subject": "$CERT_SUBJECT",
        "validityInMonths": 12
        }
    }
    EOF
    
  2. Créez le certificat :

    az keyvault certificate create -n $CERT_NAME --vault-name $AKV_NAME -p @my_policy.json
    

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

  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 des tâches Azure Container Registry. Utilisez toujours la valeur digest pour identifier 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
    
  3. Obtenez l’ID de la clé de signature. Un certificat dans Key Vault peut avoir plusieurs versions. La commande suivante obtient l’ID de clé de la dernière version :

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
    
  4. Signez l'image de conteneur avec le format de signature CBOR Object Signing and Encryption (COSE), à l'aide de l'ID de clé de signature. Pour vous connecter avec un certificat auto-signé, vous devez définir la valeur self_signed=truede configuration du plug-in .

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true $IMAGE
    

    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 self_signed=true --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 de 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

    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).

  5. Affichez le graphique des images signées et des signatures associées :

    notation ls $IMAGE
    

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

Pour vérifier l’image conteneur, ajoutez le certificat racine qui signe le certificat nœud terminal au magasin de confiance, et créez des stratégies de confiance pour vérification. Pour le certificat auto-signé que cet article utilise, le certificat racine est le certificat auto-signé lui-même.

  1. Téléchargez un certificat public :

    az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH
    
  2. Ajoutez le certificat public téléchargé au magasin de confiance nommé pour la vérification des signatures :

    STORE_TYPE="ca"
    STORE_NAME="wabbit-networks.io"
    notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
    
  3. Répertoriez le certificat à confirmer :

    notation cert ls
    
  4. 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. L’exemple suivant configure une stratégie d’approbation nommée wabbit-networks-images. Cette stratégie s’applique à tous les artéfacts dans $REGISTRY/$REPO et utilise le magasin d’approbation appelé $STORE_NAME de type $STORE_TYPE. Il suppose également que l'utilisateur approuve une identité spécifique avec l’objet X.509 $CERT_SUBJECT. Pour plus d’informations, consultez la spécification du magasin de confiance et de la politique de confiance.

    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
    
  5. Utilisez notation policy pour importer la configuration de la politique de confiance à partir du fichier JSON que vous avez créé précédemment :

    notation policy import ./trustpolicy.json
    notation policy show
    
  6. Utilisez notation verify pour vérifier que l'image du conteneur n'a pas été modifiée après le moment de la construction :

    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.

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.

Notation fournit des solutions 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) :