Journal Sortie de Glewlwyd 2.0, serveur SSO

Posté par  (site Web personnel) . Licence CC By‑SA.
14
3
nov.
2019

Glewlwyd, serveur SSO polyvalent, est maintenant disponible en version 2.0 sur les interwebs!

https://babelouest.github.io/glewlwyd/

Je reprends une partie de l'ancien journal écrit pour la sortie de la RC2, mais celui-ci est bien plus détaillé pour les curieux.

Installer

Paquets pour certaines distributions

Des paquets pour certaines distributions Linux sont disponibles ici: https://github.com/babelouest/glewlwyd/releases/tag/v2.0.0

Image Docker

Une image Docker est disponible ici pour tester rapidement, ou pour utiliser en vrai, juste en modifiant une option: https://hub.docker.com/r/babelouest/

Installation manuelle avec CMake

Sinon le manuel d'installation décrit comment recompiler ca sans stress: https://github.com/babelouest/glewlwyd/blob/master/docs/INSTALL.md

Présentation

Glewlwyd est un serveur d'authentification unique, autrement appelé Serveur SSO, qui implémente les protocoles OAuth2 et OpenID Connect.

Le backend est écrit en C, ce qui lui permet de fonctionner sur tout type de machine sans trop bouffer de ressources.

Il gère les utilisateurs et les clients stockés en base de données ou dans un LDAP.

Il nécessite une base de données pour fonctionner, au choix SQLite3, MariaDB/MySQL ou PostgreSQL.

Schémas d'authentification

Il gère également les schémas d'authentification multiples:

  • HOTP/TOTP
  • WebAuthn, supporte au moins:
    • les Yubikeys
    • les machines sous Android 7+ en s'authentifiant par code secret ou empreinte digitale
  • Mot de passe à usage unique envoyé par courriel
  • Certificats TLS avec possibilité d'émission de certificat PKCS#12

Architecture

Et il utilise une architecture à base de greffons pour ajouter, modifier ou supprimer plus facilement les backends ou sont stockés les utilisateurs ou les clients, les schémas d'authentification ou encore les plugins comme OAuth2.

Protocoles supportés

OAuth2

OAuth2 est le successeur d'OAuth, et est un framework de délégation d'authentification qui permet à un client de se connecter à un ou plusieurs serveurs de ressources au nom d'un utilisateur.

Le principe est le suivant: le client redirige l'utilisateur vers le serveur d'authentification unique en notifiant au serveur d'authentification qui est le client qui demande, et quels accès il demande. L'utilisateur s'authentifie, autorise ou non les accès au client selon ses droits, puis le serveur d'authentification redirige l'utilisateur vers le client avec une clé. Cette clé permet enfin au client d'accéder aux ressources demandées initialement.

OpenID Connect

La fondation OpenID est partie du standard OAuth2 et de ses propres expériences et solutions pour proposer le protocole OpenID Connect.
OpenID Connect est issu de OAuth2 mais n'en est pas pour autant interopérable. En fait, il a pris certains aspects d'OAuth2 qui l'intéresse, ignore des aspects qui ne l'intéresse pas (response types Resource Owner Password Credentials Grant et Client Credentials Grant), et a ajouté de nouvelles fonctionnalités pour étendre les possibilités.

La grosse nouveauté d'OpenID Connect (mais pas la seule) est le id_token, c'est un JWT permettant au client d'identifier l'utilisateur connecté et d'accéder à des informations de l'utilisateur comme son nom, son adresse courriel, son adresse postale, etc.

Autorisation

Glewlwyd fait de l'authentification mais aussi de l'autorisation car les access token générés par les plugins OAuth2 ou OpenID Connect sont également des JWT contenant une information minimale permettant d'identifier l'utilisateur connecté, ainsi que les niveaux d'accès autorisés par le serveur et l'utilisateur.

https://github.com/babelouest/glewlwyd/blob/master/docs/OAUTH2.md#access-token-format

Implémentations existantes

Beaucoup de fournisseurs de services en ligne proposent leur propre SSO: Google, Microsoft Azure, Apple, Twitter, AWS, la liste est longue.

Pour les libristes, il existe également beaucoup de produits libres que l'on peut utiliser chez soi: Gluu, Keycloak notamment pour ceux que je connais un peu.

Glewlwyd sans vouloir concurrencer les autres, veut apporter une alternative simple à installer et à utiliser, et propose des outils pour l'étendre plus facilement à ses besoins.

  • # Base de données

    Posté par  (site Web personnel) . Évalué à 4.

    Pourquoi il a besoin d'une base de données pour fonctionner ? Il aurait pas pu en utiliser une qui soit en cache RAM ? Que doit-il écrire sur le disque ?

    Sous jasent à ma question, il y a deux intérêts :

    • coté RGPD, plus c'est en RAM et moins c'est sur le disque et plus c'est "facile" de montrer qu'on ne conserve pas les données

    • coté Admin Système, plus c'est en RAM, moins il y a besoin de stockage persistent d'une instance à une autre en cas de reboot (VM OpenStack par exemple)

    Autre question, ton service est capable de se clusteriser ?

    • [^] # Re: Base de données

      Posté par  (site Web personnel) . Évalué à 2. Dernière modification le 04/11/19 à 14:38.

      Pourquoi il a besoin d'une base de données pour fonctionner ?

      Au hasard, pour stocker les utilisateurs, et leurs données sous-jacentes (nom, mot de passe, email..).

      J'ai du mal à imaginer ça dans un stockage non persistant…

      coté Admin Système, plus c'est en RAM, moins il y a besoin de stockage persistent d'une instance à une autre en cas de reboot

      Donc à chaque reboot, l'admin sys doit se taper le remplissage de sa base de donnée en RAM en y injectant les centaines d'utilisateurs potentiels ?

    • [^] # Re: Base de données

      Posté par  (site Web personnel) . Évalué à 2.

      Pourquoi il a besoin d'une base de données pour fonctionner ?

      J'avoue que je ne m'attendais pas à cette question.
      Pour faire simple, la base de données stocke au minimum:
      - La configuration des modules
      - Les hash et métadonnées des session utilisateurs
      - Les scopes et leurs facteurs d'authentification
      - Les hash de code et de tokens
      - Les configs de certains schémas d'authentification pour les utilisateurs

      Il aurait pas pu en utiliser une qui soit en cache RAM ?

      Entre deux redémarrages du service ou du serveur, il faut stocker un minimum d'informations pour ne pas avoir à perdre toute la config ou les données de session des utilisateurs. Cela dit, si tu veux une BD en RAM, tu peux monter un RAMDisk et y coller le fichier de BD SQLite3. Mais je doute que ca réponde à ton besoin.

      Pour la question sur le RGPD, je te laisse juge sur comment l'appliquer, c'est un domaine que je ne connais pas, mais je ne pense pas qu'avoir une base données qui s'efface à chaque redémarrage soit utile.

      Autre question, ton service est capable de se clusteriser ?

      En utilisant une base de données MariaDB ou PostgreSQL je dirais que oui, au final c'est un simple exécutable qui utilise la BD pour la persistance, donc une session ouverte depuis une instance de serveur Glewlwyd peut être utilisée par une autre instance par exemple. Le seul truc important à penser c'est de relancer le service sur chaque noeud si on a changé la configuration des instances de modules (ajouter ou modifier un schema d'authentification par exemple)

      Cela dit je n'ai pas essayé de le clusteriser donc ca se peut qu'il y ait des problèmes auxquels je n'ai pas pensé, dans ce cas je serai ravi de les corriger!
      Enfin, il faut aussi se poser la question de l'utilité de faire un cluster.
      Un serveur SSO est finalement peu sollicité en moyenne. Je suis un petit utilisateur de mon application donc chez moi ca tournerait sans problèmes sur un Raspberry Pi Zero, bien qu'il tourne en fait sur un Odroid C2.
      Si c'est pour répartir la charge ok, mais dans ce cas je suis curieux, pour combien d'utilisateurs et de clients?

      • [^] # Re: Base de données

        Posté par  (site Web personnel) . Évalué à 4. Dernière modification le 04/11/19 à 19:08.

        Je me pose toujours la question de la pertinence d'une BD qui stocke à la fois des paramètres de config et de session… En général, ce sont les mêmes identifiants qui permettent d'accéder aux deux alors que par exemple pour la config, seul un identifiant en lecture seule est utile dans 99% des cas et s'avèrent bien plus robuste aux attaques.

        Par ailleurs, je n'aime pas trop les config en base de donnée, cela ne se pousse pas trop facilement via cfengine, puppet, salt… Mais c'est une opinion personnelle. Pour la sauvegarde, c'est mieux aussi de mettre les trucs vraiment important séparés des trucs pas fondamental.

        A-t-on besoin d'une base de donnée relationnelle, donc avec transaction ? Si non, une base de donnée type Riak ou Etcd permet de clusteriser de manière quasi transparente. Si oui, a-t-on besoin des transactions sur toutes les tables ?

        Avec un service clusterisé, pas besoin de se fatiguer à gérer le reboot, d'où ma question en RAM. Si un des noeuds du cluster reboot, les deux autres (si à trois) assure le job. Si les trois noeuds tombent, alors les sessions tombent mais cela devrait arriver très rarement. Bref, la clusterisation solutionne des problèmes et peut en amener d'autres. Mais comme le restart pour le HPC, si on y pense pas dès le début, c'est pas toujours facile à ajouter après.

        Bonne continuation.

        • [^] # Re: Base de données

          Posté par  (site Web personnel) . Évalué à 5.

          Je me pose toujours la question de la pertinence d'une BD qui stocke à la fois des paramètres de config et de session

          Et c'est en effet une très bonne question, sauf qu'il faut voir l'application comme une boite noire qui expose une API REST.

          J'utilise la BD pour la configuration de certains aspects parce que c'est le meilleur moyen que j'ai trouvé pour avoir une configuration pérenne et dynamique, tout en gardant le principe KISS dans un coin de la tête.

          Glewlwyd utilise un fichier de config au format libconfig, ce fichier contient la configuration dite statique et hardcore de Glewlwyd, avec notamment l'url externe, le chemin local vers les fichiers statiques du front-end, le chmin local vers les modules ou encore la connexion vers base de données.

          Mais tout ce qui est configuration des modules: CRUD des modules backend utilisateurs ou clients, CRUD des plugins, CRUD des schémas d'authentification, tout se fait via l'interface graphique d'administration, parce que ces parties-là sont plus complexes à configurer et qu'une UI qui t'accompagne en te disant ce que tu as le droit de faire ou non, c'est plus simple à utiliser qu'un fichier de config à plat ou un fichier XML pour lequel il faut lire et comprendre la doc. Ca permet aussi d'avoir plein de modules qui "juste marchent" sans forcément avoir à tout comprendre, typiquement les schémas HOTP/TOTP ou Webauthn.

          Ensuite, il faut voir que la config en BD n'est lue qu'au démarrage de l'application, puis "mappée" en mémoire, ou rechargée lorsqu'on modifie la config via les API. Donc la question de distinguer la BD de config de la BD de session ne se pose pas trop non plus je pense.

          Et comme toute la config stockée en BD est accédée entièrement via les API REST, tu as la possibilité d'automatiser l'administration via des scripts qui font des appels HTTP à l'ancienne.

          A-t-on besoin d'une base de donnée relationnelle, donc avec transaction ?

          Ca aussi c'est une bonne question!

          Au début de mon ère néo-productiviste libriste avec les API REST en C, je me demandais justement si j'allais pas directement taper sur des bases de données NoSQL comme MongoDB, qui est d'ailleurs un peu la seule que je connais pour l'instant, et encore très peu, plutôt que de rester sur les vieilles techno à grand-papa comme le SQL. À l'époque, j'entendais parler du NoSQL partout sans trop savoir c'est quoi, et moi aussi je voulais être copain avec le nouveau gars cool de l'école.

          Sauf que justement je ne connais pas tant que ca le NoSQL, et mon approche de modélisation était et est encore très modèle relationnel. Quand je pense à une structure de données à persister, je vois facilement son schéma SQL dans ma tête. J'aime bien utiliser des technos récentes mais quand c'est justifié, pas juste pour utiliser des trucs hype. J'ai donc préféré rester sur mon approche à l'ancienne qui ne m'a posé aucun problème. Je ne critique même pas le NoSQL, je dis juste que j'en ai pas encore l'utilité.

          Les transactions SQL ne sont pas utilisées dans Glewlwyd, l'architecture REST et la façon dont sont identifiées les données permet de l'éviter.

          Je ne connais ni Riak, ni Etcd, merci pour l'info.
          Dans la mesure où je fais Glewlwyd avant tout pour moi, sur mon temps libre, je préfère utiliser des technos que je connais et que je maîtrise.
          Par contre, si quelqu'un me propose un patch ou de l'aide pour migrer sur une autre persistance qu'une base SQL, je suis preneur!

          • [^] # Re: Base de données

            Posté par  (site Web personnel) . Évalué à 2. Dernière modification le 05/11/19 à 15:33.

            Ma question sur le transactionnel n'était pas à propos de SQL / NoSQL mais plutôt concernant le théorème CAP : https://fr.wikipedia.org/wiki/Th%C3%A9or%C3%A8me_CAP

            Si on accepte de faire sauter le C (le coté transactionnel), on peut alors avoir une base répartie clusterisée master master beaucoup plus facilement.

            En tout cas, je te remercie pour toutes tes réponses très détaillées. C'est vraiment un projet intéressant.

            • [^] # Re: Base de données

              Posté par  (site Web personnel) . Évalué à 2.

              Ma question sur le transactionnel n'était pas à propos de SQL / NoSQL mais plutôt concernant le théorème CAP

              OK, alors j'ai lu rapidement la page wikipedia et je dois dire que je suis dans le champ solide!
              Ce n'est pas du tout mon domaine, et Glewlwyd n'a pas été concu pour du calcul distribué, ni pour une quelconque répartition de charge.

              Si on accepte de faire sauter le C (le coté transactionnel), on peut alors avoir une base répartie clusterisée master master beaucoup plus facilement.

              Admettons, mais là on est dans la couche données, pas dans la couche métier. Mais encore là je suis à l'ouest donc je vais éviter de polémiquer pour ne pas dire plein de bêtises.

              Par contre je ne vois pas le rapport entre tes explications et un serveur d'API REST qui permet de faire du OAuth2/OpenID Connect. Quel serait l'avantage de ce que tu décris pour Glewlwyd?

              • [^] # Re: Base de données

                Posté par  (site Web personnel) . Évalué à 2.

                Attention : cluster ne veut pas dire calcul distribué ici ;-)

                J'emploie le terme cluster au sens plusieurs machines. Dans ton cas, si tu es sur une base Etcd par exemple avec 3 machines, les sessions peuvent être en RAM car la probabilité de perdre les 3 noeuds est faible. Ainsi, tu peux mettre à jour un nœud, le rebooter puis le faire sur les suivants…

                Moins il y a de données en dur qui doivent être persistantes, plus c'est facile de mettre le service dans un conteneur, on est plus en mode "cloud". L'idéal est la VM virtuelle qu'on met à la poubelle à chaque reboot.

                Pour Glewlwyd, cela pourrait apporter une certaine robustesse d'administration, de déploiement… Plus trop à s'inquiéter du SPoF (Single Point of Failure). Tu installes cela dans un cluster kubernetes et hop, le truc tourne tout seul ;-)

            • [^] # Re: Base de données

              Posté par  . Évalué à 1. Dernière modification le 06/11/19 à 09:31.

              Les transactions sont loin d'être la seule cohérence dont il est question en CAP. Les contraintes d'intégrités sont en soit une barrière. Rien que garantir l'unicité d'un champ par exemple va péter complètement ta capacité de partitionnement.

              Si tu veux du partitionnement, tu risque aussi d'avoir des problèmes avec l'usage de jointures.

              C'est des problèmes qui sont plus ou moins adressable par les SGBDR, mais il faut que ce soit utilisé pour.

              Si tu regarde mongodb, la base de données NoSQL populaire. Elle ne propose pas de master/master. C'est du primary/secondary et les écritures ne sont autorisées que sur le primaire (tu peux avoir plusieurs primaires, mais ils ne manipulent des partitions différentes).

              • [^] # Re: Base de données

                Posté par  (site Web personnel) . Évalué à 2. Dernière modification le 10/11/19 à 17:38.

                Hé hé, c'est pour cela que je n'ai jamais évoqué MongoDB, mais Etcd et Riak ;-) Ce sont des bases master/master. Sinon, effectivement, l’intérêt est moindre de basculer sur ce genre de base sans une bonne raison.

                • [^] # Re: Base de données

                  Posté par  . Évalué à 1.

                  Et MariaDB peut se déployer en master/master même avec des transactions. C'est pour ça que j'explique qu'il faut se poser plus de question que avec ou sans transaction et qu'absence de transaction ne veux pas dire qu'il est possible de faire du master/master. Je dis même qu'avant de se demander si on veut faire du master/master (une solution technique), il faut savoir quel est le besoin fonctionnel derrière (il est possible de faire de la haute disponibilité sans master/master, il y a des contraintes à déployer un master/master).

          • [^] # Re: Base de données

            Posté par  . Évalué à 1.

            Sauf que justement je ne connais pas tant que ca le NoSQL, et mon approche de modélisation était et est encore très modèle relationnel. Quand je pense à une structure de données à persister, je vois facilement son schéma SQL dans ma tête. J'aime bien utiliser des technos récentes mais quand c'est justifié, pas juste pour utiliser des trucs hype. J'ai donc préféré rester sur mon approche à l'ancienne qui ne m'a posé aucun problème. Je ne critique même pas le NoSQL, je dis juste que j'en ai pas encore l'utilité.

            Et tu as très bien fait. Éventuellement, si l'idée t'intéresse tu peux stocker ta conf dans un annuaire LDAP ce qui peut simplifier le déploiement, mais tu as très bien fait de partir sur ce que tu connais bien :)

      • [^] # Re: Base de données

        Posté par  . Évalué à 2.

        Ce projet m'intéresse. Je lis :

        Il gère les utilisateurs et les clients stockés en base de données ou dans un LDAP.

        Est-ce que ça veut dire que le backend peut fonctionner en utilisant un LDAP existant ? Et que je pourrais utiliser Glewlwyd pour ajouter l'authent OpenID à mon serveur LDAP ?

        Sauf erreur je n'ai pas trouvé comment le configurer de cette façon ( en parcourant rapidement https://babelouest.github.io/glewlwyd/docs/INSTALL.html#database-back-end-initialisation ), je dis ptêt une connerie.

        • [^] # Re: Base de données

          Posté par  (site Web personnel) . Évalué à 4. Dernière modification le 04/11/19 à 21:56.

          Est-ce que ça veut dire que le backend peut fonctionner en utilisant un LDAP existant ?

          Oui, on peut même utiliser plusieurs LDAP existants si ca nous chante. La doc que tu pointes est celle pour l'installation du service, pas sa configuration (je vais ajouter une précision)

          Une fois que le serveur est lancé, il faut le configurer et c'est expliqué là: https://babelouest.github.io/glewlwyd/docs/GETTING_STARTED.html

          Et plus précisément comment configurer un backend LDAP est expliqué là: https://babelouest.github.io/glewlwyd/docs/USER_LDAP.html

          Le truc qui pourrait manquer aux utilisateurs hardcore de services LDAP, c'est les groupes pour mapper avec les scopes de Glewlwyd.
          Je ne l'ai pas fait vu que je ne l'utilse pas moi-même, et que je ne comprends pas bien comment ca marche dans la vraie vie.
          Mais si on m'explique ou qu'on me propose un patch, je serai content!

          Par contre, Glewlwyd ne permet pas d'ajouter l'authentification OpenID à ton serveur LDAP, mais te permet d'avoir un service d'authentification oidc ou OAuth2 branché sur ton annuaire LDAP pour les informations minimales de tes utilisateurs (login, mot de passe, scopes, e-mail, etc)

  • # Docker

    Posté par  (site Web personnel) . Évalué à 3.

    Chez moi l'adresse qui marche est celle-ci:
    https://hub.docker.com/r/babelouest/

    Néanmoins, avec la dernière image j'ai une erreur

    Error connecting to Glewlwyd API

    • [^] # Re: Docker

      Posté par  (site Web personnel) . Évalué à 3.

      Chez moi l'adresse qui marche est celle-ci:
      https://hub.docker.com/r/babelouest/

      Anéfé, le lien que je donne n'est pas valide dans tous les cas, si un modo veut bien le corriger.

      Error connecting to Glewlwyd API

      Là par contre je ne comprends pas. Si tu utilises la commande docker run --rm -it -p 4593:4593 babelouest/glewlwyd et que tu as ce résultat-là c'est un problème que je ne connaissais pas. Peux-tu ouvrir un bug pour essayer de corriger ca?

      • [^] # Re: Docker

        Posté par  (site Web personnel) . Évalué à 2.

        En fait pas besoin, j'avais étendu la notion de machine locale à mon réseau local, donc forcément en me connectant sur l'IP distante ça ne passait pas.

        En modifiant la variable external_url ça passe :)

        Petite question (qui elle mérite peut-être un ticket), ne serait-il pas intéressant que ce ficher fasse appel à un css custom, vide mais qui peut être modifié par la suite par l'utilisateur?

        Bien sûr on peut modifier glewlwyd.css mais je trouve que ça fait moins propre, et c'est moins évident de suivre les différences s'il y a des mises à jour.

        Superbe travail en tout cas!

        • [^] # Re: Docker

          Posté par  (site Web personnel) . Évalué à 3.

          En fait pas besoin, j'avais étendu la notion de machine locale à mon réseau local, donc forcément en me connectant sur l'IP distante ça ne passait pas.

          L'url de connexion à l'image docker est mentionnée dans le README.md mais pas dans le INSTALL.md.

          Je vais rajouter ca pour expliquer que l'image quickstart est pour localhost seulement, et expliquer la bonne utilisation du external_url. :)

          Petite question (qui elle mérite peut-être un ticket), ne serait-il pas intéressant que ce ficher fasse appel à un css custom, vide mais qui peut être modifié par la suite par l'utilisateur?

          Oui, tout à fait, je vais même faire mieux parce qu'il y a 3 applis web: admin, login et profile. Je vais donc rajouter un css custom par appli, et un autre global à toutes les applis. Merci pour l'idée!

    • [^] # Re: Docker

      Posté par  (site Web personnel) . Évalué à 4.

      Corrigé, merci.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n’en sommes pas responsables.