GitLab peut être utilisé comme provider OIDC. Pour cela il suffit de déclarer une “Application” cliente dans GitLab.
Dans cet exemple nous allons configurer un cluster Kubernetes k3s ainsi que l’outil en ligne de commande kubectl pour permettre à un utilisateur de s’authentifier via le provider OIDC GitLab.
Déclaration d’une nouvelle application dans GitLab
GitLab permet de déclarer une application à plusieurs niveaux différents : global, groupe ou utilisateur.
Par exemple pour créer une application au niveau d’un groupe GitLab :
- Allons sur la page du groupe.
- Dans le menu de gauche, sélectionnons
Settings
>Applications
. - Dans la case
Name
indiquons un nom pour l’application, par exemplemon-cluster-k3s
. - Dans la case
Redirect URI
, indiquonshttp://localhost:8000
. - Cochons la case
Confidential
. - Cochons les
Scopes
suivants :
openid
profile
email
- Enregistrons le tout et notons les valeurs générées pour
Application ID
etSecret
, nous nous en servirons ultérieurement.
Installation du cluster k3s
Sur une machine virtuelle (dans mon exemple l’adresse IP de cette machine est 35.78.143.121
), installons k3s à l’aide de la commande :
sudo -i
cd /root && curl -sfL https://get.k3s.io | sh -
Toujours en tant qu’utilisateur root créons un namespace nommé foo, qui nous servira d’exemple :
kubectl create namespace foo
Configuration de k3s
Créons le fichier /etc/rancher/k3s/config.yaml
pour configurer k3s avec le contenu suivant :
tls-san:
- 35.78.143.121 # Adresse IP du cluster k3s
kube-apiserver-arg:
- '--oidc-issuer-url=https://gitlab.com'
- '--oidc-client-id=<APPLICATION ID GITLAB>'
- '--oidc-username-claim=email'
- '--oidc-username-prefix=oidc:'
- '--oidc-groups-claim=groups_direct'
- '--oidc-groups-prefix=gitlab:'
-
tls-san
: Indique le ou les noms d’hôtes (ou adresses IPv4/IPv6) à ajouter en tant que noms alternatifs de sujet sur le certificat TLS. Ceci permet d’éviter des erreurs TLS lors de l’utilisation du client kubectl depuis autre machine. -
kube-apiserver-arg
: Permet de spécifier les paramètres permettant de configurer l’API server de Kubernetes. Il est possible de spécifier un certain nombre de paramètres OIDC. -
Les options
--oidc-username-prefix
et--oidc-groups-prefix
permettent d’ajouter un prefixe permettant d’éviter les conflits avec des utilisateurs ou groupes déjà déclarés dans Kubernetes.
Redémarrons le service k3s pour prendre en compte la nouvelle configuration :
sudo systemctl restart k3s.service
Connexion d’un utilisateur au cluster
Imaginons que nous souhaitions maintenant donner un accès sur le cluster à un développeur qui a le bon goût de travailler sur une machine Ubuntu ;-)
Les pré-requis nécessaires à installer sur sa machine sont :
-
sudo apt-get update && sudo apt-get install -y apt-transport-https curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list sudo apt-get update sudo apt-get install -y kubectl
-
curl -LO https://github.com/int128/kubelogin/releases/download/v1.28.1/kubelogin_linux_amd64.zip unzip kubelogin_linux_amd64.zip rm LICENSE README.md kubelogin_linux_amd64.zip sudo mv kubelogin /usr/local/bin/kubectl-kubelogin
Il est important de préfixer le nom du binaire avec
kubectl-
pour que kubectl puisse reconnaître kubelogin comme un de ses plugins.kubelogin est un plugin pour kubectl qui permet de faire la colle entre kubectl et un provider OIDC :
Nous devons ensuite fournir à l’utilisateur un fichier kubeconfig qui lui permettra de se connecter au cluster. Pour cela nous pouvons récupérer sur le serveur k3s le fichier /etc/rancher/k3s/k3s.yaml
et l’adapter pour produire le fichier suivant que l’on pourra copier sur la machine de l’utilisateur à l’emplacement ~/.kube/config
après avoir remplacé les éléments figurant entre < >
.
Attention à ne pas écraser un éventuel fichier ~/.kube/config
pré-existant !
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: <LAISSER LA VALEUR D'ORIGINE>
server: https://35.78.143.121:6443 # URL de l'API server du cluster k3s
name: default
contexts:
- context:
cluster: default
user: default
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubectl
args:
- kubelogin
- get-token
- --oidc-issuer-url=https://gitlab.com
- --oidc-client-id=<APPLICATION ID PROVENANT DE GITLAB>
- --oidc-client-secret=<APPLICATION SECRET PROVENANT DE GITLAB>
- --oidc-extra-scope=email
#- -v1 # A décommenter si on souhaite afficher du debug
env: null
interactiveMode: IfAvailable
provideClusterInfo: false
Testons l’authentification avec la commande :
kubectl auth whoami
Les pages suivantes devraient s’ouvrir dans le navigateur de l’utilisateur afin qu’il puisse s’authentifier sur GitLab :
Relançons la commande précédente, ça doit passer ce coup-ci :
kubectl auth whoami
ATTRIBUTE VALUE
Username oidc:bob@example.com
Groups [gitlab:k8s-permissions gitlab:k8s-permissions/foo-developers system:authenticated]
Nous sommes bien reconnus. Essayons maintenant de récupérer la liste des pods du namespace foo :
kubectl get pods -n foo
Error from server (Forbidden): pods is forbidden: User "oidc:bob@example.com"
cannot list resource "pods" in API group "" in the namespace "foo"
Que se passe-t-il ? Nous sommes bien reconnus mais nous n’avons pas encore d’autorisations pour pouvoir réaliser cette opération.
Configurer les droits d’accès
Pour configurer ces autorisations, revenons sur le serveur k3s et créons les fichiers nécessaires pour donner un accès de type développeur à nos développeurs.
Le fichier developer.clusterrole.yaml
déclare les permissions de base habituelles pour un développeur ayant besoin de déployer des applications :
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: developer
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/portforward", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
Ce ClusterRole peut ensuite être référencé dans un objet de type RoleBinding pour donner accès à un utilisateur ou un groupe d’utilisateurs sur un namepace donné. Exemple de fichier pour le namespace foo que nous avons créé précédemment :
Fichier developer-foo.rolebinding.yaml
:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: foo-developer
namespace: foo
subjects:
- kind: Group
name: "gitlab:k8s-permissions/foo-developers"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: developer
apiGroup: rbac.authorization.k8s.io
Ici nous disons simplement : dans le namespace foo on donnera les permissions définies dans le ClusterRole developer aux utilisateurs déclarés dans le groupe GitLab k8s-permissions/foo-developers.
Pour que cela fonctionne avec notre utilisateur il faudra donc bien sûr l’ajouter comme membre du groupe GitLab k8s-permissions/foo-developers.
On applique la configuration :
kubectl apply -f developer.clusterrole.yaml
kubectl apply -f foo-developer.rolebinding.yaml
Test des permissions
Revenons sur la machine de notre développeur et essayons de nouveau la commande précédente :
kubectl get pods -n foo
No resources found in foo namespace.
Ca à l’air mieux ;-)
Notons que si nous essayons de lister les pods d’un autre namespace, par exemple bar nous obtiendrons logiquement un message d’erreur puisque nous n’avons autorisé que l’accès sur foo :
kubectl get pods -n bar
Error from server (Forbidden): pods is forbidden: User "oidc:bob@example.com"
cannot list resource "pods" in API group "" in the namespace "bar"
Essayons donc maintenant de déployer une application dans le namepace foo :
kubectl create deployment wit --image xian310/who-is-there:25 -n foo
deployment.apps/wit created
Et voilà :
kubectl get pods -n foo
NAME READY STATUS RESTARTS AGE
wit-5dcfc9b44d-597b7 1/1 Running 0 15s
Suppression des droits de l’utilisateur
Pour supprimer les droits à notre developpeur sur le namespace foo il suffira simplement de le retirer du groupe GitLab k8s-permissions/foo-developers.