Aller au contenu principal
JenkinsCI/CDDevOps

Jenkins #7 — Sécurité : RBAC, Credentials, Audit Trail et Hardening

30 min de lecture Jenkins — Chapitre 7

Sécurise ton Jenkins comme un pro : RBAC avec Matrix Auth et Role Strategy, gestion avancée des credentials, audit trail et hardening complet.

Un Jenkins compromis, c’est potentiellement tout ton SI qui tombe. Il a accès au code source, aux secrets, à l’infrastructure, aux déploiements. C’est une cible de choix pour un attaquant — et pourtant, la majorité des installations Jenkins en entreprise ont des failles de sécurité béantes.

Ce cours couvre les quatre piliers de la sécurité Jenkins : authentification, autorisation RBAC, gestion des credentials, et hardening complet.

Authentification — qui peut se connecter

Le Security Realm définit comment les utilisateurs s’authentifient. Trois options selon la taille de l’organisation.

Jenkins interne — pour les petites équipes. Jenkins gère ses propres utilisateurs. Simple mais pas scalable au-delà de 10-15 personnes.

LDAP / Active Directory — pour les entreprises. Centralise l’authentification avec l’annuaire existant. Les groupes LDAP deviennent directement utilisables dans les règles RBAC.

OIDC / SAML — pour le SSO. Keycloak, Okta, Google Workspace. La solution moderne qui unifie l’authentification avec le reste de l’outillage.

# JCasC — authentification OIDC avec Keycloak
jenkins:
  securityRealm:
    oic:
      clientId: "${OIDC_CLIENT_ID}"
      clientSecret: "${OIDC_CLIENT_SECRET}"
      wellKnownOpenIDConfigurationUrl: "https://keycloak.example.com/realms/jenkins/.well-known/openid-configuration"
      userNameField: "preferred_username"
      groupsFieldName: "groups"
      scopes: "openid profile email"

💡 Recommandation : OIDC avec Keycloak ou Okta. Tu bénéficies du MFA, de la gestion centralisée des comptes, et de la révocation instantanée quand quelqu’un quitte l’entreprise. L’authentification interne Jenkins, c’est un plan B, jamais un plan A en production.

⚠️ Piège classique : laisser “Allow users to sign up” activé avec l’authentification interne. N’importe qui peut se créer un compte sur ton Jenkins.

Autorisation RBAC — qui peut faire quoi

Jenkins offre plusieurs stratégies d’autorisation, de la plus simple à la plus granulaire.

Matrix Authorization

Le plugin matrix-auth définit des permissions par utilisateur ou groupe. Idéal pour un Jenkins avec 2-3 équipes :

# JCasC — Matrix Authorization
jenkins:
  authorizationStrategy:
    globalMatrix:
      permissions:
        - "Overall/Administer:admin"
        - "Overall/Read:developers"
        - "Job/Build:developers"
        - "Job/Read:developers"
        - "Job/Workspace:developers"
        - "Run/Replay:developers"
        - "View/Read:developers"
        - "Overall/Read:viewers"
        - "Job/Read:viewers"
        - "View/Read:viewers"

Role-Based Strategy

Le plugin role-strategy est plus flexible pour les gros Jenkins. Il combine des rôles globaux avec des rôles par projet, filtrés par pattern regex :

jenkins:
  authorizationStrategy:
    roleBased:
      roles:
        global:
          - name: "admin"
            permissions: ["Overall/Administer"]
            entries:
              - group: "jenkins-admins"
          - name: "developer"
            permissions:
              - "Overall/Read"
              - "Job/Build"
              - "Job/Read"
              - "Job/Workspace"
              - "Run/Replay"
            entries:
              - group: "developers"
        items:
          - name: "team-a-full"
            pattern: "team-a/.*"
            permissions: ["Job/Build", "Job/Configure", "Job/Read"]
            entries:
              - group: "team-a"

🎯 Organisation par dossiers : structure tes jobs en dossiers par équipe (team-a/, team-b/, infrastructure/). Combine avec les rôles items pour que chaque équipe n’accède qu’à ses propres projets. Le credential scoping par dossier isole automatiquement les secrets.

Gestion avancée des credentials

Chaque secret doit passer par le store de credentials Jenkins — jamais en clair dans un script ou une variable d’environnement système.

Hiérarchie et isolation

Les credentials suivent une hiérarchie : SystemGlobalFolder. Un credential défini dans le dossier team-a/ est invisible pour les jobs de team-b/. Cette isolation par scope est ta première ligne de défense.

# JCasC — credentials par type
credentials:
  system:
    domainCredentials:
      - credentials:
          - basicSSHUserPrivateKey:
              scope: GLOBAL
              id: "github-ssh"
              username: "git"
              privateKeySource:
                directEntry:
                  privateKey: "${SSH_PRIVATE_KEY}"
          - string:
              scope: GLOBAL
              id: "sonar-token"
              secret: "${SONAR_TOKEN}"
          - usernamePassword:
              scope: GLOBAL
              id: "docker-registry"
              username: "${DOCKER_USER}"
              password: "${DOCKER_PASS}"

Masking et fuites

Jenkins masque automatiquement les credentials dans les logs. Mais plusieurs patterns les exposent quand même :

// ❌ DANGER — fuites de secrets
sh 'env | sort'         // Affiche tout l'environnement
sh 'set -x'             // Mode debug = secrets visibles en clair
sh 'echo $SECRET_VAR'   // Peut échapper au masking

// ✅ SAFE — toujours set +x dans les scripts sensibles
withCredentials([string(credentialsId: 'token', variable: 'TOKEN')]) {
    sh '''
        set +x
        curl -sS -H "Authorization: Bearer $TOKEN" https://api.example.com
    '''
}

🔥 HashiCorp Vault : pour les organisations matures, intègre Vault avec le plugin hashicorp-vault-plugin. Les secrets sont gérés centralement, avec rotation automatique, audit trail natif, et révocation granulaire. Jenkins ne stocke plus que le token d’accès Vault.

⚠️ Rotation : audite régulièrement tes credentials avec un script Groovy dans la Script Console. Identifie ceux qui n’ont pas de description, pas de scope restreint, ou qui ne sont utilisés par aucun job. Un credential orphelin est un vecteur d’attaque silencieux.

Audit Trail et traçabilité

Le plugin Audit Trail enregistre toutes les actions administratives : qui a modifié un job, qui a lancé un build, qui a accédé aux credentials.

# JCasC — Audit Trail
unclassified:
  audit-trail:
    logBuildCause: true
    pattern: ".*/(?:configSubmit|doDelete|postBuildResult|enable|disable|cancelQueue|stop|toggleLogKeep|createItem)"
    loggers:
      - syslog:
          syslogServerHostname: "syslog.example.com"
          syslogServerPort: 514
          appName: "jenkins"
      - file:
          log: "/var/log/jenkins/audit.log"
          limit: 100
          count: 10

Pour les déploiements, ajoute un log structuré dans le pipeline lui-même. Chaque déploiement en production doit tracer qui l’a déclenché, quelle version, et vers quel environnement. Envoie ces events vers un système centralisé — ELK, Datadog, ou un simple webhook.

💡 La Script Console est l’outil le plus puissant ET le plus dangereux de Jenkins. Elle donne un accès Groovy complet au système. En production, restreins-la aux super-admins uniquement — sépare le rôle Overall/Administer du rôle Overall/RunScripts.

Hardening — les mesures concrètes

Huit mesures de hardening à appliquer sur toute installation Jenkins en production.

Zéro executor sur le controller — le controller orchestre, les agents exécutent. Un build lourd sur le controller peut crasher toute l’instance. Configure numExecutors: 0 dans JCasC.

CSRF Protection — activée par défaut, mais vérifie que personne ne l’a désactivée. Le crumb issuer protège contre les requêtes cross-site forgées.

HTTPS obligatoire — termine le TLS au reverse proxy (nginx/Traefik). Ajoute les headers de sécurité : X-Content-Type-Options, X-Frame-Options: DENY, Strict-Transport-Security.

Réseau restreint — le port 8080 ne doit jamais être exposé sur Internet. Firewall strict : accès limité au réseau interne, port 50000 uniquement pour les agents.

# Firewall — seuls les ports nécessaires
sudo ufw default deny incoming
sudo ufw allow from 10.0.0.0/8 to any port 8080   # Réseau interne
sudo ufw allow from 10.0.0.0/8 to any port 50000   # Agents JNLP
sudo ufw enable

Sandbox Groovy — les Jenkinsfile s’exécutent dans une sandbox par défaut. Ne valide jamais aveuglément les scripts en attente dans In-process Script Approval. Lis le code avant d’approuver.

Plugins à jour — vérifie les vulnérabilités connues régulièrement. Ne fais pas Update All — mets à jour un par un et teste entre chaque.

Network Policies K8s — si Jenkins tourne sur Kubernetes, isole les pods agents. Ils ne doivent communiquer qu’avec le controller, le DNS et les registres Docker. Tout le reste est bloqué.

API tokens — force l’utilisation d’API tokens au lieu des mots de passe pour l’API REST. Les tokens sont révocables individuellement et n’exposent pas le mot de passe principal.

Checklist et résumé

🎯 Checklist de sécurité Jenkins — vérifie ces 12 points sur ton installation :

  • Authentification configurée (jamais “Anyone can do anything”)
  • RBAC avec principe du moindre privilège
  • 0 executors sur le controller
  • CSRF Protection activée
  • Script Console restreinte aux super-admins
  • Plugins à jour, pas de vulnérabilités connues
  • HTTPS obligatoire avec headers de sécurité
  • Credentials dans le store Jenkins, jamais en clair
  • Audit Trail activé et centralisé
  • Accès réseau limité (firewall / NetworkPolicy)
  • Sandbox Groovy activée pour les pipelines
  • Rotation régulière des credentials

La sécurité Jenkins n’est pas un projet one-shot — c’est un processus continu. Chaque nouveau plugin, chaque nouveau pipeline, chaque nouvel utilisateur est une surface d’attaque potentielle. La checklist ci-dessus devrait être auditée trimestriellement, pas juste cochée à l’installation.

⚠️ La vérité qui fait mal : la majorité des incidents de sécurité Jenkins ne viennent pas d’attaques sophistiquées. Ils viennent d’un set -x qui expose un token, d’un credential en scope Global au lieu de Folder, ou d’un plugin abandonné avec une CVE connue. Les bases bien faites protègent contre 95% des risques.

🖥️ Pratique sur ton propre serveur

Pour suivre Jenkins en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés