Pourquoi Authelia ?

Nous avons vu dans une série d'articles précédents comment configurer Traefik et différents services afin de les exposer publiquement. De plus, l'aspect authentification a été abordé dans l'article précédent avec le mTLS.

Cependant, si je souhaite répondre à la question suivante :

Comment authentifier différents types d'utilisateurs et gérer de manière personnalisée leurs accès ?

Je remarque que le mTLS n'est pas adapté dans cette situation.

C'est pourquoi, je vais vous présenter Authelia qui permet, en plus de répondre à la problématique du dessus, de sécuriser rapidement et efficacement nos services web grâce à une authentification simple (couple nom d'utilisateur/mot de passe) voire même renforcée (utilisation d'un deuxième facteur d'authentification).

Je trouve que l'utilisation d'Authelia couplée à celle de Traefik est assez simple à mettre en oeuvre comme nous le verrons à la suite de cet article et idéale pour un usage personnel.

Présentation

Tout d'abord, Authelia est un outil open-source qui agit comme un portail où l'utilisateur est invité à s'authentifier.

Une fois connecté, Authelia permet de gérer si un utilisateur peut accéder ou non à des ressources données avec une granularitée assez fine sur l'url. Par exemple, on peut permettre à l'utilisateur de se connecter à un nom de domaine, tout en interdisant à celui-ci d'accéder à un dossier spécifique (/admin).

Pour l'instant, l'interface graphique d'Authelia est très minimaliste. Elle se compose d'une mire d'authentification et quelques options (réinitiliser son mot de passe, paramétrer son deuxième facteur d'authentification, etc.). L'essentiel de la configuration se fait donc via des fichiers.

Cet outil gère jusqu'à deux facteurs d'authentification et permet d'utiliser une connexion unique (SSO) à travers l'ensemble des applications configurées à travers celui-ci.

Enfin, Authelia s'intègre facilement avec les outils de type proxy inverse (reverse proxy) tels que Traefik, NGINX voire même HAProxy comme vous pouvez le voir sur l'architecture ci-dessous :

authelia-architecture

Mise en place

Avant de commencer

L'exemple dans lequel Authelia sera utilisé est celui de la sécurisation d'applications de supervision (Prometheus et Grafana). La configuration spécifique de ces outils est détaillée dans cet article que je vous invite à lire si ce n'est pas déjà fait.

Configuration et explications

Le code du projet à cloner est disponible ci-dessous via mon compte Github.

https://github.com/axinorm/traefik-authelia

L'ensemble de la configuration d'Authelia se trouve dans le dossier du même nom.

Le configuration.yml.j2 regroupe la configuration globale d'authelia, la documentation officielle permet de modifier/enrichir celle-ci.

authentication_backend:
  file:
    path: /config/users_database.yml

Le bloc ci-dessus permet d'indiquer où seront stockés les utilisateurs, dans ce cas d'utilisation, il s'agit d'un fichier YAML dans lequel un utilisateur filador a été créé avec comme mot de passe filadorpassword, or celui-ci est hashé pour des raisons de sécurité.

A la place de ce fichier, il est bien évidemment possible de configurer un annuaire LDAP.

Si vous souhaitez changer le mot de passe de l'utilisateur, il suffit de faire cette commande pour récupérer le hash :

docker run authelia/authelia:latest authelia hash-password <mot de passe>

On remarque aussi que l'on peut définir un email, qui est utile si jamais l'utilisateur veut réinitialiser son mot de passe, et on peut définir des groupes qui permettront de donner des accès à certaines applications.

Dans notre cas d'utilisation, le but est d'interdire à un utilisateur anonyme l'ensemble de nos outils de supervision et de permettre uniquement à ceux du groupe admins d'y accéder. Ce qui va se schématiser par ce bloc :

access_control:
  default_policy: deny
  rules:
    - domain: admin.{{ url_traefik }}
      resources:
        - "^/prometheus.*$"
        - "^/grafana.*$"
        - "^/traefik.*$"
        - "^/api.*$" # For Traefik
      subject:
        - "group:admins"
      policy: one_factor

On interdit deny tout accès sauf pour le nom de domaine admin.{{ url_traefik }} et aux ressources concernées (ce sont les chemins que l'on retrouve dans l'url après le nom de domaine) uniquement pour les utilisateurs du groupe admins avec un seul facteur d'authentification (nom d'utilisateur et mot de passe).

Pour pouvoir accéder au tableau de bord de Traefik il est important d'autoriser l'api ^/api.*$ qui est indépendante de l'interface.

session:
  name: authelia_session
  secret: unsecure_session_secret
  expiration: 3600 # 1 hour
  inactivity: 300 # 5 minutes
  domain: {{ url_traefik }} 

Ici, on configure la session accordée par Authelia, sa durée, le temps d'inactivité où l'on sera automatiquement déconnecté, etc.

regulation:
  max_retries: 3
  find_time: 120
  ban_time: 300

Un peu à la manière de fail2ban, authelia intègre un système permettant de limiter le nombre d'échec d'authentification et de bannir une ip le cas échéant.

Le stockage est effectué par défaut via une base de données sqlite3 mais Authelia permet d'utiliser aussi bien du MariaDB, MySQL ou encore PostgeSQL.

Côté docker-compose.yml.j2, on retrouve nos composants de supervision ainsi que Traefik mais aussi et surtout la définition de notre nouveau service avec ces trois lignes, qui permettent d'ajouter un middleware au sein de Traefik et de rediriger les connexions vers Authelia :

- "traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://authelia.{{ url_traefik }}"
- "traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email"

Après avoir défini Authelia, il reste à ajouter le middleware dans les services que l'on veut sécuriser, on prend ici le cas de Grafana :

- "traefik.http.routers.grafana.middlewares=authelia@docker,grafana-stripprefix"

Petite remarque sur l'ordre des middlewares lors de la définition de service avec un PathPrefix, ce dernier doit toujours être à la fin pour que Authelia puisse rediriger correctement.

Génération de la configuration

Avant de pouvoir exécuter notre docker-compose, il faut pouvoir l'initialiser en fonction de notre environnement, cela passe par plusieurs étapes.

Nous allons donc générer différents fichiers grâce à la librairie jinja2 avec le langage python.

Tout d'abord, il faut l'installer :

virtualenv .venv
source .venv/bin/activate
pip install jinja2

Puis, configurer les variables d'environnement :

export TM_SERV_OS=linux
export TM_SERV_ARCH=arm
export TM_URL_TRAEFIK=example.com

Et enfin, générer le fichier docker-compose et les fichiers de configuration :

python3 generate_compose_file.py

Lancement du docker-compose

Après la génération des différents fichiers ci-dessus, il ne reste plus qu'une seule commande à exécuter :

docker-compose up -d

Et maintenant essayons d'accéder à Grafana en allant sur
https://admin.<nom de domaine défini>/grafana.

On remarque que l'on est redirigé automatiquement vers la mire d'authentification d'Authelia pour se connecter :

authelia-portail-authentification

Une fois notre utilisateur renseigné, on peut accéder à notre tableau de bord Grafana :

authelia-grafana

Conclusion et pour aller plus loin

L'ensemble des points positifs d'Authelia ont été cités au début de cet article, et nous avons pu voir la simplicité de configuration d'Authelia.

Si jamais vous voulez aller plus loin, il est possible de :

  • Configurer le bloc access_control avec plusieurs noms de domaine ;
  • Enrichir sur les permissions de groupe ou même d'autoriser les accès uniquement avec un deuxième facteur d'authentification ;
  • Ajouter des services au docker-compose.