Retour aux microservices avec Istio. 3e partie



Remarque perev. : La première partie de cette série a été consacrée à la présentation des capacités d'Istio et à leur démonstration en action, la seconde à un routage finement réglé et à une gestion du trafic réseau. Nous allons maintenant parler de sécurité: pour démontrer les fonctions de base qui lui sont associées, l'auteur utilise le service d'identité Auth0, mais d'autres fournisseurs peuvent être configurés par analogie avec lui.

Nous avons mis en place un cluster Kubernetes dans lequel Istio et l'application de microservice d'analyse des sentiments ont été déployés, ce qui a été la démonstration d'Istio.

En utilisant Istio, nous avons pu garder les services de petite taille, car ils n'ont pas besoin d'implémenter des «couches» telles que les tentatives, retouts, délais d'attente, disjoncteurs, traçage, surveillance . De plus, nous avons utilisé des techniques avancées de test et de déploiement: tests A / B, mise en miroir et déploiements canaries.



Dans le nouveau matériel, nous traiterons des dernières couches sur le chemin de la valeur commerciale: l'authentification et l'autorisation - et à Istio, c'est un vrai plaisir!

Authentification et autorisation à Istio


Je n'aurais jamais cru que je serais inspiré par l'authentification et l'autorisation. Quelle technologie peut offrir Istio pour rendre ces sujets passionnants et encore plus pour vous inspirer?

La réponse est simple: Istio transfère la responsabilité de ces fonctionnalités de vos services aux mandataires Envoy. Au moment où les demandes parviennent aux services, elles sont déjà authentifiées et autorisées, il vous suffit donc d'écrire du code utile pour les entreprises.

Sonne bien? Regardons à l'intérieur!

Authentification avec Auth0


Nous utiliserons Auth0 comme serveur pour la gestion des identités et des accès, qui a une version d'essai, qui est intuitive à utiliser et j'aime ça. Cependant, les mêmes principes peuvent être appliqués à toute autre implémentation d' OpenID Connect : KeyCloak, IdentityServer et bien d'autres.

Tout d'abord, accédez au portail Auth0 avec votre compte, créez un locataire (locataire - «locataire», unité d'isolation logique, pour plus de détails, consultez la documentation - environ la traduction). Allez dans Applications> Application par défaut , en choisissant Domaine , comme indiqué dans la capture d'écran ci-dessous. :



Spécifiez ce domaine dans le resource-manifests/istio/security/auth-policy.yaml ( source ):

 apiVersion: authentication.istio.io/v1alpha1 kind: Policy metadata: name: auth-policy spec: targets: - name: sa-web-app - name: sa-feedback origins: - jwt: issuer: "https://{YOUR_DOMAIN}/" jwksUri: "https://{YOUR_DOMAIN}/.well-known/jwks.json" principalBinding: USE_ORIGIN 

Ayant une telle ressource, Pilot (l'un des trois composants de base de Control Plane dans Istio - environ. Transl.) Configure les Envoyés pour authentifier les demandes avant de les rediriger vers les services: sa-web-app et sa-feedback . Dans le même temps, la configuration ne s'applique pas aux Envoys du sa-frontend , ce qui nous permet de laisser le frontend non authentifié. Pour appliquer une stratégie, exécutez la commande:

 $ kubectl apply -f resource-manifests/istio/security/auth-policy.yaml policy.authentication.istio.io “auth-policy” created 

Revenez à la page et faites une demande - vous verrez qu'elle se termine par 401 Statut non autorisé . Nous redirigeons maintenant les utilisateurs frontaux vers l'authentification avec Auth0.

Demander une authentification avec Auth0


Pour authentifier les demandes des utilisateurs finaux, vous devez créer une API dans Auth0 qui représentera les services authentifiés (avis, détails et évaluations). Pour créer une API, accédez à Auth0 Portal> APIs> Create API et remplissez le formulaire:



Les informations importantes ici sont l' identifiant , que nous utiliserons plus tard dans le script. Écrivons-le pour nous comme ceci:

  • Audience : {YOUR_AUDIENCE}

Les autres détails dont nous avons besoin se trouvent sur le portail Auth0 dans la section Applications - sélectionnez Test Application (il est créé automatiquement avec l'API).

Ici, nous écrivons:

  • Domaine : {YOUR_DOMAIN}
  • Identifiant client : {YOUR_CLIENT_ID}

Faites défiler l' application de test jusqu'à la zone de texte URL de rappel autorisées (URL autorisées pour le rappel), dans laquelle nous indiquons l'URL où l'appel doit être envoyé une fois l'authentification terminée. Dans notre cas, c'est:

 http://{EXTERNAL_IP}/callback 

Et pour les URL de déconnexion autorisées ( URL autorisées pour la déconnexion), ajoutez:

 http://{EXTERNAL_IP}/logout 

Passons au frontend.

Mise à jour frontend


Basculez vers la branche auth0 du auth0 [istio-mastery] . Dans ce thread, le code frontal est modifié pour rediriger les utilisateurs vers Auth0 pour l'authentification et utiliser le jeton JWT dans les demandes d'autres services. Ce dernier est implémenté comme suit ( App.js ):

 analyzeSentence() { fetch('/sentiment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${auth.getAccessToken()}` // Access Token }, body: JSON.stringify({ sentence: this.textField.getValue() }) }) .then(response => response.json()) .then(data => this.setState(data)); } 

Pour convertir le frontend en utilisant les données du locataire dans Auth0, ouvrez sa-frontend/src/services/Auth.js et remplacez-y les valeurs que nous avons écrites ci-dessus ( Auth.js ):

 const Config = { clientID: '{YOUR_CLIENT_ID}', domain:'{YOUR_DOMAIN}', audience: '{YOUR_AUDIENCE}', ingressIP: '{EXTERNAL_IP}' //      } 

L'application est prête. Indiquez votre ID Docker dans les commandes ci-dessous lors de la création et du déploiement des modifications apportées:

 $ docker build -f sa-frontend/Dockerfile \ -t $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 \ sa-frontend $ docker push $DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 $ kubectl set image deployment/sa-frontend \ sa-frontend=$DOCKER_USER_ID/sentiment-analysis-frontend:istio-auth0 

Essayez l'application! Vous serez redirigé vers Auth0, où vous devrez vous connecter (ou vous inscrire), après quoi vous serez renvoyé à la page à partir de laquelle les demandes déjà authentifiées seront effectuées. Si vous essayez les commandes curl mentionnées dans les premières parties de l'article, vous recevrez un code d'état 401 , qui indique que la demande n'est pas autorisée.

Passons à l'étape suivante - autoriser les demandes.

Autorisation avec Auth0


L'authentification nous permet de comprendre qui est l'utilisateur, mais pour savoir à quoi il a accès, une autorisation est requise. Istio propose également des outils pour cela.

À titre d'exemple, nous allons créer deux groupes d'utilisateurs (voir le schéma ci-dessous):

  • Utilisateurs (utilisateurs) - avec accès uniquement aux services SA-WebApp et SA-Frontend;
  • Modérateurs - avec accès aux trois services.


Concept d'autorisation

Pour créer ces groupes, nous utiliserons l'extension Auth0 Authorization et utiliserons Istio pour leur fournir différents niveaux d'accès.

Installation et configuration de l'autorisation Auth0


Sur le portail Auth0, accédez à Extensions et installez Auth0 Authorization . Après l'installation, accédez à l' extension d'autorisation , puis à la configuration du locataire en cliquant en haut à droite et en sélectionnant l'option de menu appropriée (Configuration) . Activez Groupes et cliquez sur le bouton Règle de publication .



Création de groupe


Dans l'extension d'autorisation, accédez à Groupes et créez un groupe de modérateurs . Étant donné que nous considérerons tous les utilisateurs authentifiés comme ordinaires, il n'est pas nécessaire de créer un groupe supplémentaire pour eux.

Sélectionnez le groupe Modérateurs , cliquez sur Ajouter des membres , ajoutez votre compte principal. Laissez certains utilisateurs sans groupe pour vous assurer que l'accès leur est refusé. (Les nouveaux utilisateurs peuvent être créés manuellement via le portail Auth0> Utilisateurs> Créer un utilisateur .)

Ajouter une revendication de groupe pour accéder au jeton


Les utilisateurs sont ajoutés aux groupes, mais ces informations doivent se refléter dans les jetons d'accès. Afin de se conformer à OpenID Connect et de renvoyer en même temps les groupes dont nous avons besoin, le jeton devra ajouter sa revendication personnalisée . Il est implémenté selon les règles d'Auth0.

Pour créer une règle, accédez au portail Auth0 aux règles , cliquez sur Créer une règle et sélectionnez une règle vide dans les modèles.



Copiez le code ci-dessous et enregistrez-le en tant que nouvelle règle d' ajout de revendication de groupe ( namespacedGroup.js ):

 function (user, context, callback) { context.accessToken['https://sa.io/group'] = user.groups[0]; return callback(null, user, context); } 

Remarque : ce code prend le premier groupe d'utilisateurs défini dans l'extension d'autorisation et l'ajoute au jeton d'accès en tant que revendication personnalisée (sous son espace de noms, comme requis par Auth0).

Revenez à la page Règles et vérifiez que vous disposez de deux règles écrites dans l'ordre suivant:

  • auth0-autorisation-extension
  • Ajouter une revendication de groupe

L'ordre est important car le champ de groupe reçoit de manière asynchrone la règle d'auth0-autorisation-extension et est ensuite ajouté en tant que revendication par la deuxième règle. Le résultat est un tel jeton d'accès:

 { "https://sa.io/group": "Moderators", "iss": "https://sentiment-analysis.eu.auth0.com/", "sub": "google-oauth2|196405271625531691872" // [  ] } 

Vous devez maintenant configurer le proxy Envoy pour vérifier l'accès utilisateur, pour lequel le groupe sera extrait de la revendication ( https://sa.io/group ) dans le jeton d'accès renvoyé. C'est le sujet de la section suivante de l'article.

Configuration des autorisations Istio


Pour l'autorisation de travailler, vous devez activer RBAC pour Istio. Pour ce faire, utilisez la configuration suivante:

 apiVersion: "rbac.istio.io/v1alpha1" kind: RbacConfig metadata: name: default spec: mode: 'ON_WITH_INCLUSION' # 1 inclusion: services: # 2 - "sa-frontend.default.svc.cluster.local" - "sa-web-app.default.svc.cluster.local" - "sa-feedback.default.svc.cluster.local" 

Explications:
  • 1 - activer RBAC uniquement pour les services et les espaces de noms répertoriés dans le champ Inclusion ;
  • 2 - listez la liste de nos services.


Nous appliquons la configuration avec cette commande:

 $ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml rbacconfig.rbac.istio.io/default created 

Désormais, tous les services nécessitent un contrôle d'accès basé sur les rôles. En d'autres termes, l'accès à tous les services est refusé et entraînera une réponse RBAC: access denied . Autorisez maintenant l'accès aux utilisateurs autorisés.

Configuration d'accès pour les utilisateurs réguliers


Tous les utilisateurs doivent avoir accès aux services SA-Frontend et SA-WebApp. Mis en œuvre à l'aide des ressources Istio suivantes:

  • ServiceRole - définit les droits de l'utilisateur;
  • ServiceRoleBinding - Détermine à qui appartient ce ServiceRole.

Pour les utilisateurs ordinaires, autorisez l'accès à certains services ( servicerole.yaml ):

 apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRole metadata: name: regular-user namespace: default spec: rules: - services: - "sa-frontend.default.svc.cluster.local" - "sa-web-app.default.svc.cluster.local" paths: ["*"] methods: ["*"] 

Et par le biais de la regular-user-binding appliquez un ServiceRole à tous les visiteurs de la page ( regular-user-service-role-binding.yaml ):

 apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBinding metadata: name: regular-user-binding namespace: default spec: subjects: - user: "*" roleRef: kind: ServiceRole name: "regular-user" 

«Tous les utilisateurs» signifie-t-il que les utilisateurs non authentifiés auront accès à SA WebApp? Non, la politique vérifiera la validité du jeton JWT.

Appliquer la configuration:

 $ kubectl apply -f resource-manifests/istio/security/user-role.yaml servicerole.rbac.istio.io/regular-user created servicerolebinding.rbac.istio.io/regular-user-binding created 

Configuration d'accès pour les modérateurs


Pour les modérateurs, nous voulons permettre l'accès à tous les services ( mod-service-role.yaml ):

 apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRole metadata: name: mod-user namespace: default spec: rules: - services: ["*"] paths: ["*"] methods: ["*"] 

Mais nous voulons ces droits uniquement pour les utilisateurs dont le jeton d'accès a une revendication https://sa.io/group avec la valeur Moderators ( mod-service-role-binding.yaml ):

 apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBinding metadata: name: mod-user-binding namespace: default spec: subjects: - properties: request.auth.claims[https://sa.io/group]: "Moderators" roleRef: kind: ServiceRole name: "mod-user" 

Appliquer la configuration:

 $ kubectl apply -f resource-manifests/istio/security/mod-role.yaml servicerole.rbac.istio.io/mod-user created servicerolebinding.rbac.istio.io/mod-user-binding created 

En raison de la mise en cache des envoyés, les règles d'autorisation peuvent prendre quelques minutes pour prendre effet. Après cela, vous pouvez vous assurer que les utilisateurs et les modérateurs ont des niveaux d'accès différents.

Conclusion sur cette partie


Eh bien, sérieusement: avez-vous déjà vu une approche plus simple, sans effort, évolutive et sécurisée de l'authentification et de l'autorisation?

Seules trois ressources Istio (RbacConfig, ServiceRole et ServiceRoleBinding) étaient nécessaires pour obtenir un contrôle plus fin de l'authentification et de l'autorisation d'accès des utilisateurs finaux aux services.

De plus, nous avons pris soin de ces questions hors de nos services en tant qu'envoyé, obtenant:

  • Réduire la quantité d'exemples de code pouvant inclure des problèmes de sécurité et des bogues;
  • réduire le nombre de situations stupides dans lesquelles un point final s'est avéré être accessible de l'extérieur et a oublié de le signaler;
  • éliminer la nécessité de mettre à jour tous les services chaque fois qu'un nouveau rôle ou droit est ajouté;
  • que les nouveaux services restent simples, sécurisés et rapides.

Conclusion


Istio permet aux équipes de concentrer leurs ressources sur les tâches critiques de l'entreprise sans ajouter de frais généraux aux services, leur redonnant ainsi le statut micro.

L'article (en trois parties) a fourni des connaissances de base et des instructions pratiques prêtes à l'emploi pour commencer à travailler avec Istio dans des projets réels.

PS du traducteur


Lisez aussi dans notre blog:

Source: https://habr.com/ru/post/fr443668/


All Articles