Vérification des signatures d'artefact d'image et non-image
Conservez l'intégrité des images qui sont générées dans le pipeline d'intégration continue (CI) avant le déploiement en vérifiant les signatures d'image.
Avant de commencer
Avant de commencer à utiliser la vérification par image, assurez-vous que les conditions préalables suivantes sont remplies.
- Vous devez disposer de la clé publique GPG. Pour obtenir de l'aide sur la génération de votre clé GPG, voir la documentation.
- Vous devez ajouter la variable d'environnement
code-signing-certificateavec la clé publique GPG codée en base 64. - Vous devez configurer les identifiants du registre pour pouvoir accéder aux images de conteneurs pendant la vérification (voir « Configuration des identifiants du registre »).
Vérification des images
Une nouvelle étape prod-verify-artifact vérifie la signature d'une image dans le pipeline Continuous Delivery (CD). Cette étape effectue les étapes suivantes:
-
Décode la clé publique GPG codée fournie par l'utilisateur dans un fichier temporaire.
-
Crée une règle de conteneur Docker (
/etc/containers/policy.json) avec la clé publique.{ "default": [ { "type": "reject" } ], "transports": { "docker-daemon": { "": [ { "type": "reject" } ] }, "docker": { "": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/tmp/GPGPublicKey" } ] } } } -
Extrait la liste des artefacts pour chaque artefact à l'aide de Skopeo pour extraire l'image avec la règle de conteneur.
skopeo copy docker://"${image}" dir:"${tmp_sign_dir}" --src-creds iamapikey:"${ibmcloud_api_key}"
Si la signature est valide et vérifiée par la clé publique fournie par l'utilisateur, l'extraction d'image aboutit.
Configuration des informations d'identification du registre pour la vérification
Lors de la vérification des signatures des images de conteneurs, le pipeline a besoin d'identifiants pour s'authentifier auprès du registre de conteneurs et accéder aux images signées. Le pipeline « DevSecOps » prend en charge la résolution dynamique des identifiants lors de l'exécution, ce qui vous permet de configurer ces identifiants de différentes manières grâce à des mécanismes de repli automatiques.
Hiérarchie de résolution des informations d'identification
Le pipeline résout dynamiquement les identifiants (nom d'utilisateur et clé API) au moment de l'exécution en suivant la hiérarchie suivante :
Ordre de résolution des clés API :
- Clé API spécifique à l'espace de noms:
signing-token-apikey-{registry}-{namespace}(secret) - Clé API spécifique au registre:
signing-token-apikey-{registry}(secret) - Docker Fichier de configuration JSON:
signing-dockerconfigjson(secret) - Solutions de secours spécifiques à l'ICR:
ciso-ibmcloud-api-key(secret)ibmcloud-api-key(secret)
Ordre de résolution des noms d'utilisateur :
- Nom d'utilisateur spécifique à l'espace de noms:
signing-token-username-{registry}-{namespace}(variable d'environnement) - Nom d'utilisateur spécifique au registre:
signing-token-username-{registry}(variable d'environnement) - Par défaut:
iamapikey(si aucun nom d'utilisateur n'est configuré)
Où :
{registry}est le nom d'hôte du registre (par exemple,us.icr.io,de.icr.io){namespace}correspond au chemin d'accès complet de l'espace de noms, dans lequel les barres obliques et les points ont été remplacés par des traits de soulignement (par exemple,my_namespace_path)
Configuration des identifiants spécifiques à un espace de noms
Pour un contrôle d'accès plus précis, vous pouvez configurer des identifiants spécifiques à un espace de noms du registre :
Clé API (secret): signing-token-apikey-{registry}-{namespace}
Nom d'utilisateur (variable d'environnement): signing-token-username-{registry}-{namespace}
Exemple: pour une image us.icr.io/my-namespace/my-app:latest
- Registre :
us.icr.io - Espace de noms :
my-namespace - Clé secrète de l'API :
signing-token-apikey-us.icr.io-my_namespace - Variable d'environnement « nom d'utilisateur » :
signing-token-username-us.icr.io-my_namespace - Si le nom d'utilisateur n'est pas indiqué, la valeur par défaut est :
iamapikey
Configuration des informations d'identification spécifiques au registre
Pour un accès plus large à l'ensemble des espaces de noms d'un registre :
Clé API (secret): signing-token-apikey-{registry}
Nom d'utilisateur (variable d'environnement): signing-token-username-{registry}
Exemple: pour toute image dans us.icr.io
- Clé secrète de l'API :
signing-token-apikey-us.icr.io - Variable d'environnement « nom d'utilisateur » :
signing-token-username-us.icr.io - Si le nom d'utilisateur n'est pas indiqué, la valeur par défaut est :
iamapikey
Configuration du fichier JSON de configuration d' Docker
Vous pouvez fournir un fichier de configuration JSON de type base64-encoded Docker contenant les identifiants d'accès pour plusieurs registres :
Nom secret: signing-dockerconfigjson
Format: Base64-encoded JSON, conforme au format config.json de Docker:
{
"auths": {
"us.icr.io": {
"username": "iamapikey",
"password": "your-api-key"
},
"us.icr.io/my-namespace": {
"username": "iamapikey",
"password": "namespace-specific-key"
}
}
}
Le pipeline correspond d'abord au chemin le plus spécifique, ce qui permet des remplacements au niveau de l'espace de noms dans la configuration d' Docker.
Exemple de configuration
Pour une image us.icr.io/production/my-app:v1.0.0:
Option 1 : spécifique à l'espace de noms (recommandée pour la production)
- Clé secrète de l'API :
signing-token-apikey-us.icr.io-production=your-namespace-api-key - Variable d'environnement « username » (facultative):
signing-token-username-us.icr.io-production=iamapikey - Si le nom d'utilisateur n'est pas indiqué, la valeur par défaut est
iamapikey
Option 2 : À l'échelle du registre
- Clé secrète de l'API :
signing-token-apikey-us.icr.io=your-registry-api-key - Variable d'environnement « username » (facultative):
signing-token-username-us.icr.io=iamapikey - Si le nom d'utilisateur n'est pas indiqué, la valeur par défaut est
iamapikey
Option 3 : Fichier de configuration JSON d' Docker
- Secret :
signing-dockerconfigjson=base64-encoded-docker-config - Le nom d'utilisateur est extrait du fichier de configuration JSON situé à l'adresse Docker
Option 4 : valeur par défaut de « IBM Cloud » (automatique pour ICR)
- Clé secrète de l'API :
ibmcloud-api-key=your-ibmcloud-api-key - Le nom d'utilisateur par défaut est
iamapikey
Vérification des artefacts autres que des images
Dans les pipelines d' DevSecOps, la signature des artefacts signés fait l'objet d'une vérification. Cette section décrit les prérequis que les utilisateurs doivent respecter avant de procéder à la vérification des artefacts.
Avant de commencer
Avant de pouvoir utiliser la vérification d'image, vérifiez que vous disposez des prérequis suivants.
-
Modifiez la configuration de votre pipeline pour activer le processus de vérification. Ajoutez l'extrait de code suivant à votre fichier
.pipeline-config.yaml.verify-artifact: image: icr.io/continuous-delivery/pipeline/image-signing:1.0.0@sha256:e9d8e354668ba3d40be2aaee08298d2aa7f0e1c8a1829cca4094ec93830e3e6a image_pull_policy: IfNotPresent abort_on_failure: false dind: true script: | #!/usr/bin/env bash source /opt/commons/verify-artifact/verify_non_image_artifact.sh -
Téléchargez l'artefact et stockez-le dans l'environnement d'exécution du pipeline.
Avant d'appeler l'étape
verify-artifact, téléchargez et stockez les artefacts requis dans l'environnement d'exécution Cocoa. Par défaut, tous les artefacts répertoriés dans la collection «list_artifacts» sont vérifiés. Utilisez la propriété de texte «skip-sign-artifact-type» pour ignorer la vérification de la signature des images pour les types d'artefacts indiqués (par exemple : log; report; documentation). L'exemple de code suivant montre comment télécharger un artefact depuis Cloud Object Storage et l'enregistrer dans l'environnement d'exécution Cocoa :#!/usr/bin/env bash export SECRET_PATH="/config/ibmcloud-api-key" . "${ONE_PIPELINE_PATH}"/iam/get_token SKIP_SIGN_ARTIFACTS_TYPE="$(get_env skip-sign-artifact-type "")" IFS=';' read -ra ARTIFACT_LIST <<<"$SKIP_SIGN_ARTIFACTS_TYPE" list_artifacts | while IFS= read -r artifact; do type="$(load_artifact "$artifact" "type")" if [[ ! "${ARTIFACT_LIST[@]}" =~ "$type" ]] && [[ "$type" != "image" ]]; then inventory_entry="$(load_artifact "$artifact" "inventory-entry")" inventory_entry=${inventory_entry///artifacts/$WORKSPACE} artifact_url=$(jq -r .'app_artifacts.artifact_url' ${inventory_entry}) echo "downloading the artifact ${artifact_url}" curl -H "Authorization: bearer ${IAM_ACCESS_TOKEN}" --output outputfile ${artifact_url} save_file "${artifact}" outputfile fi done
Vérification des artefacts
Dans le processus de vérification d'artefact, la clé publique GPG fournie par l'utilisateur est importée dans le fichier de clés GPG. Tous les artefacts répertoriés dans la collection list_artifacts seront vérifiés. L'étape tente
d'extraire la signature de l'inventaire et effectue la vérification suivante:
gpg --verify "${signature}" "${artifactName}"
Si la signature est valide et vérifiée à l'aide de la clé publique fournie, l'étape enregistre les preuves et marque l'étape comme réussie.