Découverte du bastion Teleport

le 06/07/2020 par Arnaud Mazin
Tags: Software Engineering, Devops, SRE

Dans cet article, nous allons jeter un coup d’œil à Teleport, dans sa version open source. Pour résumer, au risque d’être simplificateur, il s’agit d’une solution de bastion qui tente le délicat exercice de protéger une ferme de machines et de services, sans être trop intrusif à l’usage. Nous avions évoqué ce produit il y a quelques années, il est temps d’aller plus loin.

L’objectif ici n’est pas de paraphraser le site de ce logiciel qui décrit tout son fonctionnement, son installation et sa configuration, mais d’en extraire quelques thèmes qui semblent dignes d’intérêt. C’est parti…

Disclaimer

Je précise avant de commencer que je n’ai pas (encore) eu l’occasion de mettre en œuvre Teleport sur un vrai projet. Ce sont donc des résultats de POC que je partage ici.

Fonctions

Teleport, c’est un bastion

Je ne vais pas revenir sur le principe du bastion dans les architectures de sécurité, juste rappeler qu’un bastion joue le rôle de point d’accès sécurisé (authentification, filtrage) vers plusieurs machines, traditionnellement via SSH.

Dans des contextes cloud, ce composant peut être remplacé par des implémentations spécifiques. Citons à titre d’exemple SSM dans l’écosystème AWS.

En l'absence de tels outils au catalogue, cela semble une bonne idée d’envisager l’installation d’un bastion. Idem si l'on souhaite maximiser la portabilité de nos outils vis-à-vis des fournisseurs de cloud.

Teleport, c’est un bastion modulaire

Teleport est composé de plusieurs composants qui permettent de modéliser différentes architectures. Je vous invite à faire un petit tour sur ces deux liens pour commencer.

Il existe un concept de clusters qui sert de point d’accès à des nœuds : c’est le modèle du bastion classique.

Il est également possible d’organiser une hiérarchie de bastions, ce qui devient plus intéressant pour gérer des environnements avec des politiques de sécurité différentes (exemple : il faut passer par un premier bastion pour pouvoir aller sur le bastion de la prod…).

Qui dit modularité dit configuration et composants optionnels à activer (nœud, authentification, serveur SSH, proxies en tous genres…). Le détail de l'interaction des composants peut alors ressembler à ça :

Fort heureusement, pour des cas simples, il n’y a qu’un service à démarrer, un fichier de configuration à produire.

Deux types d’accès sont possibles au travers de Teleport :

  • SSH, le mode classique et historique, qui se veut le plus compatible possible avec OpenSSH, ce qui rend son usage quasiment transparent dans de nombreux cas d’usage, Ansible en premier lieu.
  • Kubernetes qui permet de gérer les accès à un ou plusieurs clusters Kubernetes, turfu, nous voilà !!

Teleport, c’est un référentiel d’identités et une PKI avant tout

Et c’est finalement l’idée centrale de Teleport : pour utiliser le bastion, il faut présenter un certificat valide. Pour obtenir un certificat valide, il faut le demander à la brique d'authentification de Teleport.

L'authentification par défaut est basée sur un référentiel interne de type login/mot de passe auquel il est possible d’ajouter un second facteur, soit au standard TOTP (comme Google Authenticator) soit U2F (comme bon nombre de clés matérielles USB). C’est une des grandes forces de cette solution. Il ne semble pas y avoir de moyen documenté pour utiliser ce référentiel interne dans d'autres solutions.

Une authentification par GitHub fait également partie de la version open source. Pour d’autres mécanismes, il sera nécessaire de se tourner vers la version commerciale de Teleport, qui apporte également un modèle de droits bien plus fins.

Il existe des commandes (via l’outil en ligne de commande tctl) pour les administrateurs permettant de gérer (enrôler, révoquer, changer les droits) des utilisateurs.

Dans la version open source, changer les droits consiste essentiellement à lister les comptes avec lesquels les utilisateurs seront autorisés à se connecter et définir les groupes Kubernetes qui leur seront associés.

L’enrôlement classique d’un utilisateur se termine en générant un lien Web jetable. Celui-ci permet à l’intéressé de finaliser lui-même son enrôlement (saisie du mot de passe, enregistrement du second facteur).

Les certificats forgés par Teleport ont une durée de vie assez courte (12h par défaut) de la même façon qu’un token d’API dans beaucoup de solutions sur le cloud. Le but est de régulièrement les renouveler auprès du serveur d'authentification.

Teleport, pour les utilisateurs, c’est le client tsh, ou le Web

En ligne de commande

tsh, voilà donc le nom de l’outil pour utiliser Teleport en ligne de commande. Il est disponible pour Windows, MacOS et Linux

Deux commandes sont particulièrement intéressantes :

  • tsh --proxy=mon-bastion.acme.com login qui va vérifier l’authentification de l’utilisateur auprès du bastion pour obtenir le fameux certificat (il est déposé dans ~/.tsh/keys/<nom_du_bastion>/).
  • tsh logout dont je vous laisse deviner l’usage. Techniquement, ce qui se passe côté serveur n’est pas forcément expliqué. Côté client, le certificat et sa clé privée, sont supprimés.

Notons également que la clé privée liée au certificat est automatiquement ajoutée dans votre ssh-agent. Ce qui fait qu’une fois le certificat obtenu, vous pouvez tout à fait utiliser votre bon vieux client OpenSSH. tsh peut rester pertinent cependant pour éviter de faire des ssh_config alambiqués. Le renouvellement des certificats est également géré automatiquement via tsh.

tsh se veut aussi compatible que possible avec ssh, notamment dans sa capacité à supporter des options avancées. Citons en premier lieu -D12345 et -L8080:127.0.0.1:8080, pour établir des tunnels respectivement dynamiques et statiques. Point de tunnel remontant en revanche (-R2222:127.0.0.1:22).

Cadeau bonus, si Teleport est configuré comme proxy Kubernetes, votre kubeconfig est également mis à jour avec ces éléments de configuration. Nous en reparlerons dans quelques lignes…

La Web Console

La brique dite « proxy » de Teleport, déployée sur le bastion joue également le rôle de Web Console. Elle permet de prendre la main en SSH sur les nœuds simplement avec un navigateur Web moderne. Très pratique notamment pour rejoindre les sessions en cours et revoir les logs de sessions précédentes.

Exemple d’ouverture de session Web avec le second facteur de type U2F. C’est le moment d’appuyer sur le petit bouton de votre token.

Ces petits plus qui suscitent l’intérêt

Joindre une session SSH en cours

joindre une session en cours, via la console ou la commande tsh join permet de se raccrocher à une session déjà ouverte, sans couper la connexion avec les clients déjà connectés. On peut y voir un fonctionnement similaire à tmux ou screen au moment de s’attacher à plusieurs à une session. Très pratique.

Une session est en cours, je peux la rejoindre en cliquant sur l’icône join.

J’ai rejoint une session, nous sommes à présent deux utilisateurs arno (représentés par l’icône “A” à gauche de l’écran. Je vois ce que l’autre utilisateur tape et vice versa.

L’enregistrement des sessions SSH

L’enregistrement des sessions, justement, c’est cette capacité à garder un historique de nos actions passées sur les machines. Souriez, vous êtes filmés.

Ce mécanisme est uniquement pour le protocole SSH, Kubernetes proposant des fonctions natives d’audit-logs au niveau de son Apiserver.

L’interface Web (en cliquant sur l’icône play sur une session donnée) et la ligne de commande (ts play) permettent de simplement rejouer une session passée. Rejouer, c’est concrètement consulter le flux texte des entrées et sorties qui sont passées dans la connexion. Il est par conséquent possible aux administrateurs de récupérer ces fichiers pour les triturer à loisir.

Des options de configuration permettent d’externaliser ces traces sur un stockage tiers, comme un stockage objet par exemple.

Les certificats forgés au standard OpenSSH

Les certificats utilisés dans Teleport ont l’avantage d’être compatibles avec OpenSSH, ce qui permet de n’installer Teleport que sur le bastion, même si l’architecture canonique suggère d’installer un agent Teleport (et activer son propre service SSH, en plus de celui déjà présent en standard) sur toutes les machines protégées par le bastion.

Attention toutefois, dans cette situation, il faut faire une configuration pour pouvoir continuer à logguer les sessions SSH. En effet, en l’absence d’utilisation d’un service SSH Teleport (qui trace habituellement les sessions), l’enregistrement des sessions utilisateurs doit se faire du côté du proxy, ce qui impose de déchiffrer le flux à ce niveau pour pouvoir le sauvegarder, et donc d’activer le ForwardAgent SSH...

Kubernetes et l'impersonation

Dernier point très intéressant : l’intégration avec l’authentification Kubernetes. Le principe est le suivant :

    • Le client (kubectl, sauf exception) lit le kubeconfig qui a été configuré par un appel antérieur à tsh login. Il présente le certificat et sa clé privée au proxy Teleport, qu’il croit être un vrai serveur Kubernetes.

<li">Le bastion Teleport, via son proxy Kubernetes, reçoit les connexions des clients (kubectl) sur un port spécifique. Les API servers Kubernetes n’ont donc pas besoin d’être directement exposés aux clients.

  • Il valide le certificat présenté par le client et en extrait des éléments d’identité (login, groupes Kubernetes) qui ont été renseignés par l’administrateur dans la fiche de l’utilisateur.
  • Le bastion Teleport dispose d’un kubeconfig (privé et très très secret) permettant de se connecter au cluster Kubernetes et d’y exécuter une impersonation. L’utilisateur, qui était jusque-là très privilégié devient alors un utilisateur lambda (les login et groupes Kubernetes qui étaient présents dans le certificat). Pour rappel, les utilisateurs ne sont jamais internes à Kubernetes (à part dans le cas des ServiceAccounts qui ne nous intéressent pas ici). Il n’y a donc pas de nécessité de créer un utilisateur pour qu’il existe dans Kubernetes : la brique d’authentification externe ou dans notre cas la fonction d’impersonation décide simplement de la nouvelle identité d’un utilisateur.
  • Kubernetes applique normalement les permissions RBAC sur cet utilisateur, libre à vous de créer les RoleBindings et ClusterRoleBindings en conséquence.

Teleport peut être mis en haute disponibilité

Comme pour l'enregistrement des sessions SSH, il est possible d’externaliser la persistance de toutes les données de Teleport (les audits d’action et l’état interne de Teleport) sur des solutions tierces comme DynamoDB, FireStore, etcd...

Est-ce que tout est parfait ?

Certes non, citons quelques limitations relevées à ce jour.

La configuration réseau complexe à comprendre

Il n’est pas forcément aisé de comprendre quel(s) port(s) TCP utiliser en fonction des cas. La documentation en décrit pas moins de 6 à utiliser en fonction des besoins, et ce, en plus du port 22 standard de notre bon vieux SSH.

Autant l’usage de certains ne fait pas de grand mystère, autant d’autres semblent un peu cryptiques. Patience et lecture de documentation sont de mise.

Cette remarque s’applique lorsqu’il s’agit de configurer n'importe quelle partie de Teleport. Autant le fichier de configuration (en YAML) n’est pas très compliqué, autant les implications d’utiliser des FQDN ou des @IP publiques ou privées ne sont pas 100% évidentes. Certains paramètres ont en effet du sens entre les nœuds, d’autres sont visibles exclusivement des clients. Un peu d’essais-erreurs sera sans doute nécessaire pour trouver les réglages qui correspondent à votre topologie. Mention spéciale si votre DNS répond à la fois en IPv4 et IPv6...

Quelques crashes…

J’ai pu constater quelques stacktraces surgir en tentant des configurations un peu folkloriques autour des ssh-agents, l’occasion de voir que Teleport est écrit en Go… Le redémarrage du service se fait via Systemd donc rien d’alarmant, mais c’est toujours un peu embêtant. Peut-être est-ce lié à la version ARM de Teleport que j’ai essayé lors de mes tests.

Et les limitations de la version open source ?

Une véritable limitation est l’incapacité de se baser sur un référentiel d’identités d’entreprise (OIDC ou autre) et ainsi éviter un provisionnement (et la révocation) de toute une flotte d’utilisateurs. Cette limitation est à modérer, en tout cas dans nos contextes projets, car rares sont les cas où un projet ne sollicite qu’une seule entreprise. Nous sommes par conséquent généralement conduits à recréer un référentiel spécifique. Pourquoi pas dans Teleport ?

Autre point fâcheux, le référentiel interne d’identités n’implémente pas de politique de mot de passe (longueur, complexité…) ni de stratégie de renouvellement périodique. À noter que ce point n’est pas nécessairement critique si on met en place le MFA. Le renouvellement des mots de passe reste toujours possible.

Idem, il ne semble pas y avoir de procédure pour procéder au changement de son second facteur (token matériel ou appli type Google Authenticator). Les commandes tctl get et tctl create (assez semblables à kubectl <get|create|update> pour les connaisseurs) permettent sans doute de procéder manuellement à ces opérations, mais la documentation se fait bien rare.

Conclusion

Teleport fournit une approche assez légère et peu intrusive de bastion permettant l’authentification à deux facteurs dans des contextes SSH et Kubernetes. L’impression est plutôt bonne et donne clairement envie de l’implémenter dans un contexte projet, là où des solutions natives fournies par un cloud provider ne pourraient pas s’appliquer.