Keycloak

De wikarphy
Version datée du 8 décembre 2024 à 17:00 par Linarphy (discussion | contributions) (Replace some code tags by syntaxhighlight inline)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)

Keycloak est le service disponible sur l'adresse suivante. Il gère l'authentification des utilisateurs sur tous les autres services de l'architecture.

Configuration actuelle

Le service Nginx transfère les pages web du port 8127 (géré par Keycloak) vers le port 443 (https) sur le domaine wiki.linarphy.net (serveur computing). Les données sont gérés par Postgresql via une base de donnée ayant pour nom keycloak et pour utilisateur keycloak. Cette instance stocké dans le dossier /usr/share/keycloak/ tourne sur la version 26.0.0 avec openjdk-21.0.2 (lui-même dans /usr/share/openjdk/21/).

Installation

Prérequis

Procédure

Fichiers

La première étape consiste au téléchargement du service avec la commande curl -L https://github.com/keycloak/keycloak/releases/download/26.0.0/keycloak-26.0.0.tar.gz -o keycloak-26.0.0.tar.gz en tant qu'utilisateur root. Le lien est récupéré sur la page de téléchargement. Le fichier keycloak-26.0.0.tar.gz peut ensuite être extrait avec la commande tar -xf keycloak-26.0.0.tar.gz en tant qu'utilisateur root pour ensuite supprimer cette archive: rm keycloak-26.0.0.tar.gz.

Le dossier peut ensuite être déplacé dans son emplacement final (/usr/share/keycloak/) avec la commande mv keycloak-26.0.0 /usr/share/keycloak(toujours en tant que root).

Java

Télécharger OpenJDK 21 avec la commande curl -L {lien-targz-openjdk-21} -o openjdk-21.tar.gz en tant que root. Le lien vers l'archive est disponible ici. Puis extraire l'archive: tar -xf openjdk-21.tar.gz et supprimer l'archive téléchargée: rm openjdk-21.tar.gz. Si le dossier n'existe pas déjà, crée le dossier /usr/share/openjdk/ avec la commande mkdir /usr/share/openjdk puis déplacer le dossier extrait vers son emplacement final: mv jdk-21.0.2 /usr/share/openjdk/21.

Pour se lier au service LDAP du serveur FreeIPA, il est nécessaire d'ajouter les clefs publics des certificats utilisés pour sécuriser la connexion. L’utilisation de la commande /usr/share/openjdk/21/bin/keytool -v -import -file /etc/ipa/ca.crt -alias ipacrt -keystore /usr/share/openjdk/21/lib/security/cacerts permet d'effectuer cette opération (ajouter la clef public du certificat du serveur au stockage de clef public de l'installation de java qui va être utilisé par Keycloak).

Permissions

Le service s'exécutera avec un utilisateur particulier (et non root) pour isoler le processus. Il est donc nécessaire de créer l'utilisateur local keycloak avec la commande adduser --system --no-create-home --group keycloak en tant que root. La commande chown -R keycloak:keycloak /usr/share/keycloak/ pour donner les permissions du dossier à ce nouvel utilisateur.

Keycloak sera accessible via une connexion chiffré (https), et sa configuration nécessite l'accès à la clef privé et public utilisé pour cette connexion (comme Nginx). Pour protéger ces clefs et ne pas les rendre accessible à d'autres utilisateur que keycloak, un hook (script) sera mis en place pour être exécuté par Certbot. Il va donc être nécessaire de créer le dossier /usr/share/keycloak/certs via la commande mkdir /usr/share/keycloak/certs en tant que root (oui oui, pas keycloak pour le moment, c'est normal), puis de modifier ces permissions avec les commandes chown keycloak:keycloak /usr/share/keycloak/certs et chmod 500 /usr/share/keycloak/certs. Créer ensuite le fichier /usr/share/keycloak/certs/hook.sh toujours en tant que root avec l'éditeur de sont choix contenant le script:

#!/usr/bin/env sh

# adapted from https://gist.github.com/Sternerson/file-ssl-deploy-hook-L1

KEYCLOAK_CERT_DIR=/usr/share/keycloak/certs

umask 077 # the certificate are not world readable during the copying

cp "${RENEWED_LINEAGE}/privkey.pem" "${KEYCLOAK_CERT_DIR}/privkey.pem"
cp "${RENEWED_LINEAGE}/fullchain.pem" "${KEYCLOAK_CERT_DIR}/fullchain.pem"

chown keycloak:keycloak "${KEYCLOAK_CERT_DIR}/privkey.pem"
chown keycloak:keycloak "${KEYCLOAK_CERT_DIR}/fullchain.pem"

chmod 400 "${KEYCLOAK_CERT_DIR}/privkey.pem"
chmod 400 "${KEYCLOAK_CERT_DIR}/fullchain.pem"

Exécuter la commande chmod +x /usr/share/keycloak/hook.sh pour permettre l'exécution du script. Les permissions de ce fichier ne vont pas être autrement modifié, le script ne sera exécuté que par l'utilisateur root.

Configuration

# Basic settings for running in production. Change accordingly before deploying the server.

# Database

# The database vendor.
#db=postgres
db=postgres

# The username of the database user.
#db-username=keycloak
db-username=keycloak

# The password of the database user.
#db-password=password
db-password={keycloak-postgresql-password}

# The full database JDBC URL. If not provided, a default URL is set based on the selected database vendor.
#db-url=jdbc:postgresql://localhost/keycloak
db-url=jdbc:postgresql://localhost/keycloak

# Observability

# If the server should expose healthcheck endpoints.
#health-enabled=true
health-enabled=true

# If the server should expose metrics endpoints.
#metrics-enabled=true
metrics-enabled=true

# HTTP

# The file path to a server certificate or certificate chain in PEM format.
#https-certificate-file=${kc.home.dir}conf/server.crt.pem
https-certificate-file=${kc.home.dir}/certs/fullchain.pem

# The file path to a private key in PEM format.
#https-certificate-key-file=${kc.home.dir}conf/server.key.pem
https-certificate-key-file=${kc.home.dir}/certs/privkey.pem

# The proxy address forwarding mode if the server is behind a reverse proxy.
#proxy=reencrypt

# Do not attach route to cookies and rely on the session affinity capabilities from reverse proxy
#spi-sticky-session-encoder-infinispan-should-attach-route=false

# Hostname for the Keycloak server.
#hostname=myhostname
hostname=auth.linarphy.net

## Added manually
proxy-headers=xforwarded
https-port=8127

Nginx

Créer le fichier /etc/nginx/sites-available/auth.linarphy.net contenant la configuration Nginx suivante:

server {
  server_name auth.linarphy.net;

  listen 80;
  listen [::]:80;
}

Puis créer un lien symbolique avec la commande ln -s /etc/nginx/sites-available/auth.linarphy.net /etc/nginx/sites-enabled/auth.linarphy.netet tester la configuration via nginx -t. Si la configuration est valide, il est nécessaire de recharger le service systemd avec systemctl reload nginx et mettre en place le chiffrement ssl avec certbot --nginx --domain auth.linarphy.net --deploy-hook=/usr/share/keycloak/certs/hook.sh.

Vérifier ensuite sur un navigateur l'accès au service sur le protocole https.

Modifier ensuite le fichier /etc/nginx/sites-available/auth.linarphy.net avec le contenu suivant:

server {
        # adapted from https://github.com/keycloak/keycloak/discussions/13441 (Igortorrente)
        server_name auth.linarphy.net;

        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        listen 443 ssl; # managed by Certbot

        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-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;

        location / {
               return 301 https://$host/realms/linarphy.net/account/#/;
        }
        location / {
                proxy_pass https://localhost:8127;
        }
        location /admin/ {
                deny all;
                allow {private-ip};
                proxy_pass https://localhost:8127;
        }
        location /health/ {
                deny all;
                allow {private-ip};
                proxy_pass https://localhost:8127;
        }
        location /js/ {
                proxy_pass https://localhost:8127;
        }
        location /metrics/ {
                deny all;
                allow {private-ip};
                proxy_pass https://localhost:8127;
        }

        location /realms/ {
                proxy_pass https://localhost:8127;
        }
        location /resources/ {
                proxy_pass https://localhost:8127;
        }

        ssl_certificate /etc/letsencrypt/live/auth.linarphy.net/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/auth.linarphy.net/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


}
server {
        server_name auth.linarphy.net;

        listen 80;
        listen [::]:80;

        location / {
                return 301 https://$host$request_uri;
        }

        return 404; # managed by Certbot
}

Base de donnée

En tant qu'utilisateur postgres, lancer la commande psql puis exécuter les commandes suivantes:

  • CREATE DATABASE keycloak;
  • CREATE USER keycloak WITH ENCRYPTED PASSWORD '{keycloak-postgresql-password}';
  • GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak;
  • \c keycloak
  • GRANT ALL ON SCHEMA public TO keycloak;
  • \q

Systemd

Lancer la commande systemctl edit --full --force keycloak.service pour écrire l'unité systemd suivante avec l'éditeur de votre choix (systemd utilise la variable d'environnement EDITOR):

[Unit]
Description=Keycloak authentication server connected to the FreeIPA LDAP
Documentation=https://keycloak.org/documentation
After=network-online.target

[Service]
User=keycloak
Restart=on-failure
RestartSec=2s
WorkingDirectory=/usr/share/keycloak
ExecStart=/usr/share/keycloak/bin/kc.sh start --optimized
TimeoutStopSec=10s
KillSignal=SIGTERM
KillMode=process
SendSIGKILL=no
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Puis créer un second fichier de configuration supplémentaire avec systemctl edit keycloak.service et y écrire:

[Service]
Environment="JAVA_HOME=/usr/share/openjdk/21"

Pour mieux organiser la configuration, modifier le nom du fichier de réécriture avec mv /etc/systemd/system/keycloak.service.d/override.conf /etc/systemd/system/keycloak.service.d/env.conf.

Configuration

Toute cette étape sera suivie par l'utilisateur keycloak dans le dossier /usr/share/keycloak/.

D'abord, construisez la configuration avec la commande ./bin/kc.sh build jusqu'à attendre la fin, puis lancer une première fois keycloak avec ./bin/kc.sh start. Une fois que le message (main) Installed features: [...] s'affiche, appuyer sur Ctrl+C pour arrêter le programme.

Si tout allait bien, il aurait suffit de définir les variables d'environnement KC_BOOTSTRAP_ADMIN_USERNAME et KC_BOOTSTRAP_ADMIN_PASSWORD pour définir respectivement le nom d'utilisateur et le mot de passe de l'administrateur du service, puis de lancer les commandes précédentes. Malheureusement, le monde n'est pas parfait. Du coup il est nécessaire d'effectuer la commande ./bin/kc.sh bootstrap-admin user puis de définir le nom d'utilisateur et le mot de passe de l'administrateur.

Finalisation

Activer et lancer le service systemd en exécutant systemctl enable keycloak puis systemctl start keycloak.

Configuration post-installation

Création du realm

Une fois connecté sur le nouveau site, cliquer sur le menu déroulant en haut à gauche (Keycloak master) et cliquer sur Create realm. Et définir son nom. C'est ce realm qui va relier l'authentification de tous les services.

Liaison avec FreeIPA

Dans l'onglet "Fédération utilisateur" du nouveau realm, ajouter un nouveau fournisseur LDAP et y insérer la configuration suivante (les entrées non définie sur celui-ci sont laissé par défaut):

clef valeur
vendor Red Hat Directory Server
connection URL ldaps://admin0.linarphy.net:636
enable StartTLS Off
user truststore SPI Always
bind DN uid=admin,cn=users,cn=accounts,dc=linarphy,dc=net
bind credentials {password-admin-freeipa}
edit mode READ_ONLY
users DN cn=users,cn=accounts,dc=linarphy,dc=net
username LDAP attribute uid
RDN LDAP attribute uid
UUID LDAP attribute ipaUniqueID
user object classes inetOrgPerson, organizationalPerson
search scope One Level
import users On
sync Registrations On