Meilleures pratiques pour la gestion sécurisée des identifiants Jenkins

Stockez les secrets Jenkins en toute sécurité avec le plugin Credentials, la portée des dossiers, withCredentials, RBAC, la rotation et les coffres externes.

Meilleures pratiques pour la gestion sécurisée des identifiants Jenkins

Les tâches Jenkins nécessitent souvent des secrets proches de la production : jetons cloud, mots de passe de registre, clés de déploiement, certificats de signature et identifiants API. Si ces secrets se retrouvent dans un Jenkinsfile, un journal de console ou un paramètre de tâche, votre système CI/CD devient un chemin direct vers la compromission.

Utilisez le plugin Credentials, gardez les identifiants avec une portée étroite et injectez-les uniquement pour l'étape qui en a besoin.

Les bases : le plugin Jenkins Credentials

Le plugin Credentials est le mécanisme standard que Jenkins utilise pour stocker les données sensibles. Il fournit un référentiel centralisé et crypté pour les identifiants, garantissant que les secrets ne sont jamais exposés dans les journaux de construction, le contrôle de source ou les fichiers de configuration.

Lorsque Jenkins stocke des identifiants, il les crypte en utilisant du matériel de clé sur le contrôleur Jenkins, y compris les fichiers sous JENKINS_HOME/secrets. Toute personne ayant un accès large au système de fichiers du contrôleur et à la configuration de Jenkins peut potentiellement récupérer les secrets, donc l'accès au système de fichiers et à l'administrateur doit être strictement contrôlé.

Types d'identifiants clés

Comprendre les types d'identifiants disponibles est la première étape vers une implémentation sécurisée. Choisissez le type qui correspond le plus précisément au secret stocké :

  1. Texte secret : Utilisé pour des valeurs de texte courtes et génériques telles que les jetons API, les clés d'accès, les jetons OAuth ou les secrets de webhook.
  2. Nom d'utilisateur et mot de passe : Paire standard utilisée pour l'authentification contre des services comme les dépôts Maven, les registres privés (Docker Hub, Artifactory) ou les applications internes.
  3. Nom d'utilisateur SSH avec clé privée : Essentiel pour accéder aux agents distants, cloner des dépôts Git privés ou exécuter des commandes sur une infrastructure distante. La clé privée peut être saisie directement, fournie sous forme de chemin ou gérée par le contrôleur Jenkins.
  4. Fichier secret : Utilisé pour télécharger des fichiers entiers qui sont sensibles, tels que des trousseaux de clés, des certificats (.pem, .crt) ou des fichiers de configuration contenant des secrets.

Astuce : Utilisez toujours le type d'identifiant le plus granulaire possible. Par exemple, si vous avez seulement besoin d'une clé API, utilisez Texte secret plutôt que d'essayer de l'intégrer dans un champ Nom d'utilisateur et mot de passe.

Principe du moindre privilège : définition de la portée des identifiants

La portée des identifiants détermine où ils sont accessibles dans l'environnement Jenkins. Appliquer le principe du moindre privilège—n'accorder que l'accès nécessaire à la tâche—est crucial.

1. Portée système

Les identifiants avec portée système (stockés sous Gérer Jenkins > Gérer les identifiants > Jenkins) sont disponibles globalement pour toutes les tâches, dossiers et pipelines sur l'instance Jenkins.

  • Utilisation : Utilisez la portée système uniquement pour les secrets nécessaires à l'ensemble de l'opération Jenkins, tels que les identifiants utilisés par les plugins de configuration globale ou les secrets nécessaires pour toutes les connexions d'agents.
  • Avertissement : Minimisez l'utilisation de la portée système. Toute tâche compromise pourrait potentiellement accéder à tous les secrets globalement disponibles.

2. Portée dossier

Les identifiants avec portée dossier sont définis dans un dossier spécifique (créé à l'aide du plugin Folder ou via des dossiers d'organisation). Ces secrets ne sont visibles et utilisables que par les tâches résidant dans ce dossier et ses sous-dossiers.

  • Recommandation : Préférez toujours la portée dossier. Cela compartimente l'accès et limite le rayon d'explosion si un projet est compromis.

Injection sécurisée dans les pipelines déclaratifs

Ne codez pas en dur les identifiants dans les scripts de pipeline. Les variables d'environnement sont acceptables uniquement lorsque Jenkins les injecte pour un bloc étroit et masque les valeurs de secret connues dans les journaux.

La méthode sécurisée pour accéder aux identifiants dans un pipeline déclaratif consiste à utiliser l'étape intégrée withCredentials. Cette étape charge l'identifiant spécifié dans une variable d'environnement avec portée qui n'est disponible que pendant l'exécution du bloc.

Exemple 1 : Injection de texte secret (jeton API)

Cet exemple récupère de manière sécurisée un identifiant de texte secret (MY_API_TOKEN) et attribue sa valeur à la variable interne SECRET_TOKEN. Une fois le bloc withCredentials terminé, SECRET_TOKEN est automatiquement supprimé de l'environnement.

pipeline {
    agent any
    stages {
        stage('Déploiement via API') {
            steps {
                script {
                    withCredentials([string(credentialsId: 'MY_API_TOKEN', variable: 'SECRET_TOKEN')]) {
                        sh "echo 'Appel de l\'API externe...'"
                        sh '''
                            curl -X POST \
                              -H "Authorization: Bearer $SECRET_TOKEN" \
                              https://api.mycorp.com/deploy
                        '''
                    }
                }
            }
        }
    }
}

Exemple 2 : Injection de nom d'utilisateur et mot de passe

Lors de l'utilisation d'identifiants de type nom d'utilisateur et mot de passe, l'étape withCredentials divise le secret en deux variables : une pour le nom d'utilisateur et une pour le mot de passe, généralement suffixées par _USR et _PSW (ou des noms personnalisés).

pipeline {
    agent any
    stages {
        stage('Connexion au registre') {
            steps {
                withCredentials([usernamePassword(credentialsId: 'DOCKER_REGISTRY_CRED', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {
                    sh '''
                        printf '%s' "$DOCKER_PASS" | docker login \
                          --username "$DOCKER_USER" \
                          --password-stdin my.registry.com
                    '''
                }
            }
        }
    }
}

Avertissement de sécurité : Suppression des journaux

Jenkins tente de masquer les valeurs d'identifiants connues dans les journaux de construction, mais le masquage ne remplace pas des scripts prudents. N'imprimez pas les secrets, ne passez pas les mots de passe en ligne de commande et n'exécutez pas le traçage de shell (set -x) autour de l'utilisation de secrets.

Intégration de sécurité avancée

Pour les environnements à haute sécurité, se fier uniquement à la clé maître locale de Jenkins est souvent insuffisant. L'intégration avec un système de gestion de secrets externe fournit une séparation des préoccupations, une audit centralisé et des capacités de cryptage améliorées.

Magasins d'identifiants externes

Les intégrations populaires incluent :

  • HashiCorp Vault : En utilisant le plugin Vault, Jenkins peut demander dynamiquement des secrets à Vault au moment de l'exécution. Cela signifie que les secrets ne sont jamais stockés en permanence sur le contrôleur Jenkins, seulement temporairement en mémoire pendant la phase d'exécution.
  • AWS Secrets Manager/Azure Key Vault : Les plugins natifs du cloud permettent aux pipelines de récupérer des secrets directement depuis ces services en utilisant des rôles IAM ou des principaux de service, minimisant l'exposition statique des identifiants.

L'utilisation de magasins externes s'aligne sur les meilleures pratiques de sécurité en :

  1. Séparant le stockage : L'infrastructure des secrets est découplée du serveur CI/CD.
  2. Accès dynamique : Les secrets peuvent être rotés fréquemment sans nécessiter de mises à jour manuelles de la configuration Jenkins.
  3. Audit amélioré : Toutes les tentatives d'accès aux secrets sont journalisées dans le système de coffre externe.

Contrôle d'accès basé sur les rôles (RBAC)

L'implémentation d'un plugin RBAC (comme la stratégie d'autorisation basée sur les rôles) permet aux administrateurs de contrôler non seulement qui peut exécuter une tâche, mais aussi qui peut configurer et voir des identifiants spécifiques.

  • Restreignez les permissions de configuration des tâches afin que seuls les utilisateurs de confiance puissent lier des identifiants dans les pipelines.
  • Restreignez la capacité de modifier ou de créer des identifiants au niveau système à un petit groupe d'administrateurs de sécurité ou de plateforme.

Meilleures pratiques de gestion des identifiants

Pratique Description Avantage de sécurité
Utiliser la portée dossier Limiter l'accès aux identifiants aux tâches/dossiers spécifiques qui en ont besoin. Limite l'exposition et le rayon d'explosion.
Éviter le codage en dur Ne jamais placer de secrets dans Jenkinsfile, scripts de construction ou contrôle de source. Élimine la vulnérabilité du code source.
Utiliser withCredentials Injecter les secrets de manière sécurisée dans les étapes du pipeline en utilisant l'API officielle de Jenkins. Assure la rédaction automatique des journaux et le nettoyage de l'environnement.
Intégrer un coffre externe Utiliser Vault, AWS Secrets Manager ou Azure Key Vault pour les déploiements d'entreprise. Découple le stockage et permet la rotation dynamique.
Appliquer RBAC Utiliser des plugins d'autorisation pour restreindre qui peut configurer, voir et utiliser les identifiants. Applique le principe du moindre privilège parmi les utilisateurs.
Rotation régulière Faire tourner les clés API et les mots de passe régulièrement (idéalement automatisé via un coffre externe). Minimise la fenêtre de temps pour que les secrets compromis soient exploités.
Sécuriser le contrôleur Assurer des permissions strictes sur le système de fichiers du contrôleur Jenkins pour protéger master.key. Protège le mécanisme de cryptage central.

Traitez les identifiants Jenkins comme des secrets de production. Limitez leur portée étroitement, liez-les brièvement, faites-les tourner régulièrement et maintenez l'accès au contrôleur limité aux personnes autorisées à récupérer ces secrets.