CVE Watch
CybersécuritéArticle7 min de lecture

SSO avec Keycloak et Guacamole via OpenID Connect - installation et configuration complète

MB
Massioudath Bankole
22 mars 2026 · 30 vues

Dans l'article précédent, j'ai installé Apache Guacamole 1.6.0 sur Ubuntu Server. Aujourd'hui on va plus loin : on va connecter Guacamole à Keycloak pour que les utilisateurs se connectent avec un compte unique - sans avoir à gérer des comptes séparés dans Guacamole. C'est ce qu'on appelle le SSO (Single Sign-On).

Concrètement, le flux devient :

Utilisateur → Guacamole → Redirigé vers Keycloak → Authentifié → Retour Guacamole

Plus besoin de gérer des mots de passe dans Guacamole. Keycloak centralise tout.

Prérequis : Guacamole 1.6.0 installé et fonctionnel, Ubuntu Server 22.04, accès sudo.


C'est quoi Keycloak ?

Keycloak est un serveur d'identité open source développé par Red Hat. Il gère l'authentification et les autorisations pour tes applications via des protocoles standards comme OpenID Connect (OIDC) et SAML.

Dans notre architecture, Keycloak joue le rôle de fournisseur d'identité (IdP) - c'est lui qui vérifie qui tu es. Guacamole joue le rôle de client - il délègue l'authentification à Keycloak.


Étape 1 : Installer Keycloak sur Ubuntu

Installer Java (prérequis)

Keycloak nécessite Java 21 minimum depuis la version 26 :

sudo apt update
sudo apt install -y openjdk-21-jdk
java -version
# openjdk version "21.x.x"

Télécharger et installer Keycloak

wget https://github.com/keycloak/keycloak/releases/download/26.1.4/keycloak-26.1.4.tar.gz
tar -xzf keycloak-26.1.4.tar.gz
sudo mv keycloak-26.1.4 /opt/keycloak

Créer un utilisateur système dédié

On ne lance jamais un service en root. On crée un utilisateur système sans shell d'accès :

sudo useradd -r -d /opt/keycloak -s /sbin/nologin keycloak
sudo chown -R keycloak:keycloak /opt/keycloak

L'option -r crée un compte système, -s /sbin/nologin empêche toute connexion interactive avec ce compte. C'est une bonne pratique de sécurité.


Étape 2 : Démarrer Keycloak

Mode développement (pour les tests)

Pour un lab ou un environnement de test, le mode dev est suffisant :

sudo -u keycloak /opt/keycloak/bin/kc.sh start-dev --http-port=8180

On utilise le port 8180 car Tomcat/Guacamole occupe déjà le port 8080.

Créer le compte admin initial

Dans un second terminal :

sudo -u keycloak /opt/keycloak/bin/kc.sh bootstrap-admin user --username admin

Bug rencontré : "HTTPS required"

En accédant à http://IP:8180, Keycloak affichait "HTTPS required". C'est une protection par défaut pour les accès depuis des IPs non-locales.

Solution - désactiver temporairement cette contrainte via kcadm.sh :

/opt/keycloak/bin/kcadm.sh config credentials \
  --server http://localhost:8180 \
  --realm master \
  --user admin \
  --password YOUR_PASSWORD

/opt/keycloak/bin/kcadm.sh update realms/master \
  -s sslRequired=NONE

Rafraîchis la page - tu devrais voir la page de login Keycloak.

Important : En production, configure un vrai certificat SSL et remets sslRequired=EXTERNAL ou ALL.

Si tu as oublié ton mot de passe admin

sudo rm -rf /opt/keycloak/data/h2
sudo -u keycloak KEYCLOAK_ADMIN=admin KEYCLOAK_ADMIN_PASSWORD=NouveauMotDePasse \
  /opt/keycloak/bin/kc.sh start-dev --http-port=8180

Étape 3 : Configurer Keycloak pour Guacamole

Créer un Realm dédié

Un Realm dans Keycloak c'est un espace isolé - ses propres utilisateurs, ses propres clients, ses propres règles. On ne mélange pas les applications dans le realm master.

  1. Clique sur "Keycloak master" en haut à gauche
  2. Clique sur "Create realm"
  3. Realm name : guacamole
  4. Clique sur Create

Créer le Client OIDC

Dans le realm guacamole :

  1. Clique sur ClientsCreate client
  2. Client type : OpenID Connect
  3. Client ID : guacamole
  4. Clique sur Next

Configuration des capabilities :

  • Client authentication : Off (client public, suffisant pour Guacamole)
  • Authorization : Off
  • Authentication flow : coche Standard flow + Implicit flow

Configuration des URLs (remplace YOUR_SERVER_IP) :

Root URL              : http://YOUR_SERVER_IP:8080/guacamole
Home URL              : http://YOUR_SERVER_IP:8080/guacamole
Valid redirect URIs   : http://YOUR_SERVER_IP:8080/guacamole/*
Valid post logout URIs: http://YOUR_SERVER_IP:8080/guacamole
Web origins           : http://YOUR_SERVER_IP:8080

Clique sur Save.

Créer un utilisateur de test

  1. Clique sur UsersCreate new user
  2. Remplis : Username testuser_example, Email user@example.com
  3. Clique sur Create
  4. Onglet CredentialsSet password
  5. Mets un mot de passe, désactive Temporary
  6. Clique sur Save

Étape 4 : Installer l'extension OpenID dans Guacamole

Télécharger l'extension SSO

wget https://downloads.apache.org/guacamole/1.6.0/binary/guacamole-auth-sso-1.6.0.tar.gz
tar -xzf guacamole-auth-sso-1.6.0.tar.gz
cd guacamole-auth-sso-1.6.0
sudo cp openid/guacamole-auth-sso-openid-1.6.0.jar /etc/guacamole/extensions/
ls -la /etc/guacamole/extensions/

Configurer guacamole.properties

sudo nano /etc/guacamole/guacamole.properties

Ajoute ces lignes à la fin du fichier en remplaçant IP par l'IP de ton serveur :

# OpenID Connect (Keycloak SSO)
openid-authorization-endpoint: http://IP:8180/realms/guacamole/protocol/openid-connect/auth
openid-jwks-endpoint: http://IP:8180/realms/guacamole/protocol/openid-connect/certs
openid-issuer: http://IP:8180/realms/guacamole
openid-client-id: guacamole
openid-redirect-uri: http://IP:8080/guacamole

Redémarre Tomcat :

sudo systemctl restart tomcat9

Étape 5 : Tester le SSO

Ouvre http://IP:8080/guacamole dans ton navigateur. Tu devrais voir deux options de connexion :

  • Le formulaire classique Guacamole
  • Un lien "Connectez-vous avec OpenID"

Clique sur OpenID → tu es redirigé vers Keycloak → connecte-toi avec testuser_example → tu arrives dans Guacamole.

Bug rencontré : "Implicit flow is disabled"

Erreur : unauthorized_client - Implicit flow is disabled for the client

C'est parce que Guacamole 1.6.0 utilise l'implicit flow par défaut. Il faut l'activer dans Keycloak :

  1. Clientsguacamole → onglet Settings
  2. Descends jusqu'à Authentication flow
  3. Coche Implicit flow
  4. Clique sur Save

Reteste - ça devrait fonctionner.


Étape 6 : Créer un compte admin permanent

Le compte admin initial de Keycloak est temporaire. Il faut créer un compte admin permanent dans le realm master.

  1. Repasse sur le realm master
  2. UsersAdd user
  3. Remplis username, email, prénom, nom
  4. CredentialsSet password → Temporary : Off
  5. Onglet Role mappingAssign role → filtre "realm roles" → coche adminAssign

Reconnecte-toi avec ce nouveau compte, puis supprime le compte admin temporaire.


Étape 7 : Synchroniser les utilisateurs Keycloak → Guacamole

Un utilisateur authentifié via Keycloak doit aussi exister dans Guacamole pour avoir accès aux connexions. J'ai écrit un script Python qui fait cette synchronisation automatiquement.

#!/usr/bin/env python3
"""
Synchronisation Keycloak -> Guacamole
Récupère les users du realm Keycloak et les crée dans Guacamole si absents.
Cron recommandé : 0 * * * * /usr/bin/python3 /opt/scripts/sync_keycloak_guacamole.py
"""
import requests
import logging

KEYCLOAK_URL   = "http://YOUR_SERVER_IP:8180"
KEYCLOAK_REALM = "guacamole"
KEYCLOAK_ADMIN_REALM = "master"
KEYCLOAK_ADMIN_USER  = "YOUR_KEYCLOAK_ADMIN_USER"
KEYCLOAK_ADMIN_PASS  = "TON_MOT_DE_PASSE"

GUACAMOLE_URL        = "http://YOUR_SERVER_IP:8080/guacamole"
GUACAMOLE_ADMIN      = "guacadmin"
GUACAMOLE_PASS       = "YOUR_GUACADMIN_PASSWORD"
GUACAMOLE_DATASOURCE = "mysql"

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
log = logging.getLogger(__name__)

def get_keycloak_token():
    url = f"{KEYCLOAK_URL}/realms/{KEYCLOAK_ADMIN_REALM}/protocol/openid-connect/token"
    data = {"client_id": "admin-cli", "username": KEYCLOAK_ADMIN_USER,
            "password": KEYCLOAK_ADMIN_PASS, "grant_type": "password"}
    r = requests.post(url, data=data)
    if r.status_code == 200:
        return r.json().get("access_token")
    log.error(f"Erreur token Keycloak: {r.status_code}")
    return None

def get_keycloak_users(token):
    url = f"{KEYCLOAK_URL}/admin/realms/{KEYCLOAK_REALM}/users?max=1000"
    r = requests.get(url, headers={"Authorization": f"Bearer {token}"})
    return r.json() if r.status_code == 200 else []

def get_guacamole_token():
    r = requests.post(f"{GUACAMOLE_URL}/api/tokens",
                      data={"username": GUACAMOLE_ADMIN, "password": GUACAMOLE_PASS},
                      headers={"Content-Type": "application/x-www-form-urlencoded"})
    return r.json().get("authToken") if r.status_code == 200 else None

def get_guacamole_users(token):
    r = requests.get(f"{GUACAMOLE_URL}/api/session/data/{GUACAMOLE_DATASOURCE}/users",
                     headers={"Guacamole-Token": token})
    return list(r.json().keys()) if r.status_code == 200 else []

def create_guacamole_user(token, email):
    r = requests.post(
        f"{GUACAMOLE_URL}/api/session/data/{GUACAMOLE_DATASOURCE}/users",
        headers={"Guacamole-Token": token, "Content-Type": "application/json"},
        json={"username": email, "password": "",
              "attributes": {"disabled": "", "expired": ""}}
    )
    if r.status_code == 200:
        log.info(f"Utilisateur créé : {email}")
    else:
        log.error(f"Erreur création {email}: {r.status_code}")

def sync():
    kc_token   = get_keycloak_token()
    guac_token = get_guacamole_token()
    if not kc_token or not guac_token:
        return

    kc_users   = get_keycloak_users(kc_token)
    guac_users = get_guacamole_users(guac_token)

    created = 0
    for user in kc_users:
        email = user.get("email", "")
        if not email:
            continue
        if email not in guac_users:
            create_guacamole_user(guac_token, email)
            created += 1

    log.info(f"Sync terminée : {created} utilisateur(s) créé(s).")

if __name__ == "__main__":
    sync()

Pour l'automatiser toutes les heures :

sudo crontab -e
# Ajoute :
0 * * * * /usr/bin/python3 /opt/scripts/sync_keycloak_guacamole.py >> /var/log/sync_keycloak_guacamole.log 2>&1

Résultat final

Tu as maintenant un bastion Guacamole avec SSO complet :

  • Les utilisateurs se connectent via Keycloak - un seul compte pour tout
  • Guacamole n'a plus à gérer l'authentification
  • La synchronisation automatique crée les comptes Guacamole à partir de Keycloak

Dans le prochain article, on va encore plus loin avec HashiCorp Vault pour stocker les secrets SSH/RDP de façon sécurisée - fini les mots de passe en clair dans Guacamole.


Tags : Guacamole, Keycloak, SSO, OpenID Connect, Admin Linux, DevSecOps, Bastion

Partager cet article

Commentaires (0)

Sois le premier à commenter !

Articles similaires