Nous essayons de déterminer la meilleure façon d'autoriser les utilisateurs dans une architecture de microservices, tout en garantissant que les microservices ont des autorisations limitées. Notre architecture utilise un service d'autorisation central pour gérer l'émission de jetons JWT.
Nous avons les exigences suivantes:
Les utilisateurs devraient être limités à remplir certains rôles. par exemple, un utilisateur ne devrait pouvoir créer / modifier / lire que le contenu qu'il possède.
Les microservices doivent être limités aux seules autorisations dont ils ont besoin. Par exemple, un microservice qui n'a besoin que de lire des données d'un autre service devrait être explicitement interdit d'écrire des données dans ce service.
Par exemple, supposons que nous ayons un système où les utilisateurs peuvent télécharger des photos vers un service de stockage d'images. Nous avons un service de marquage qui marque automatiquement les photos avec un emplacement. Les utilisateurs peuvent uniquement CRUD leurs propres images. Le service de marquage peut lire n'importe quelle image du service de stockage d'images, mais ne doit pas être en mesure de modifier / supprimer.
Quelle est la bonne façon de réaliser ce qui précède en utilisant des jetons JWT? Voici quelques solutions dont nous avons discuté:
Le service de stockage d'images expose 2 API, une qui est disponible en externe (donnant un accès CRUD à l'utilisateur) et une qui est disponible en interne (donnant un accès interne en lecture seule). Semble inflexible - et si un autre service interne a besoin d'un accès en lecture / écriture à toutes les images (par exemple, un qui supprime automatiquement les images explicites)?
Nous avons configuré deux autorisations dans le JWT de l'utilisateur, l'une étant CRUD_OwnImages, l'autre étant READ_ForAnalysis. Le service de balisage peut voir si l'utilisateur dispose des autorisations READ_ForAnalysis et, dans l'affirmative, effectuer la demande appropriée. Nous avons un autre microservice qui vérifie si l'utilisateur a des opérations CRUD_OwnImages for CRUD sur ses propres images. Cela met la responsabilité sur chaque microservice de s'assurer que l'utilisateur est limité aux actions dont il a besoin. Le magasin d'images n'a aucun moyen de restreindre chaque microservice avec cette approche, il est donc potentiellement floconneux et sujet aux erreurs.
Nous accordons au microservice de balisage son propre utilisateur, avec READ_ForAnalysis comme autorisation. Ensuite, lorsque le service de marquage demande des images à la banque d'images, il y a accès, mais il est interdit de les modifier. L'utilisateur de l'utilisateur ne dispose que de l'autorisation CRUD_OwnImages, il est donc en mesure de récupérer et d'accéder uniquement à ses images depuis le frontend. Si un autre service a besoin de CRUD pour toutes les données, nous pouvons lui donner CRUD_AllData ou similaire. Nous aimons cette approche car chaque service est désormais responsable de ses propres données (plutôt que cette logique étant dupliquée sur plusieurs services), mais que se passe-t-il si le service nécessite à la fois des autorisations utilisateur et des autorisations de microservice? Pouvons-nous envoyer deux jetons JWT (à la fois l'utilisateur et le microservice) en toute sécurité? Existe-t-il un moyen de combiner les autorisations en toute sécurité et de les envoyer via? par exemple
Le problème est exacerbé si les informations utilisateur sont nécessaires plus en aval (à 2 ou 3 microservices de distance). Supposons-nous simplement qu'il appartient aux microservices individuels de se limiter aux actions dont ils ont besoin, et de ne pas le rendre explicite?
Réponses:
En général, autant d'opérations que possible doivent être liées à un utilisateur réel et humain. Cela oblige les gens à s'authentifier correctement, cela pousse à une stratégie d'autorisation cohérente unique, et c'est un élément important pour fournir une piste d'audit cohérente.
Et en général, vous avez trois types de scénarios avec des microservices:
1. L'utilisateur entre, télécharge une photo et doit être étiquetée. Génial. Le service photo peut simplement transmettre le JWT au service de balisage (ou vice versa selon le sens de votre dépendance) et si l'utilisateur n'a pas les droits pour effectuer la sous-opération, vous prenez l'action appropriée (peut-être téléchargez la photo sans balise , peut-être retourner l'erreur, peut-être autre chose).
2. L'utilisateur entre, télécharge une photo et doit être étiquetée ... mais pas maintenant. Cool. Vous gérez maintenant la photo normalement. Plus tard, lorsque le balisage se produit (gestion des événements / messages, traitement des commandes de style CQRS, certains traitements de travaux périodiques, peu importe), le service de balisage usurpera l'identité de l'utilisateur (très probablement en utilisant un secret partagé pour demander un JWT personnalisé à auth) la sous-opération au nom du demandeur d'origine (avec toutes leurs autorisations et limitations). Cette méthode a le problème habituel avec les opérations asynchrones où il est difficile de renvoyer des erreurs à l'utilisateur si les choses ne se passent pas bien, mais si vous utilisez ce modèle pour les opérations interservices, vous auriez déjà résolu cela.
3. Certains sous-systèmes doivent faire des choses en dehors du contexte d'un utilisateur. Vous avez peut-être un travail de nuit pour archiver de vieilles images. Peut-être que vos balises doivent être consolidées ... Dans ce cas, vous voulez probablement que chacun de ces acteurs ait son propre pseudo-utilisateur avec des autorisations limitées et un ID unique pour la piste d'audit.
Les options à utiliser varient en fonction de votre scénario, de vos besoins et de votre tolérance au risque. Et bien sûr, ce ne sont là qu'un ensemble incomplet de généralisations générales de l'AVC.
Mais en général, les microservices eux-mêmes ne devraient pas être des utilisateurs si possible.
la source