Bastion Guacamole¶
Rôle¶
Bastion d'accès distant unique de l'infrastructure Indio : point d'entrée
web (Apache Guacamole 1.6.0) pour l'administration RDP/SSH/VNC de
pratiquement toute la flotte, sans nécessiter de client RDP/SSH local sur le
poste de l'administrateur. VM guac-bastion / INDIDEN001
(10.100.2.244, seg-identite). À ce jour, il stocke 55 connexions
couvrant vCenter, NSX Manager, les nœuds Edge, le witness vSAN, les deux
contrôleurs de domaine AD (RDP), GitLab, Nexus, le nœud de contrôle
lui-même, Horizon, et quasi toute la flotte IND* en SSH.
Contrairement aux autres briques identité de ce même dépôt (FreeIPA, voir FreeIPA & trust AD), l'application Guacamole a été installée manuellement par l'utilisateur — aucun projet IaC dédié, aucun rôle Ansible. Elle a été auditée en détail le 2026-07-12 ; cette page documente cet audit et son évolution depuis.
Remédiation la plus urgente de toute l'infrastructure Indio, non traitée à ce jour
Les identifiants par défaut du produit, guacadmin / guacadmin,
fonctionnaient encore lors du dernier contrôle connu (2026-07-12,
revalidé indirectement le 2026-07-16 lors de l'ajout d'une connexion —
voir Procédure manuelle). Ce bastion donne accès à la quasi-totalité de
l'infrastructure. Voir la section Points d'attention pour le détail
complet et son statut de vérification.
Architecture¶
Pile applicative¶
| Composant | Port | Bind | Rôle |
|---|---|---|---|
| Apache httpd | 443/tcp | 0.0.0.0 (attendu — accès public du bastion) |
Reverse proxy, terminaison TLS, vhost durci |
| Tomcat | local | 127.0.0.1 (via AJP/HTTP proxifié par Apache) |
Exécute guacamole.war (webapp) + guacamole-auth-jdbc-mysql-1.6.0.jar |
| guacd | 4822/tcp | 0.0.0.0 (voir Points d'attention) |
Traducteur de protocole (RDP/SSH/VNC), non authentifié par nature |
| MariaDB | 3306/tcp | 0.0.0.0 (voir Points d'attention) |
Base guacamole_db : connexions, paramètres, historique, comptes |
flowchart LR
Client["Client (navigateur admin)"] -->|"HTTPS 443\nTLS auto-signé, SANS SAN"| Apache["Apache httpd\n(reverse proxy TLS, vhost durci)"]
Apache -->|proxy local| Tomcat["Tomcat\nguacamole.war + auth-jdbc-mysql"]
Tomcat -->|JDBC| MariaDB["MariaDB :3306\nguacamole_db\nbind 0.0.0.0"]
Tomcat -->|"protocole Guacamole"| Guacd["guacd :4822\nbind 0.0.0.0, non authentifié"]
Guacd -->|RDP| T1["addns-node01/02 (DC AD), win11..."]
Guacd -->|SSH| T2["quasi toute la flotte IND*"]
Guacd -->|"RDP/SSH/VNC"| T3["vCenter, NSX Manager, edges,\nwitness vSAN, GitLab, Nexus,\nHorizon, SOC (Kibana)..."]
Les 55 connexions, regroupées par zone¶
flowchart TB
B["INDIDEN001 (guac-bastion)\n10.100.2.244 — seg-identite\nCompte unique : guacadmin"]
B --> MGMT["Zone mgmt (10.15.100.x)\nvCenter-Server, nsx-manager,\nedge-node01/02/03, vSAN-Witness,\nfedora-control-node (nœud de contrôle lui-même)"]
B --> AD["seg-identite — DC AD (RDP)\naddns-node01, addns-node02"]
B --> DEVOPS["gitlab, nexus"]
B --> VDI["horizon, win11"]
B --> FLEET["Quasi toute la flotte IND* en SSH\n(dont INDSERV026, ajouté 2026-07-16)"]
B -.->|"accès scopé grp-guac-bastion\najouté 2026-07-15"| SOC["seg-soc (deny-all sinon)\nKibana INDSOC017 + SSH"]
L'accès du bastion vers la zone SOC (deny-all scopé par défaut, voir NSX) est régi par des règles DFW dédiées, ajoutées le 2026-07-15 :
| Règle | Fichier | Source | Détail |
|---|---|---|---|
guac-bastion-to-soc-ssh |
dfw_soc.tf |
grp-guac-bastion (IP 10.100.2.244 seule) |
SSH vers la zone SOC |
guac-bastion-to-soc-kibana |
dfw_soc.tf |
grp-guac-bastion |
HTTPS vers Kibana (INDSOC017) |
grp-guac-bastion est scopé à l'IP précise du bastion (ipaddress_expression
= ["10.100.2.244"]), pas à toute seg-identite — un choix délibéré tant
que le compte guacadmin par défaut reste actif (voir Points d'attention) :
élargir l'accès à toute la zone identité aurait aussi élargi la portée d'une
éventuelle compromission de ce compte partagé.
Aucun dépôt IaC dédié
Il n'existe pas de structure de dépôt à documenter pour l'application
Guacamole elle-même — seule la VM est provisionnée en Terraform (voir
ci-dessous). Toute la configuration applicative (Apache, Tomcat, guacd,
MariaDB, schéma, comptes, 55 connexions) vit uniquement sur le système
live et dans la base guacamole_db.
Provisioning Terraform¶
La VM INDIDEN001 est provisionnée par le même projet Terraform que
FreeIPA (/root/identity/main.tf, voir
FreeIPA & trust AD) : ressource
vsphere_virtual_machine.vm en for_each sur var.nodes, qui inclut
INDIDEN001 (2 vCPU / 4096 Mo) aux côtés des VM FreeIPA. Aucune ressource
Terraform séparée ni spécifique à Guacamole — le clonage (template, réseau
seg-identite, personnalisation IP/hostname) suit exactement le même
mécanisme générique que le reste du dépôt.
Configuration Ansible¶
ansible/inventory.ini du même dépôt /root/identity déclare un groupe
[guacamole] avec INDIDEN001 ansible_host=10.100.2.244, mais
site.yml l'exclut explicitement :
# Note : le bastion Guacamole (INDIDEN001) est installé manuellement,
# hors de ce playbook (choix opérationnel).
Ce groupe d'inventaire existe donc mais n'est ciblé par aucun play — un lecteur pressé pourrait croire à une configuration Ansible fonctionnelle en voyant le groupe déclaré ; ce n'est pas le cas.
Procédure manuelle¶
1. Installation initiale (reconstituée depuis l'audit du 2026-07-12)¶
Aucun script ni playbook ne documente cette installation — ce qui suit est la reconstitution la plus complète disponible à partir de l'état système observé, pas une procédure rejouable automatiquement.
- VM clonée depuis
tmpl-rocky96-hardened(SELinux enforcing, firewalld zone par défautdrop) via le Terraform partagé avec FreeIPA. - Installation de
guacamole-server(compilation/paquet fournissantguacd) et démarrage du service sur le port 4822. - Installation de Tomcat + déploiement de
guacamole.war(webapp Guacamole) et de l'extensionguacamole-auth-jdbc-mysql-1.6.0.jar(authentification via base MySQL/ MariaDB — seule extension d'authentification chargée, pas deguacamole-auth-totp/duo). - Installation de MariaDB, création de la base
guacamole_db(import du schéma JDBC officiel), création d'un compte applicatifguacamole_userstrictement scopé à cette base (pas de droits globaux),root@localhostlaissé en authentification socket-only (refuse tout accès TCP même avec le bon mot de passe). /etc/guacamole/guacamole.propertiesconfiguré avecmysql-hostname,mysql-database,mysql-username/mysql-password(ce dernier réutilise le mot de passe standard de flotte — voir Points d'attention, valeur non reproduite ici) pointant vers l'extension JDBC.- Apache httpd installé et configuré en reverse proxy TLS devant Tomcat :
certificat auto-signé (
CN=bastion.infra.indio, sans SAN, auto-émis — pas via la CA interne Vault, voir Vault & PKI),TLSv1.2/TLSv1.3uniquement, en-têtes de sécurité (HSTS,X-Frame-Options, etc.). - firewalld : zone
drop, seuls http/https/ssh explicitement autorisés. - Compte
guacadminlaissé à sa valeur par défaut du produit lors du premier démarrage — jamais changé depuis (voir Points d'attention). - 55 connexions créées au fil du temps (vCenter, NSX Manager, edges,
witness vSAN, DC AD en RDP, GitLab, Nexus, nœud de contrôle, Horizon,
quasi toute la flotte
IND*en SSH), organisées en groupes de connexion par segment/zone.
2. Procédure d'ajout d'une connexion (mécanisme réel, réutilisé au moins deux fois)¶
En l'absence de tout IaC pour ce composant, c'est littéralement la
procédure de déploiement de ce composant au quotidien — utilisée telle
quelle le 2026-07-16 pour ajouter INDSERV026 (SSH, groupe seg-service)
et le 2026-07-15 pour l'accès SOC :
sequenceDiagram
participant Op as Opérateur
participant API as API REST Guacamole (INDIDEN001)
participant DB as MariaDB (guacamole_db)
Op->>API: POST /guacamole/api/tokens (compte administrateur)
API-->>Op: authToken
Op->>API: GET .../connectionGroups/ROOT/tree?token=...
Note over Op: identifie le groupe de connexion du segment cible,<br/>récupère les parameters d'une connexion voisine du même segment
Op->>API: POST .../connections?token=...<br/>{parentIdentifier, protocol, parameters dupliqués}
API->>DB: INSERT connection + parameters
API-->>Op: connexion créée
Op->>API: DELETE /guacamole/api/tokens/{authToken}
Note over API: token révoqué immédiatement après usage
Étapes concrètes :
- Identifier le groupe de connexion (
connectionGroups) correspondant au segment NSX de la cible. - S'authentifier (
POST /guacamole/api/tokens) pour obtenir un token. - Dupliquer les
parametersd'une connexion voisine déjà existante dans le même segment (hostname/port/protocole diffèrent, le reste — options d'affichage, etc. — reste identique) plutôt que de tout ressaisir. - Créer la connexion (
POST /guacamole/api/connections). - Révoquer le token immédiatement après usage
(
DELETE /guacamole/api/tokens/{token}) — pas de session admin laissée ouverte plus longtemps que nécessaire.
Procédure de déploiement¶
Il n'existe pas de procédure de déploiement automatisée de bout en bout pour ce composant :
terraform applydans/root/identity— provisionne la VM nueINDIDEN001surseg-identite(partagé avec FreeIPA).- Installation applicative : entièrement manuelle, suivre Procédure manuelle §1 — aucun playbook Ansible ni script ne l'automatise.
- Ajout de nouvelles connexions : suivre Procédure manuelle §2.
Contrôle de santé / Vérification¶
# Services
systemctl is-active guacd tomcat9 mariadb httpd fail2ban firewalld
# Ports en écoute — vérifier en particulier le bind de guacd et MariaDB
ss -tlnp | grep -E ':4822|:3306|:443'
# Politique firewalld effective
firewall-cmd --get-default-zone
firewall-cmd --list-all
# fail2ban (attendu : inactif, cf. Points d'attention)
fail2ban-client status
# SAN du certificat servi réellement (pas seulement présent sur disque)
openssl s_client -connect 10.100.2.244:443 -servername bastion.infra.indio </dev/null 2>/dev/null \
| openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
# Test des identifiants par défaut (lecture seule stricte : le token est
# immédiatement révoqué après vérification, jamais utilisé pour agir)
TOKEN=$(curl -sk -X POST https://10.100.2.244/guacamole/api/tokens \
-d 'username=guacadmin&password=guacadmin' | python3 -c "import json,sys;print(json.load(sys.stdin).get('authToken',''))")
[ -n "$TOKEN" ] && echo "guacadmin/guacadmin fonctionne encore" \
&& curl -sk -X DELETE "https://10.100.2.244/guacamole/api/tokens/$TOKEN"
Non ré-exécuté en direct lors de la rédaction de cette page
Dernière confirmation live connue : 2026-07-12 (audit complet) et
2026-07-16 (utilisation implicite du compte lors de l'ajout
d'INDSERV026). Une tentative de re-vérification a été faite lors de
la rédaction de cette page (2026-07-19) mais le nœud de contrôle utilisé
pour cette session de documentation n'avait de route réseau que vers le
segment management (10.15.100.0/26) — aucune route vers seg-identite
ni vers la VIP Vault (10.100.2.130, elle aussi injoignable au même
moment), confirmant une limitation de connectivité de cette session
plutôt qu'un problème spécifique à ce composant. Aucune remédiation
n'est mentionnée dans l'historique du projet entre le 07-16 et
aujourd'hui — le finding doit être considéré comme toujours valide par
défaut jusqu'à revérification.
Points d'attention¶
guacadmin / guacadmin — identifiants par défaut actifs (dernière confirmation : 2026-07-12)
Le compte administrateur par défaut du produit fonctionnait encore lors
du dernier audit (POST /guacamole/api/tokens → HTTP 200 + authToken
valide, révoqué immédiatement après test). Ce bastion stocke 55
connexions dont vCenter, NSX Manager, les nœuds Edge, le witness vSAN,
les deux contrôleurs de domaine AD en RDP, GitLab, Nexus, le nœud de
contrôle lui-même, Horizon, et quasi toute la flotte IND* en SSH —
un accès à ce compte équivaut potentiellement à un accès à
l'intégralité de l'infrastructure. Un seul compte Guacamole existe
(guacadmin) : pas de comptes nominatifs, donc aucune imputabilité
individuelle malgré la bannière SSH « toute connexion est journalisée ».
C'est la remédiation la plus urgente actuellement identifiée dans toute
l'infrastructure Indio.
remote_hosttoujours127.0.0.1dansguacamole_connection_history— le reverse-proxy Apache ne transmet pas l'IP client réelle à Tomcat (pas deRemoteIpValve/X-Forwarded-Forexploité côté Tomcat). L'audit trail ne permet donc pas de savoir d'où vient réellement une connexion — gap d'auditabilité significatif pour un bastion dont la raison d'être est la traçabilité des accès.- Aucun enregistrement de session (
recording-path) configuré sur aucune des 55 connexions — pas de rejouabilité a posteriori des sessions RDP/SSH passées par le bastion. - Pas de MFA/TOTP — seule l'extension
guacamole-auth-jdbc-mysql-1.6.0.jarest chargée. guacd(4822) et MariaDB (3306) écoutent sur0.0.0.0au lieu de127.0.0.1— protégés uniquement par firewalld (zonedrop), pas par un bind localhost. Risque concret car la zone admin NSX est en DFW default-ALLOW (voir NSX) : toute VM compromise dans la zone admin pourrait tenter une connexion directe àguacd(protocole interne non authentifié par nature) ou à MariaDB, en contournant entièrement l'authentification web de Guacamole.- Le mot de passe MySQL de
guacamole.propertiesréutilise le mot de passe standard de toute la flotte au lieu d'un mot de passe dédié à cette base applicative (valeur non reproduite ici, voir Gestion des secrets) — un secret partagé avec des dizaines d'autres usages pour une base qui, si elle fuite, exposerait aussi les paramètres de connexion (hôtes, identifiants) des 55 cibles. - Certificat TLS auto-signé sans SAN (
CN=bastion.infra.indio) alors qu'une CA interne Vault existe déjà et pourrait émettre un certificat propre — voir Vault & PKI. Aucune raison technique de ne pas migrer ce vhost vers cette PKI. fail2baninactif — pas de protection anti-bruteforce sur le login web Guacamole (le SSH de la VM elle-même aMaxAuthTries 4via le hardening standard du template, ce point-là est correct).- Points corrects/bien faits : SELinux enforcing, firewalld zone
dropscopée, TLS moderne (TLSv1.2/1.3uniquement) + en-têtes de sécurité (HSTS,X-Frame-Options, etc.) sur le vhost Apache, compte MariaDB applicatif strictement scopé àguacamole_db(pas de droits globaux),root@localhostMariaDB en authentification socket-only. - Accès réseau vers la zone SOC résolu le 2026-07-15 (voir Architecture)
— pattern à réutiliser pour tout futur accès bastion → zone restreinte :
un groupe NSX scopé à l'IP précise du bastion, jamais un élargissement de
toute
seg-identite, tant que le findingguacadminci-dessus reste ouvert. - Pattern d'ajout de connexion (Procédure manuelle §2) à documenter
soigneusement à chaque usage tant qu'aucun IaC n'existe pour ce
composant — c'est la seule trace de configuration qui subsiste en dehors
de la base
guacamole_dbelle-même.