C'est une problématique que l'on rencontre régulièrement : comment fournir proprement un accès aux Ops et développeurs aux clusters Kubernetes. Comment respecter le principe du "moindre privilège", comment révoquer les accès lorsque nécessaire.
Bien souvent, ce que l'on constate, c'est que l'on fini par partager un Kubeconfig avec les droits administrateurs du cluster 😨😨.
XAVKI 💝 a lancé récemment une série de vidéo autour de KeyCloak qui m'a fortement interessé (je connaissais avant KeyCloak que de nom).
Par ailleurs, cela faisait longtemps que je voulais tester le support OIDC sur Kubernetes, annoncé dans cet article: "Advanced Kubernetes Kapsule features you might have missed!" chez Scaleway.
Jusqu'à présent, je l'utilise la fonctionnalité OIDC chez AWS sur les clusters EKS pour relier mes utilisateurs IAM mais sans jamais comprendre vraiment ce qui se cache derrière.
C'est l'occasion de creuser et d'essayer d'assembler tout ça ⛏️
Installation de Keycloak
Pour ce tutorial, j'ai pris la dernière version disponible, à savoir la 18.0.1. J'ai volontairement choisi de l'installer en dehors du cluster Kubernetes bien que ce soit tout à fait possible. Il serait intéressant quelles sont les bonnes pratiques concernant Keycloak (haute disponibilité, backups, monitoring)
Dans mon cas (et comme c'est juste un POC), j'ai donc choisi le mode standalone sur une instance classique (DEV1-M, Ubuntu 20.04) sur laquelle j'installe Keycloak + sa base de donnée. Une base de donnée managée séparée me semble être une bonne idée (surtout si Keycloak est utilisé pour d'autres usages).
L'installation est simple, voici les étapes que j'ai suivies :
- Création d'un groupe/user sur la machine
- Créer une base de donnée PostgreSQL pour Keycloak (MySQL/MariaDB sont d'autres options tout à fait valables)
- Créer un utilisateur keycloak pour PostgreSQL
- Télécharger et dézipper l'archive dans le dossier /opt/keycloak
- Initialiser Keycloak avec la base de donnée (téléchargement du connecteur jdbc)
- Mettre en place le service Systemd pour Keycloak et l'activer au démarrage
- Mettre en place un reverse proxy nginx + certbot devant Keycloak
- Démarrer Keycloak
Création d'un utilisateur KeyCloak sur la machine
groupadd keycloak
useradd -g keycloak -m -s /bin/bash keycloak
Téléchargement et extraction du zip Keycloak
cd /opt
wget https://github.com/keycloak/keycloak/releases/download/18.0.1/keycloak-18.0.1.zip
unzip keycloak-18.0.1.zip
ln -s keycloak-18.0.1 keycloak
rm keycloak-18.0.1.zip
chown keycloak:keycloak /opt/keycloak
chown -R keycloak:keycloak /opt/keycloak-18.0.1
Installation de PostgreSQL + Creation de la base de donnée et de l'utilisateur
sudo apt-get install postgresql-12
su - postgres
psql
create database keycloak with encoding 'UTF8';
create user keycloak with encrypted password 'XXXXXXXX';
grant all privileges on database keycloak to keycloak;
(\q pour quitter)
Téléchargement du connecteur JDBC
Afin que Keycloak soit en mesure d'utiliser la base de donnée PostgreSQL, il faut lancer la commande suivante.
# sudo su - keycloak
cd /opt/keycloak
bin/kc.sh build --db postgres
Mise en place d'un service Systemd
Service systemd utilisé pour Keycloak:
# /etc/systemd/system/keycloak.service
[Unit]
Description=The Keycloak Server
After=syslog.target network.target
Before=nginx.service
[Service]
User=keycloak
Group=keycloak
LimitNOFILE=102642
WorkingDirectory=/opt/keycloak
Environment=KEYCLOAK_ADMIN=admin KEYCLOAK_ADMIN_PASSWORD=XXXXXXXX
ExecStart=/opt/keycloak/bin/kc.sh start \
--db-url-host 127.0.0.1 \
--db-username keycloak \
--db-password XXXXXXXX \
--hostname login.devops.in.net \
--proxy edge \
-b
[Install]
WantedBy=multi-user.target
Variable d'environnement:
- KEYCLOAK_ADMIN: nom d'utilisateur qui permet la connexion à la console d'administration Keycloak
- KEYCLOAK_ADMIN_PASSWORD: mot de passe de l'utilisateur qui permet la connexion à la console d'administration Keycloak
Options du script
- db-url-host : Hôte la base de donnée
- db-username : Utilisateur pour se connecter à la base de donnée
- db-password : Mot de passe pour se connecter à la base de donnée
- hostname : hôte publiquement accessible pour l'accès à Keycloak
- proxy edge: délègue la terminaison HTTPS au reverse (autorise le fonctionnement sur HTTP)
Activation du service au démarrage :
sudo systemctl daemon-reload
sudo systemctl enable keycloak
sudo systemctl start keycloak
Si tout va bien, les logs (journalctl -u keycloak -f
) devraient afficher quelque chose de ce genre:
INFO [io.quarkus] (main) Keycloak 18.0.1 on JVM (powered by Quarkus 2.7.5.Final) started in 17.972s. Listening on: http://0.0.0.0:8080
INFO [io.quarkus] (main) Profile prod activated.
Mise en place du reverse proxy Nginx + Terminaison SSL avec Certbot (Let's encrypt)
Commencons par installer Nginx
sudo apt-get install -y nginx
Modification du Virtual Host de base (/etc/nginx/site-enabled/default
) en vue de laisser Certbot gérer le certificat.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name login.devops.in.net; ## A remplacer par votre entrée DNS
location / {
try_files $uri $uri/ =404;
}
}
On redémarre nginx
sudo nginx -t # Pour vérifier la validité de la configuration
sudo nginx -s reload # Pour recharger la configuration
Penser à mettre en place un record DNS vers l'ip publique de votre serveur, sans cela Certbot ne sera pas capable d'obtenir un certificat. Afin de valider le bon fonctionnement, vous devez pouvoir accèder à http://{VOTRE_ENTREE_DNS}
Puis on suit le guide pour la mise en place de certbot
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx
Si tout va bien vous pouvez maintenant accèder à : https://{VOTRE_ENTREE_DNS}
Modifions le vhost (/etc/nginx/site-enabled/default
)
server {
[...]
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8080;
}
[...]
}
Puis rédémarrer nginx
sudo nginx -t
sudo nginx -s reload
Tada 🎉🎉
La partie 2 est en cours de rédaction :)