Skip to main content

Comment Snyk harmonise les stratégies d’authentification avec Gloo Edge

Écrit par
Headshot of Joakim Bajoul Kakaei

Joakim Bajoul Kakaei

Jack Schofield

Headshot of David Harrigan

David Harrigan

Headshot of Gareth Visagie

Gareth Visagie

Headshot of James Bowes

James Bowes

20 juillet 2021

0 minutes de lecture

Snyk prend en charge plusieurs stratégies d’authentification (authN) sur ses API. Historiquement, les clés API constituaient la principale méthode d’authN, mais nous avons plus récemment ajouté la prise en charge de l’authN à l’aide de JWT signés, générés dans le cadre d’une intégration OAuth. Cette méthode est actuellement utilisée par nos intégrations AWS CodePipeline et Bitbucket.

À ses débuts, Snyk reposait sur une architecture en étoile, avec un monolithe central qui prenait les décisions d’authN. Cette approche fonctionnait très bien pendant que Snyk trouvait son adéquation avec le marché et évoluait rapidement. Mais à mesure que l’organisation et sa clientèle grandissaient, la demande pour adopter une architecture orientée services (SOA) augmentait elle aussi. Or, ce changement architectural aurait exigé que chaque service prenne ses propres décisions d’authN. Autrement dit, chaque service aurait dû connaître plusieurs stratégies d’authentification, ce qui serait devenu fastidieux et difficile à faire évoluer.

Pour soutenir notre transition vers une SOA, nous avons conclu que l’approche la plus sûre et la plus pragmatique consistait à confier à une autorité unique le soin d’harmoniser les stratégies d’authN sous la forme d’un jeton d’identité à l’intégrité cryptographique garantie. Les services pourraient ensuite consommer et valider ce jeton sans avoir à gérer la complexité liée à la prise en charge de plusieurs stratégies d’authN. En bref, une autorité unique prendrait la décision d’authN, puis transmettrait un JWT signé que le reste du système pourrait utiliser.

Pour y parvenir, nous devions ajouter à notre système une nouvelle couche capable d’authentifier les requêtes et de générer le jeton normalisé. Voici Gloo Edge, une passerelle API.

Gloo : le lien qui rassemble !

Qu’est-ce qu’une passerelle API ?

Sans être spécialistes des passerelles API, nous pouvons vous donner une liste de base de leurs fonctionnalités :

  • Validation des requêtes

  • Limitation du débit

  • Authentification (ou possibilité d’ajouter cette fonctionnalité !)

  • Et bien plus encore ! (Nous vous avions dit que nous n’étions pas spécialistes…)

Et voici le plus intéressant… tout se passe à la périphérie ! Si vos applications effectuent l’une des opérations mentionnées ci-dessus, vous pouvez probablement la décharger sur votre passerelle API. Vous pouvez ainsi supprimer des lignes de code, ce que tout ingénieur adore faire ! ?

Après avoir étudié différentes passerelles API, nous avons choisi Gloo Edge (que nous appellerons simplement Gloo dans cet article) pour nous accompagner dans l’évolution de notre plateforme. Cet article n’expliquera pas comment ni pourquoi nous avons choisi Gloo. Ce sera le sujet d’un prochain article !

Qu’est-ce que Gloo Edge ?

Gloo Edge est une passerelle API développée par Solo.io. Elle s’appuie sur Envoy comme couche d’abstraction et vous permet d’utiliser des définitions de ressources personnalisées (CRD) Kubernetes pour générer la configuration Envoy — ce qui la rend très accessible. Si vous savez écrire une configuration Kubernetes, vous pouvez probablement écrire une configuration Envoy à l’aide des CRD propres à Gloo.

Pour en savoir plus sur Gloo, découvrir ce que c’est et comment il s’appuie sur Envoy, consultez la documentation de Gloo Edge (elle est vraiment excellente) !

Déploiement de Gloo Edge chez Snyk

Les sections suivantes présentent une partie du travail que nous avons réalisé pour placer Gloo devant l’API et l’utiliser avec des intégrations de partenaires particulièrement intéressantes !

Définir un parcours de migration (si votre API est déjà utilisée)

L’API Snyk reçoit constamment du trafic : la placer simplement derrière Gloo n’était donc pas vraiment envisageable. Comme indiqué plus haut, l’API destinée aux clients utilisait historiquement exclusivement des clés API pour authentifier les requêtes. Mais la prise en charge des JWT et des clés API par la passerelle API a créé une séparation entre l’ancien et le nouveau système.

Heureusement, notre équipe souhaitait déjà faire passer le domaine de notre API de https://snyk.io/api/ à https://api.snyk.io. Mais nous ne voulions pas rediriger toutes les requêtes de notre DNS d’origine vers le nouveau domaine avant de placer l’API derrière la nouvelle passerelle. Nous déployons donc progressivement la passerelle API sur notre ancien domaine, au moyen d’une version canari pondérée en pourcentage.

Autrement dit, nous faisons actuellement passer une partie du trafic de notre DNS d’origine par la passerelle API. Le reste est transmis au monolithe, qui prend alors les décisions d’authN.

Gloo prend en charge les déploiements canari dès son installation. Mais comme la passerelle ne gère pas encore tout le trafic de l’API, nous utilisons plutôt le mécanisme de répartition du trafic d’Envoy Proxy. La figure ci-dessous donne un aperçu général de son fonctionnement et de la façon dont vous pourriez l’utiliser.

Schéma montrant le proxy Envoy acheminant le trafic API entre une passerelle API et un monolithe, avec des flux de trafic de x % et de 100 − x % vers une API partagée.

Déplacer la validation des JWT à la périphérie

Même si la preuve de concept OAuth mentionnée précédemment mettait en œuvre OAuth, elle était trop étroitement liée à notre hub d’identité (et était intégrée à notre monolithe). Cette nouvelle bibliothèque d’authN devait valider le JWT envoyé par le hub d’identité, ce qui ressemblait à ceci :

  • Validation des claims du JWT (sub, iat, aud)

  • Validation de la signature du JWT à l’aide de points de terminaison JWK (JSON Web Key Sets)

Même si ce défi est techniquement trivial, il nécessite généralement pas mal de code (moins de 100 lignes), sans compter les tests. Vous pouvez obtenir le même résultat en ajoutant moins de 20 lignes de code à votre VirtualService dans Gloo :

jwtStaged:
 beforeExtAuth:
   providers:
     snyk:
       issuer: <a valid jwt issuer> # where did the token come from?
       audiences:
         - <a valid jwt audience> # what service expects the token?
       tokenSource:
         headers: # Regex currently not supported
           - header: Authorization
             prefix: "Bearer"
           - header: Authorization
             prefix: "bearer"
       jwks:
         remote:
           upstreamRef:
             name: <upstream name>
             namespace: <upstream namespace>
           url: <a valid jwks endpoint>

Cette configuration extrait le JWT de l’en-tête et effectue quelques vérifications de base avant de transmettre le JWT à un plug-in d’authentification externe (ExtAuth) (nous y reviendrons plus tard !) :

  • Vérifier que l’heure actuelle se situe entre les valeurs des claims iat (date d’émission) et exp (expiration) du JWT

  • Vérifier l’audience

  • Vérifier l’émetteur

  • Vérifier la signature à l’aide d’un point de terminaison JWK externe (en amont)

Nous avons pu déplacer une grande partie des validations du monolithe vers la périphérie ! Pas mal, non ? ??

Unifier les stratégies d’authN

Même si nous validons les JWT à la périphérie, nous avons uniquement déchargé le monolithe de cette tâche. Comme vous l’avez peut-être deviné d’après le titre et l’introduction de cet article, se contenter de valider les JWT à la périphérie ne suffit pas. Nous voulons aussi décharger la périphérie de toutes les décisions d’authN, afin que Gloo puisse les prendre en fonction du matériel de clé fourni par l’utilisateur.

Pour cela, nous avons ajouté un plug-in d’autorisation externe (ExtAuth), un type de plug-in unique créé par Gloo (disponible uniquement dans leur offre Enterprise), écrit en Go et compilé sous la forme d’un filtre d’autorisation externe Envoy. Le plug-in identifie d’abord le type de matériel de clé fourni par l’utilisateur et établit son identité. Une fois cette identité établie, le plug-in signe le jeton de manière cryptographique et le transmet à l’API en aval. Celle-ci vérifie la signature du jeton et exécute l’opération demandée au nom de l’utilisateur. La figure ci-dessous présente un exemple simplifié de ce fonctionnement.

Schéma de flux montrant des clés API, des JWT et de futures stratégies d’authentification transitant par une passerelle API et un plug-in ExtAuth, qui envoient des jetons signés à trois services.

Autrement dit, à ce stade, nous avons créé un jeton interne que tous les services de notre cluster peuvent utiliser. Il contient des informations sur l’utilisateur qui peuvent être associées à un profil dans notre base de données ! Les services acheminés par Gloo vérifient que le JWT a été signé par Gloo. Cela peut sembler peu, mais auparavant, chaque service devait explicitement demander les données utilisateur à notre monolithe pour obtenir des informations sur l’identité de l’utilisateur.

En outre, Gloo permet à nos services de gérer une seule méthode d’authN, tandis qu’il prend en charge la complexité de la gestion de plusieurs stratégies d’authN à la périphérie.

Tout cela se fait sans trop de difficultés, avec peu de lignes de code (dont la plupart sont du code standard généré par Solo), comparé à la mise en œuvre de stratégies d’authN spécifiques pour chaque service. 

Prochaines étapes

Lors des prochains sprints, l’équipe Extensibility se concentrera sur deux axes clés liés à notre passerelle API :

  • Confier progressivement à Gloo la gestion de tout le trafic de notre API (autrement dit : déployer une version canari !).Nous voulons commencer à acheminer le trafic « normal », non spécifique aux partenaires, par notre passerelle API. Pour cela, nous devons mettre en place les outils d’observabilité et les alertes nécessaires, afin que nos ingénieurs d’astreinte puissent prendre en charge la nouvelle infrastructure. Nous devons également acheminer une partie du trafic reçu par le point d’entrée actuel de l’API vers le proxy Envoy de Gloo.

  • Étendre Gloo pour valider les requêtes à la périphérie.Pour l’instant, Gloo ne prend pas cette fonctionnalité en charge dès l’installation.

Nous espérons que cet article vous a été utile si vous envisagez d’utiliser Gloo dans votre environnement ! Dans de prochains articles, nous verrons comment Gloo a offert à nos équipes d’ingénierie et produit une excellente observabilité de base, et comment Gloo nous a incités à améliorer nos pratiques CI/CD chez Snyk.

Vous souhaitez rejoindre une équipe d’ingénierie à la pointe de l’innovation ? Nous recrutons partout dans le monde.

Lire la suite

blog feature snyk container custom base recommendations
Blog

Découvrez Evo Agentic AppSec : une sécurité au rythme du développement de l’IA

Le développement piloté par l’IA dépasse les capacités des processus de sécurité traditionnels. Agentic AppSec de Snyk s’appuie sur des agents de sécurité pour détecter, corriger et vérifier les vulnérabilités en continu, tandis que les équipes définissent les exigences.

feature insights context
Blog

Les attaques autonomes sont déjà là. La défense doit suivre leur rythme.

Les attaquants autonomes réduisent la fenêtre de défense. Découvrez comment la découverte, la correction, la validation et la prévention continues peuvent aider les équipes de sécurité à suivre le rythme.

Blog

Pourquoi les agents de codage IA créent-ils sans cesse des failles de contrôle d’accès ?

Les agents de codage IA peuvent générer une logique d’autorisation qui compile et passe la revue, tout en exposant les données d’un tenant à un autre. Découvrez pourquoi les failles de contrôle d’accès sont difficiles à détecter et comment les prévenir.