Authelia – Une solution de SSO pour vos microservices

 

Je vous ai présenté, à travers plusieurs articles, Keycloak, comme étant une solution de SSO pour des applications, utilisant notamment le standard OIDC (OpenID Connect).

Nous allons voir aujourd'hui une solution similaire, que je trouve, pour ma part, plus léger et plus simple à mettre en place. Et cette solution se nomme : Authelia !

Authelia agit comme une "extension" à un reverse proxy, en voici les principaux :

  • Traefik

  • Nginx

  • HAProxy

 

À l'heure actuelle l'intégration avec Apache2 n'est malheureusement pas possible, voici l'explication fournie par la documentation :

Apache has no module that supports this kind of authentication method. It’s not certain this would even be possible, however if anyone did something like this in the past we’d be interested in a contribution.

Dans cet article nous allons installer Authelia en conteneur, avec Traefik. À noter que la version de Traefik utilisée est la suivante : traefik:2.4.

 

Installation

Vous aurez besoin de quatre entrées DNS à faire, pointant sur votre instance :

  • authelia.yourdomain.fr.

  • public.yourdomain.fr.

  • traefik.yourdomain.fr.

  • secure.yourdomain.fr.

 

Cloner le projet GitHub :

git clone https://github.com/authelia/authelia.git
cd authelia/examples/compose/lite
git checkout $(git describe --tags 'git rev-list --tags --max-count=1')

 

Préparer le fichier de configuration authelia/examples/compose/lite/authelia/configuration.yml avec notamment :

default_redirection_url: https://public.yourdomain.fr
...
access_control:
  default_policy: deny
  rules:
    # Rules applied to everyone
    - domain: public.yourdomain.fr
      policy: bypass
    - domain: traefik.yourdomain.fr
      policy: one_factor
    - domain: secure.yourdomain.fr
      policy: two_factor
...
session:
...
  domain: yourdomain.fr
...
### Si vous n'avez pas de SMTP configuré :
notifier:
  disable_startup_check: false
  filesystem:
    filename: /config/notification.txt

 

Et voici le joli docker-compose.yml :

---
version: '3.3'

networks:
  net:
    driver: bridge

services:
  authelia:
    image: authelia/authelia
    container_name: authelia
    volumes:
      - ./authelia:/config
    networks:
      - net
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.authelia.rule=Host(`authelia.yourdomain.fr`)'
      - 'traefik.http.routers.authelia.entrypoints=https'
      - 'traefik.http.routers.authelia.tls=true'
      - 'traefik.http.routers.authelia.tls.certresolver=letsencrypt'
      - 'traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://authelia.yourdomain.fr'  # yamllint disable-line rule:line-length
      - 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true'
      - 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email'  # yamllint disable-line rule:line-length
    expose:
      - 9091
    restart: unless-stopped
    healthcheck:
      disable: true
    environment:
      - TZ=Australia/Melbourne

  redis:
    image: redis:alpine
    container_name: redis
    volumes:
      - ./redis:/data
    networks:
      - net
    expose:
      - 6379
    restart: unless-stopped
    environment:
      - TZ=Australia/Melbourne

  traefik:
    image: traefik:2.4
    container_name: traefik
    volumes:
      - ./traefik:/etc/traefik
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - net
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.api.rule=Host(`traefik.yourdomain.fr`)'
      - 'traefik.http.routers.api.entrypoints=https'
      - 'traefik.http.routers.api.service=api@internal'
      - 'traefik.http.routers.api.tls=true'
      - 'traefik.http.routers.api.tls.certresolver=letsencrypt'
      - 'traefik.http.routers.api.middlewares=authelia@docker'
    ports:
      - 80:80
      - 443:443
    command:
      - '--api'
      - '--providers.docker=true'
      - '--providers.docker.exposedByDefault=false'
      - '--entrypoints.http=true'
      - '--entrypoints.http.address=:80'
      - '--entrypoints.http.http.redirections.entrypoint.to=https'
      - '--entrypoints.http.http.redirections.entrypoint.scheme=https'
      - '--entrypoints.https=true'
      - '--entrypoints.https.address=:443'
      - '--certificatesResolvers.letsencrypt.acme.email=email@yourdomain.fr'
      - '--certificatesResolvers.letsencrypt.acme.storage=/etc/traefik/acme.json'
      - '--certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint=http'
      - '--log=true'
      - '--log.level=DEBUG'

  secure:
    image: traefik/whoami
    container_name: secure
    networks:
      - net
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.secure.rule=Host(`secure.yourdomain.fr`)'
      - 'traefik.http.routers.secure.entrypoints=https'
      - 'traefik.http.routers.secure.tls=true'
      - 'traefik.http.routers.secure.tls.certresolver=letsencrypt'
      - 'traefik.http.routers.secure.middlewares=authelia@docker'
    expose:
      - 80
    restart: unless-stopped

  public:
    image: traefik/whoami
    container_name: public
    networks:
      - net
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.public.rule=Host(`public.yourdomain.fr`)'
      - 'traefik.http.routers.public.entrypoints=https'
      - 'traefik.http.routers.public.tls=true'
      - 'traefik.http.routers.public.tls.certresolver=letsencrypt'
      - 'traefik.http.routers.public.middlewares=authelia@docker'
    expose:
      - 80
    restart: unless-stopped

 

Concrètement, voici le rôle des différents services :

  • Authelia : Le gestionnaire d'authentification

  • Redis : Stockage de données en mode clé-valeur

  • Traefik : Le reverse-proxy pour conteneur(s)

  • Secure : Exemple d'application (en l'occurence Whoami (https://hub.docker.com/r/containous/whoami) pour démontrer l'authentification 'two_factor')

  • Public : Exemple d'application (en l'occurence Whoami (https://hub.docker.com/r/containous/whoami) pour démontrer l'authentification 'one_factor')

 

On démarre le conteneur :

cd authelia/examples/compose/lite
docker-compose up -d

 

Allons tout d'abord sur le panel Authelia :

 

 

Les identifiants par défaut sont : authelia / authelia.

 

 

Vous êtes alors invité à configurer l'authentification en deux facteurs. Nous avons testé via OTP (à travers l'application Authy) et via YubiKey (notamment avec la version biométrique). Cliquez sur Register device, le lien pour ajouter l'appareil vous sera soit envoyé par email, ou dans le fichier suivant : authelia/examples/compose/lite/authemlia/notification.txt :

 

Date: 2021-11-04 01:33:11.592220184 +1100 AEDT m=+3124.704944362
Recipient: authelia@authelia.com
Subject: Register your mobile
Body: 
This email has been sent to you in order to validate your identity.
If you did not initiate the process your credentials might have been compromised. You should reset your password and contact an administrator.

To setup your 2FA please visit the following URL: https://authelia.yourdomain.fr/one-time-password/register?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZWxpYSIsImV4cCI6MTYzNTk1MDI5MSwiYWN0aW9uIjoiUmVnaXN0ZXJUT1RQRGV2aWNlIiwidXNlcm5hbWUiOiJhdXRoZWxpYSJ9.8DNABo4Z7ftH9Y25d3mtqzjPRpOZi6GdpriVSCAbT5M

Please contact an administrator if you did not initiate the process.

 

 

Ajouter une application

Supposons que nous avons une application web toute simple, on va ajouter un conteneur web Nginx utilisant cette image : https://hub.docker.com/r/yeasy/simple-web/

On va devoir rajouter une entrée DNS pour cette app : app1.yourdomain.fr par exemple. Puis rajouter ceci dans le docker-compose.yml :

  app1:
    image: yeasy/simple-web
    container_name: app1   
    networks:
      - net
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.app1.rule=Host(`app1.yourdomain.fr`)'
      - 'traefik.http.routers.app1.entrypoints=https'
      - 'traefik.http.routers.app1.tls=true'
      - 'traefik.http.routers.app1.tls.certresolver=letsencrypt'
      - 'traefik.http.routers.app1.middlewares=authelia@docker'

 

Ensuite, il faut choisir le mode d'authentification pour cette nouvelle application (voir : https://www.authelia.com/docs/configuration/access-control.html) ; pour l'exemple nous allons choisir two_factor. Dans authelia/examples/compose/lite/authelia/configuration.yml :

access_control:
  ...
  rules:
  ...
    - domain: app1.yourdomain.fr
      policy: two_factor

Et c'est tout ! Redémarrer les services :

docker-compose down && docker-compose up -d

 

En lecture complémentaire, voici les précédents articles émanant de l'approche du SSO : 

- Comment nous avons créé une architecture SSO : Nextcloud + Keycloak + YubiKey
- Les différents modes d'authentification sous Keycloak