Autentica Guacamole contra LDPA o Active Directory con Docker Compose


Apache Gucamole es una herramienta que sirve como puerta de enlace sin complementos ni software de cliente para protocolos estándar como VNC, RDP y SSH. Y todo esto desde el navegador web gracias a HTML5. Hay multitud de páginas que indican como instalar Apache Guacamole, aunque una de las formas más interesantes es mediante Docker Compose. El problema es que prácticamente la documentación de cómo conseguir desplegar Apache Guacamole con Docker Compose y que se autentique contra LDAP o el Active Directory es casi nula, constándonos varios días a mi compañero y a mí hasta hacerlo funcionar.

Instalación básica Apache Guacamole con Docker Compose

Para poder realizar el despliegue, tenemos que tener en cuenta las siguientes premisas:

  1. Tener instalado Docker
  2. Tener corriendo Docker compose
  3. Git
  4. Hacerlo desde un sistema Linux* y tener openssl.

*En el caso de hacerlo con Windows, hay que tener openssl instalado y realizar algunas pequeñas modificaciones en el fichero prerare.sh que comentaré más adelante.

Gracias a boschkundendienst tenemos su proyecto guacamole-docker-compose que explica como con 4 comandos podemos desplegar nuestro primer Apache Guacamole.
Estos comandos son:

git clone "https://github.com/boschkundendienst/guacamole-docker-compose.git"
cd guacamole-docker-compose
./prepare.sh
docker-compose up -d

Y ya tendríamos Apache Guacamole disponible en https://tuIP:8443/. El usuario por defecto es guacadmin y la contraseña por defecto es guacadmin.

docker-compose.yml

Aunque en la página de github del proyecto de BoschKindendienst explica el fichero Docker-componse.yml, y la estructura, os lo detallo:

Redes

La siguiente parte de docker-compose.yml creará una red con nombre guacnetwork_composeen en modo puente(bridged)

...
# networks
# create a network 'guacnetwork_compose' in mode 'bridged'
networks:
  guacnetwork_compose:
    driver: bridge
...

Servicios

Guacd

La siguiente parte de docker-compose.yml creará el servicio guacd. guacd es el corazón de Guacamole que carga dinámicamente soporte para protocolos de escritorio remoto llamados “complementos de cliente» (client plugins) y los conecta a escritorios remotos según las instrucciones recibidas de la aplicación web. El contenedor se llamará guacd_compose basado en la imagen de Docker guacamole/guacd conectada a nuestra red creada previamente guacnetwork_compose. Además, mapeamos las 2 carpetas locales ./drive y ./record en el contenedor. Podemos usarlos más tarde para mapear unidades de usuario y almacenar datos de sesiones.

...
services:
  # guacd
  guacd:
    container_name: guacd_compose
    image: guacamole/guacd
    networks:
      guacnetwork_compose:
    restart: always
    volumes:
    - ./drive:/drive:rw
    - ./record:/record:rw
...
PostgreSQL

La siguiente parte de docker-compose.yml creará una instancia de PostgreSQL usando la imagen oficial de docker. Esta imagen es configurable usando variables de entorno. Por ejemplo, inicializará una base de datos si se encuentra un script de inicialización en la carpeta /docker-entrypoint-initdb.d dentro de la imagen. Dado que asignamos la carpeta local ./init dentro del contenedor, docker-entrypoint-initdb.d podemos inicializar la base de datos para guacamole usando nuestro propio script ( ./init/initdb.sql).

...
  postgres:
    container_name: postgres_guacamole_compose
    environment:
      PGDATA: /var/lib/postgresql/data/guacamole
      POSTGRES_DB: guacamole_db
      POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
      POSTGRES_USER: guacamole_user
    image: postgres
    networks:
      guacnetwork_compose:
    restart: always
    volumes:
    - ./init:/docker-entrypoint-initdb.d:ro
    - ./data:/var/lib/postgresql/data:rw
...
Guacamole

La siguiente parte de docker-compose.yml creará una instancia de guacamole mediante el uso de la imagen Docker guacamole desde docker hub. Esta imagen también es configurable y aquí es donde más adelante explicaremos como configurar la autenticación contra un LDAP o Active Directory mediante variables de entorno. En este fichero, está configurado para conectarse a la instancia de postgres creada previamente utilizando un nombre de usuario y contraseña y la base de datos guacamole_db. El puerto 8080 solo está expuesto localmente. En el siguiente punto se explica la instancia nginx para su acceso público.

...
  guacamole:
    container_name: guacamole_compose
    depends_on:
    - guacd
    - postgres
    environment:
      GUACD_HOSTNAME: guacd
      POSTGRES_DATABASE: guacamole_db
      POSTGRES_HOSTNAME: postgres
      POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
      POSTGRES_USER: guacamole_user
    image: guacamole/guacamole
    links:
    - guacd
    networks:
      guacnetwork_compose:
    ports:
    - 8080/tcp
    restart: always
...
nginx

La última parte de docker-compose.yml creará una instancia de nginx que asigna el puerto público 8443 al puerto interno 443. Luego, el puerto interno 443 se asigna a guacamole utilizando los archivos ./nginx.conf y ./nginx/mysite.template. El contenedor utilizará el certificado autofirmado generado con prepare.sh previamente en ./nginx/ssl/ con ./nginx/ssl/self-ssl.key y ./nginx/ssl/self.cert.

...
  nginx:
   container_name: nginx_guacamole_compose
   restart: always
   image: nginx
   volumes:
   - ./nginx/ssl/self.cert:/etc/nginx/ssl/self.cert:ro
   - ./nginx/ssl/self-ssl.key:/etc/nginx/ssl/self-ssl.key:ro
   - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
   - ./nginx/mysite.template:/etc/nginx/conf.d/default.conf:ro
   ports:
   - 8443:443
   links:
   - guacamole
   networks:
     guacnetwork_compose:
   # run nginx
   command: /bin/bash -c "nginx -g 'daemon off;'"
...

prepare.sh

prepare.sh es un pequeño script para crear ./init/initdb.sql descargando la imagen docker guacamole/guacamole. Lo inicia así:

docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgres > ./init/initdb.sql

Esto crea el archivo de inicialización de base de datos necesario para postgres.

prepare.sh también crea el certificado autofirmado ./nginx/ssl/self.cert y la clave privada ./nginx/ssl/self-ssl.key que utiliza nginx para https.

Si ejecutamos Docker compose desde Windows, este fichero hay que adaptarlo, ya que está pensado con instrucciones de Linux.

reset.sh

Si deseamos restablecer todo de nuevo, únicamente ejecutaremos ./reset.sh.

Autenticación con LDAP o Active Directoy

Aquí el kit de la cuestión de este post y que tantos días nos llevó hasta conseguir hacerlo funcionar. Seguramente porque aún somos un poco novatos en el mundo del Docker y Docker-compose.

Lo primero (aunque fue de lo último que encontramos, porque todas nuestras búsquedas se basaban en docker-compose) es que en la página siguiente de documentación oficial de Apache Guacamole nos indica como pasar las variable para la autenticación de LDAP, o en nuestro caso para Active Directory. Estas variables son:

VariableDescripción
LDAP_HOSTNAMEEl nombre de host o la dirección IP de su servidor LDAP.
LDAP_USER_BASE_DNLa base del DN para todos los usuarios de Guacamole. Todos los usuarios de Guacamole que se autenticarán contra LDAP deben ser descendientes de este DN base.
LDAP_PORTEl puerto en el que escucha su servidor LDAP. De forma predeterminada, será 389 para LDAP sin cifrar o LDAP con STARTTLS y 636 para LDAP sobre SSL (LDAPS).
LDAP_ENCRYPTION_METHODEl mecanismo de encriptación que debe usar Guacamole al comunicarse con su servidor LDAP. Los valores legales son «ninguno» para LDAP sin cifrar, «ssl» para LDAP sobre SSL/TLS (comúnmente conocido como LDAPS) o «starttls» para STARTTLS. Si se omite, no se utilizará el cifrado.
LDAP_GROUP_BASE_DNLa base del DN para todos los grupos a los que se puede hacer referencia dentro de las configuraciones de Guacamole usando el atributo estándar seeAlso . Todos los grupos que se usarán para controlar el acceso a las configuraciones de Guacamole deben ser descendientes de este DN base. Si se omite esta variable, el atributo seeAlso no tendrá efecto en las configuraciones de Guacamole.
LDAP_SEARCH_BIND_DNEl DN (Nombre Distinguido) del usuario para vincular al autenticar a los usuarios que intentan iniciar sesión. Si se especifica, Guacamole consultará el directorio LDAP para determinar el DN de cada usuario que inicia sesión. Si se omite, el DN de cada usuario será derivado directamente usando el DN base especificado con LDAP_USER_BASE_DN.
LDAP_SEARCH_BIND_PASSWORDLa contraseña para proporcionar al servidor LDAP cuando se vincula LDAP_SEARCH_BIND_DNpara autenticar a otros usuarios. Esta variable solo se utiliza si LDAP_SEARCH_BIND_DNse especifica. Si se omite, pero LDAP_SEARCH_BIND_DNse especifica, Guacamole intentará vincularse con el servidor LDAP sin contraseña.
LDAP_USERNAME_ATTRIBUTEEl atributo o atributos que contienen el nombre de usuario dentro de todos los objetos de usuario de Guacamole en el directorio LDAP. Habitualmente, y por defecto, será simplemente » uid «. Si su directorio LDAP contiene usuarios cuyos nombres de usuario están dictados por diferentes atributos, se pueden especificar múltiples atributos aquí, separados por comas, pero tenga cuidado: hacerlo requiere que se proporcione un DN de búsqueda con LDAP_SEARCH_BIND_DN .
LDAP_CONFIG_BASE_DNLa base del DN para todas las configuraciones de Guacamole. 
Si se omite, las configuraciones de las conexiones de Guacamole simplemente no se consultarán desde el directorio LDAP y deberá almacenarlas en otro lugar, como dentro de una base de datos MySQL o PostgreSQL.

Sabiendo el significado de estas variables, ya podemos configurar nuestro docker-compose.yml en el apartado de Guacamole de este modo:

...
  guacamole:
    container_name: guacamole_compose
    depends_on:
    - guacd
    - postgres
    environment:
      GUACD_HOSTNAME: guacd
      POSTGRES_DATABASE: guacamole_db
      POSTGRES_HOSTNAME: postgres
      POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
      POSTGRES_USER: guacamole_user
      LDAP_HOSTNAME: DIRECCIÓN_IP_CONTROLADOR_DE_DOMINIO
      LDAP_PORT: 389 # O seguro: 636
      LDAP_USER_BASE_DN: OU=ruta,DC=dominio,DC=local
      LDAP_USERNAME_ATTRIBUTE: samAccountName
      LDAP_CONFIG_BASE_DN: OU=ruta,DC=dominio,DC=local
      LDAP_ENCRYPTION_METHOD: none # O seguro: ssl, starttls
      LDAP_SEARCH_BIND_DN: cn=usuario_LDAP,OU=ruta,DC=dominio,DC=local
      LDAP_SEARCH_BIND_PASSWORD:CONTRASEÑA
    image: guacamole/guacamole
    links:
    - guacd
    networks:
      guacnetwork_compose:
    ports:
    - 8080/tcp
    restart: always
...

Para estar seguro que esto funciona, podemos acceder a la máquina guacamole_compose y ejecutar el siguiente comando para ver si se ha añadido la configuración de LDAP al fichero guacamole.properties:

$ cat /home/guacamole/.guacamole/guacamole.properties

Y podremos ver el contenido del fichero guacamole.properties

# guacamole.properties - generated Sat Dec  3 04:12:02 PM UTC 2022
guacd-hostname: guacd
guacd-port: 4822
postgresql-username: guacamole_user
postgresql-password: XXXXX
postgresql-database: guacamole_db
postgresql-hostname: postgres
postgresql-port: 5432
ldap-hostname: 192.168.55.1
ldap-user-base-dn: OU=ruta,DC=dominio,DC=local
ldap-port: 389
ldap-encryption-method: none
ldap-search-bind-dn: cn=usuario_LDAP,OU=ruta,DC=dominio,DC=local
ldap-search-bind-password: CONTRASEÑA
ldap-username-attribute: samAccountName
ldap-config-base-dn: OU=ruta,DC=dominio,DC=local

Ahora ya solo falta crear un usuario en Apache Guacamole con el mismo nombre de usuario que en el Active Directory o LDAP y no ponerle contraseña y a funcionar!

Doble factor en Guacamole

En Guacamole existen dos formas de gestión de la autenticación en dos pasos (2FA). En nuestro caso, hemos activado extensión de autenticación TOTP que permite que los usuarios sean verificados adicionalmente contra una clave secreta y específica del usuario generada durante el registro de su dispositivo de autenticación. Es el mismo sistema que ya he explicado en otro post para ponerlo en Facebook, Instagram, Twitter mediante Microsoft Authenticator.

Para activarlo para todos los usuarios, únicamente hay que añadir TOTP_ENABLED: ‘true’ en el fichero docker-compose.yml en la sección de Guacamole:

...
  guacamole:
    container_name: guacamole_compose
    depends_on:
    - guacd
    - postgres
    environment:
      GUACD_HOSTNAME: guacd
      POSTGRES_DATABASE: guacamole_db
      POSTGRES_HOSTNAME: postgres
      POSTGRES_PASSWORD: ChooseYourOwnPasswordHere1234
      POSTGRES_USER: guacamole_user

      TOTP_ENABLED: 'true'
      LDAP_HOSTNAME: DIRECCIÓN_IP_CONTROLADOR_DE_DOMINIO
      LDAP_PORT: 389 # O seguro: 636
      LDAP_USER_BASE_DN: OU=ruta,DC=dominio,DC=local
      LDAP_USERNAME_ATTRIBUTE: samAccountName
      LDAP_CONFIG_BASE_DN: OU=ruta,DC=dominio,DC=local
      LDAP_ENCRYPTION_METHOD: none # O seguro: ssl, starttls
      LDAP_SEARCH_BIND_DN: cn=usuario_LDAP,OU=ruta,DC=dominio,DC=local
      LDAP_SEARCH_BIND_PASSWORD:CONTRASEÑA
    image: guacamole/guacamole
    links:
    - guacd
    networks:
      guacnetwork_compose:
    ports:
    - 8080/tcp
    restart: always
...

Cambiar guacadmin

Y por supuesto, OBLIGATORIO crear otro usuario administrador que no sea guacadmin o cambia la contraseña por defecto guacadmin por otra. Si yo accediese a un Guacamole ajeno, lo primero que probaría seria guacadmin / guacadmin.

Enlaces


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Últimos posts

Extraer archivos adjuntos de un fichero EML

Extraer archivos adjuntos de un fichero EML

Dic 16, 2022

Siguiendo con los retos de la página de desafíos que ya comentaba en un post anterior, me encontré con examinar…