Il ne me paraît pas nécessaire de présenter en détails Jenkins tant ce logiciel est un des habitués du milieu de l’intégration continue dans l’informatique. Lorsqu’on est une structure ayant plusieurs équipes et que l’instance Jenkins est mutualisée, on peut rapidement avoir envie de les séparer au sein d’un espace qui leur est dédié dans Jenkins pour garantir que celles-ci aient bien leur propre bac à sable et ne puissent toucher aux jobs ou paramètres d’une autre.

C’est dans ces cas là que la gestion d’habilitation de Jenkins prend tout son intérêt, mais celle-ci n’est pas forcément simple à appréhender. Je vous propose un petit tutoriel pour interfacer Jenkins avec un Identity Provider (IDP) qui permettra de gérer l’authentification et l’habilitation des utilisateurs.

Le besoin

Imaginons que nous sommes dans une structure ayant plusieurs équipes de développement utilisant chacune un Jenkins mutualisé. Ce Jenkins est administré par une équipe proposant les outils CI:CD à destination des équipes projets et opérationnelles.

Les équipes projets comprennent les développeurs et intégrateurs qui auront besoin de créer des jobs d’intégration continue pour construire leurs applications et les déployer sur les environnements de test. Les équipes projet ont, de préférence, un espace dédié pour isoler leurs jobs.

Les équipes opérationnelles comprennent les administrateurs des environnements qui peuvent lancer des jobs de déploiement sur ceux-ci, mais n’ont pas forcément besoin de pouvoir modifier ou créer des jobs. Etant transverse, l’équipe opérationnelle devrait avoir accès à tous les jobs de déploiement applicatif.

Enfin, l’équipe en charge du maintien de l’instance Jenkins est là pour administrer l’application et a donc besoin de droits avancés.

Nous pouvons alors imaginer la matrice suivante :

Equipe Droits
Admins Jenkins Admin
Projet A Accès écriture et exécution sur le dossier Projet A
Projet B Accès écriture et exécution sur le dossier Projet B
Ops Accès exécution sur les jobs de déploiement

Nous allons donc voir comment paramétrer Jenkins pour lui dire de déléguer l’authentification utilisateur auprès d’un gestionnaire d’identité (ou identity provider) et assigner à celui-ci les droits en relation avec son rôle métier.

Pour faciliter la mise en oeuvre, Jenkins est organisé avec des dossiers permettant de mieux répartir les équipes consommatrices du service.

jenkins

Nous avons trois dossiers principaux dans Jenkins. Un pour les admins qui ont besoin d’avoir des jobs d’administration ou de tests, et un espace pour chaque projet.

jenkins

Au sein de chaque projet, nous avons un dossier “BUILD” qui contiendra les jobs de construction applicative, et un dossier “DEPLOY” qui contiendra ceux de déploiement. L’équipe Ops se devra d’avoir accès aux dossiers de déploiement pour pouvoir exécuter les jobs.

jenkins

jenkins

Installer Keycloak et créer un Identity Provider

Keycloak est un outil permettant de créer un Identity Provider et mettre en place du Single Sign-On en utilisant des protocoles comme OpenID et SAML2. Ce billet n’a pas pour but d’expliquer en détails son fonctionnement, surtout que je n’ai aucune expertise sur le sujet car ce n’est pas mon domaine. Je vous propose simplement de présenter comment la matrice d’habilitation se schématise au sein de l'identity provider.

Pour les besoins de la démo, nous allons créer un nouveau Realm dans Keycloak pour contiendra nos rôles et utilisateurs.

jenkins

jenkins

On ajoute ensuite un nouveau client pour Jenkins. Dans root url, il s’agit de celle de l’application Web de Jenkins.

jenkins

Dans l’onglet “Installation”, nous mettons de côté le paramétrage au format Keycloak OICD JSON pour le donner à Jenkins plus tard.

Nous créons ensuite des rôles dans le realm GarbageCollector.

jenkins jenkins

  • jenkins_adm : pour les admins Jenkins
  • jenkins_access : permettra d’avoir le droit “Read” dans Jenkins, nous verrons ça plus loins
  • jenkins_ops_execute : sera pour le groupe Ops
  • jenkins_project_a : sera pour les membres du Projet A
  • jenkins_project_b : sera pour les membres du Projet B

Nous créons ensuite les utilisateurs.

jenkins jenkins

Dans l’onglet rôle, nous assignons le profil adapté à l’utilisateur. Nous allons créer la liste suivante :

Utilisateur Rôle
jenkins_admin jenkins_adm
ops1 jenkins_access, jenkins_ops_execute
projecta jenkins_access, jenkins_project_a
projectb jenkins_access, jenkins_project_b

jenkins

Pourquoi le rôle jenkins_access ? Jenkins requiert à minima un droit “Overall/Read” pour permettre d’accéder aux ressource de l’instance. Le groupe “admin” possède nativement ce droit, mais les autres rôles doivent obligatoirement l’avoir. Nous allons voir ça immédiatement après.

Créer sa matrice RBAC dans Jenkins

Tout d’abord, installons les quelques plugins nécessaires pour Jenkins.

Le premier est nécessaire pour activer la matrice RBAC (Role-based Access Control / Gestion de contrôle d’accès par rôle), le second permet d’activer facilement la connexion OpenID avec KeyCloak. Dans le cas où vous utilisez un autre OpenID Provider, je vous conseille le plugin OpenId Connect Authentication.

Dans Manage => Configure Global Security => Authorization, activez “Role-based strategy”, sauvegardez.

jenkins

Un nouvel élément apparaît dans l’écran d’admin : Manage and Assign Roles, allez-y.

jenkins

Créer la matrice

Nous allons d’abord dans Manage Roles pour créer les rôles d’accès. Comme vous pourrez le constater, un rôle Global “admin” est pré-renseigné. Nous n’allons pas l’utiliser car on va préférer créer le notre au sein des rôles globaux.

Ajoutez donc un rôle “jenkins_adm” pour lequel vous cocherez “Overall/Administer” et un rôle “jenkins_access” à qui vous donnerez “Overall/Read”.

jenkins

Ceci est pour l’accès global, maintenant nous allons créer des Item roles. Si Global Roles permet de donner des droits au niveau de toute l’instance, les Item Roles permettent de donner un droit d’accès très fins à certains projets ou dossiers.

Lorsqu’on joue avec les dossiers, il est nécessaire de créer un droit pour entrer dans le dossier, et un droit pour utiliser/gérer les ressources qui s’y trouvent. Ceci est nécessaire pour produire la séparation d’accès attendue entre les Devs et les Ops.

Nous ajoutons un item role pour accéder au Projet A, puis un Item Role de lecture, écriture, exécution (permettant ainsi aux devs de créer, modifier, exécuter des jobs), et enfin un seul droit d’exécution et read pour les Ops. Cela signifie donc trois items de la façon suivante :

jenkins

Côté pratique, si vous cliquez sur le Pattern, Jenkins vous renvoie les éléments trouvés.

Bon à savoir : Il faut toujours donner le droit “Read” à l’objet auquel vous donnez accès, sinon il ne pourra pas être vu. Dans mes captures d’écran je l’avais oublié, le groupe s’est retrouvé sans rien.

jenkins

On sauvegarde et on obtient le résultat suivant :

jenkins

A nouveau, il n’y a pas besoin de droits particuliers pour le profil Admin (et donc le dossier ADMIN) présent dans Jenkins car le rôle global “Jenkins adm” donnera tous les droits.

Assigner la matrice

Rendez-vous maintenant dans Assign Roles. Nous allons d’abord assigner les rôles globaux “jenkins_adm” et “jenkins_access”.

jenkins

Ici, le nom du groupe doit être identique à ceux présents dans l’IDP !

Plus bas, dans les Item Roles, nous assignons les droits nécessaires pour que les rôles “jenkins_ops_execute”, “jenkins_project_a” et “jenkins_project_b” aient les attributs qui vont bien.

jenkins

N’oubliez pas de sauvegarder ! Le terrain est prêt, nous pouvons activer l’authentification avec OpenID et Keycloak.

💡 Notez que si vous revenez sur l’écran Assign Roles, les noms seront barrés car Jenkins ne les reconnaît pas dans sa base locale d’utilisateurs. Ceci est normal car l’Identity Provider viendra les créer ensuite.

Activer l’authentification OpenID

Allez dans Manage => Global Configuration et collez dans la section “Global Keycloak Settings” la config JSON récupérée lors de la création du client Jenkins. Si vous l’avez perdu, retournez sur Keycloak et aller dans “clients => jenkins” puis “Installation” et sélectionnez “Keycloak OICD JSON”.

jenkins

Maintenant, retournez dans Manage puis Global Security et activez “Keycloak authentication plugin” et sauvegardez.

jenkins

Désormais lorsqu’on se connecte à Jenkins, on est immédiatement redirigé sur Keycloak.

jenkins

Tests

Je me connecte avec “jenkins_admin”, qui est admin de l’instance : je retrouve les mêmes accès que le profil “admin” initial.

Oui, mon addon “dark mode” n’était pas actif en session privé.

jenkins

Je me connecte avec le profil “Project A”, j’ai uniquement accès aux ressources qui m’intéressent.

jenkins jenkins jenkins

Notez que les droits ne me permettent pas de créer ou de modifier des objets du dossier “PROJECT_A”, uniquement dans les sous dossiers BUILD et DEPLOY. Bien évidemment, vous pouvez adapter tout ceci à votre convenance ! 😉

Maintenant je passe en profil Ops, je vois les deux projets, mais je ne peux qu’exécuter les jobs de déploiement.

jenkins jenkins jenkins

Conclusion

Et voilà, j’espère que cet article vous aura éclairé sur le fonctionnement de la matrice RBAC de Jenkins. Après, je conçois que cette gestion peut devenir horriblement complexe si on veut aller dans le détail, je préconise donc d’éviter d’aller trop loin et de rester simple pour éviter que ça devienne une usine à gaz. Une des possibilités pour maintenir plus facilement est d’utiliser le plugin Jenkins Configuration as Code pour gérer tout ceci via fichiers de config ou encore via un chart Helm si vous déployez votre Jenkins sur un cluster Kubernetes.

Si vous avez parcouru les écrans de Jenkins, vous aurez sûrement noté la présence d’autres fonctions comme “Role macros” ou “Nodes items”. Ce sont des fonctions que je n’ai pas encore eu l’occasion d’utiliser.