Contactez-nous

Utiliser le gestionnaire de "Credentials" pour les informations sensibles

Apprenez à utiliser le gestionnaire de Credentials de Jenkins pour stocker et utiliser de manière sécurisée mots de passe, tokens API, et clés SSH dans vos pipelines CI/CD.

La gestion des secrets : un enjeu majeur pour la sécurité de vos pipelines

Dans tout système d'automatisation, et particulièrement dans les pipelines d'intégration et de déploiement continus (CI/CD) gérés par Jenkins, la manipulation d'informations sensibles est une occurrence fréquente. Qu'il s'agisse de mots de passe pour se connecter à des bases de données, de tokens d'accès pour interagir avec des APIs tierces (comme GitHub, Docker Hub, AWS, Azure), de clés SSH pour se connecter à des serveurs distants, ou de certificats pour sécuriser des communications, ces secrets sont les clés de vos infrastructures et applications. Les exposer par inadvertance constitue un risque de sécurité majeur.

La pire pratique, malheureusement encore parfois rencontrée, consiste à coder en dur ces informations sensibles directement dans les scripts de pipeline (`Jenkinsfile`) ou dans la configuration des Jobs. Cela rend les secrets visibles à quiconque ayant accès au code source ou à la configuration Jenkins, les expose dans les logs si des commandes les affichent, et les rend difficiles à gérer et à renouveler. Jenkins propose une solution intégrée et robuste pour pallier ce problème : le gestionnaire de Credentials (ou Identifiants).

Ce chapitre est dédié à l'exploration de cette fonctionnalité cruciale. Nous verrons comment ajouter, gérer et utiliser différents types de credentials de manière sécurisée dans vos pipelines Jenkins, assurant ainsi que vos secrets restent secrets, tout en étant accessibles de manière contrôlée par vos processus d'automatisation.

Principes et avantages du gestionnaire de Credentials Jenkins

Le gestionnaire de Credentials de Jenkins est un système centralisé conçu pour stocker de manière sécurisée les informations sensibles nécessaires à vos pipelines. Au lieu d'insérer directement un mot de passe ou un token dans un script, vous l'enregistrez une fois dans Jenkins sous un identifiant unique (ID de credential). Ensuite, dans vos pipelines, vous faites référence à cet ID. Jenkins se charge alors d'injecter la valeur réelle du secret au moment de l'exécution du build, de manière sécurisée et souvent sans l'exposer directement dans les logs (selon la méthode d'injection).

Les principaux avantages de cette approche sont :

  • Sécurité renforcée : Les secrets ne sont plus stockés en clair dans les `Jenkinsfiles` ou les configurations de jobs. Jenkins les stocke de manière chiffrée sur le disque (le niveau de chiffrement peut varier).
  • Gestion centralisée : Tous les secrets sont gérés à un seul endroit, ce qui facilite leur audit, leur mise à jour et leur révocation. Si un mot de passe doit être changé, vous ne le modifiez qu'une fois dans le gestionnaire de credentials, et tous les pipelines utilisant cet ID bénéficieront de la mise à jour.
  • Contrôle d'accès : Les credentials peuvent être définis à différents niveaux (scopes) : globaux (accessibles par tous les Jobs), ou limités à des dossiers spécifiques ou même à des Jobs individuels. Cela permet d'appliquer le principe du moindre privilège.
  • Masquage dans les logs : Jenkins et de nombreux plugins s'efforcent de masquer automatiquement les valeurs des secrets injectés s'ils apparaissent dans la sortie console des builds, bien que cela ne soit pas infaillible à 100% et dépende de la manière dont le secret est utilisé.
  • Intégration avec les plugins : De nombreux plugins Jenkins (pour Git, Docker, Artifactory, les fournisseurs cloud, etc.) sont conçus pour s'intégrer nativement avec le gestionnaire de credentials.

L'utilisation du gestionnaire de credentials est une pratique fondamentale et non négociable pour toute instance Jenkins gérant des informations sensibles. C'est la première ligne de défense pour protéger l'accès à vos systèmes.

Les différents types de Credentials et comment les ajouter

Jenkins supporte nativement plusieurs types de credentials pour couvrir une large gamme de besoins. Pour ajouter un credential, vous devez généralement aller dans "Manage Jenkins" > "Manage Credentials". Vous verrez alors les "Stores" (magasins de credentials, souvent un global et potentiellement d'autres liés à des plugins) et les "Domains" (par défaut, le domaine global `_`). Cliquez sur un store (ex: "Jenkins") puis sur "Global credentials (unrestricted)" ou un domaine spécifique, et enfin sur "Add Credentials" sur la gauche.

Voici les types de credentials les plus courants :

1. Username with password :

  • Usage : Pour les authentifications classiques nécessitant un nom d'utilisateur et un mot de passe (accès à un SCM, un gestionnaire d'artefacts, une base de données, etc.).
  • Champs : `Username`, `Password`, `ID` (un identifiant unique que vous choisissez, ex: `mon-compte-artifactory`), `Description` (optionnelle mais recommandée).

2. SSH Username with private key :

  • Usage : Pour l'authentification SSH sans mot de passe, en utilisant une clé privée. Très courant pour se connecter à des serveurs distants ou pour cloner/pousser des dépôts Git via SSH.
  • Champs : `Username` (l'utilisateur sur le serveur distant, ex: `git` ou `jenkins-agent`), `Private Key` (vous pouvez entrer la clé directement, la charger depuis un fichier, ou laisser Jenkins en générer une), `Passphrase` (si votre clé privée est protégée par une passphrase), `ID`, `Description`.

3. Secret text :

  • Usage : Pour stocker des chaînes de caractères secrètes arbitraires, comme des tokens d'API (GitHub API token, Slack token, AWS secret access key, etc.).
  • Champs : `Secret` (la valeur du token ou du secret), `ID`, `Description`.

4. Secret file :

  • Usage : Pour stocker des fichiers entiers qui sont considérés comme secrets (par exemple, un fichier `kubeconfig` pour Kubernetes, un fichier `settings.xml` pour Maven contenant des mots de passe, un fichier de licence).
  • Champs : `File` (téléchargez le fichier), `ID`, `Description`.

5. Certificate :

  • Usage : Pour les certificats clients au format PKCS#12, souvent utilisés pour l'authentification mutuelle TLS.
  • Champs : `Upload PKCS#12 certificate`, `Password` (du fichier PKCS#12), `ID`, `Description`.

Il existe d'autres types de credentials qui peuvent être ajoutés par des plugins spécifiques (par exemple, pour AWS, Azure, Google Cloud). Lors de la création, choisissez un `ID` clair et mémorable, car c'est cet ID que vous utiliserez dans vos `Jenkinsfiles`.

Utiliser les Credentials dans un Jenkinsfile Déclaratif

Une fois vos credentials enregistrés dans Jenkins, vous pouvez les utiliser de manière sécurisée dans vos pipelines Déclaratifs. Il existe principalement deux façons de le faire : en les injectant comme variables d'environnement ou en utilisant le wrapper `withCredentials`.

1. Injection comme variables d'environnement :

Vous pouvez utiliser la directive `environment` au niveau du `pipeline` ou d'un `stage` pour lier un credential à une variable d'environnement. Le helper `credentials()` est utilisé pour cela. La variable contiendra alors la valeur du secret.

pipeline {
    agent any
    environment {
        // Pour un 'Secret text' ou le mot de passe d'un 'Username with password'
        MY_API_TOKEN = credentials('id-de-mon-api-token')
        // Pour un 'Username with password', Jenkins définit plusieurs variables :
        // MYAPP_USERPASS_USR contiendra le username
        // MYAPP_USERPASS_PSW contiendra le password
        // MYAPP_USERPASS (si le credential est de type username/password) est souvent la concaténation user:pass pour basic auth
        MYAPP_USERPASS = credentials('id-username-password') 
    }
    stages {
        stage('Utiliser API Token') {
            steps {
                sh 'curl -H "Authorization: Bearer ${MY_API_TOKEN}" https://api.example.com/data'
            }
        }
        stage('Utiliser Username/Password') {
            steps {
                // Si MYAPP_USERPASS_PSW est défini (ce qui est le cas avec le helper credentials() pour un type username/password)
                sh 'echo "Utilisateur: ${env.MYAPP_USERPASS_USR}, Mot de passe: [MASQUE]"' // Le mot de passe ne sera pas affiché directement
                sh 'login_tool --username ${MYAPP_USERPASS_USR} --password ${MYAPP_USERPASS_PSW}'
            }
        }
    }
}
2. Utilisation du wrapper `withCredentials` :

Le step `withCredentials` est plus flexible et souvent préféré, surtout pour les credentials de type fichier secret ou clé SSH. Il rend le secret disponible uniquement dans la portée du bloc `withCredentials`. Pour les fichiers secrets, il les copie dans un emplacement temporaire et fournit le chemin dans une variable. Pour les clés SSH, il peut gérer la configuration de l'agent SSH.

pipeline {
    agent any
    stages {
        stage('Déployer avec clé SSH') {
            steps {
                withCredentials([sshUserPrivateKey(credentialsId: 'ma-cle-ssh-deploy',
                                                    keyFileVariable: 'KEYFILE_PATH',
                                                    passphraseVariable: 'KEYFILE_PASSPHRASE', // Optionnel
                                                    usernameVariable: 'SSH_USERNAME')]) {
                    // KEYFILE_PATH contient le chemin vers un fichier temporaire contenant la clé privée
                    // SSH_USERNAME contient le nom d'utilisateur associé
                    // KEYFILE_PASSPHRASE contient la passphrase (si définie)
                    sh 'echo "Connexion en tant que ${SSH_USERNAME} avec la clé ${KEYFILE_PATH}"'
                    sh "scp -i ${KEYFILE_PATH} monfichier.zip ${SSH_USERNAME}@serveur.example.com:/opt/deploy/"
                }
                // En dehors de ce bloc, KEYFILE_PATH, SSH_USERNAME ne sont plus définis.
                // Le fichier temporaire de la clé est supprimé.
            }
        }
        stage('Utiliser un fichier secret') {
            steps {
                withCredentials([file(credentialsId: 'mon-fichier-kubeconfig', variable: 'KUBECONFIG_FILE')]) {
                    // KUBECONFIG_FILE contient le chemin vers une copie temporaire du fichier secret
                    sh 'export KUBECONFIG=${KUBECONFIG_FILE} && kubectl get pods'
                }
            }
        }
        stage('Utiliser un Secret Text dans withCredentials') {
            steps {
                withCredentials([string(credentialsId: 'mon-token-api-specifique', variable: 'TOKEN_POUR_CE_STEP')]) {
                    sh 'outil_specifique --token ${TOKEN_POUR_CE_STEP}'
                }
            }
        }
    }
}

Dans le cas de `sshUserPrivateKey`, Jenkins peut également configurer automatiquement l'agent SSH pour utiliser la clé fournie si vous utilisez des commandes comme `ssh` ou `scp` qui respectent la configuration de l'agent SSH standard. L'utilisation de `withCredentials` est généralement considérée comme plus sécurisée car elle limite la portée et la durée de vie de l'exposition du secret.

En résumé, l'utilisation systématique et correcte du gestionnaire de Credentials est un pilier de la sécurité de vos opérations CI/CD avec Jenkins. Prenez le temps de bien configurer vos secrets et de les utiliser de la manière la plus appropriée dans vos pipelines.