Staramy się ustalić najlepszy sposób autoryzacji użytkowników w architekturze mikrousług, jednocześnie zapewniając ograniczone uprawnienia mikrousług. Nasza architektura korzysta z centralnej usługi autoryzacji do obsługi wydawania tokenów JWT.
Mamy następujące wymagania:
Użytkownicy powinni mieć ograniczone możliwości wykonywania określonych ról. np. użytkownik powinien mieć możliwość tworzenia / modyfikowania / czytania treści, które posiada.
Mikrousługi powinny być ograniczone tylko do wymaganych uprawnień. np. mikrousługa, która musi tylko odczytywać dane z innej usługi, powinna być wyraźnie zabroniona zapisywania danych w tej usłudze.
Załóżmy na przykład, że mamy system, w którym użytkownicy mogą przesyłać zdjęcia do usługi magazynu obrazów. Mamy usługę tagowania, która automatycznie oznacza zdjęcia lokalizacją. Użytkownicy mogą CRUD tylko własne zdjęcia. Usługa tagowania może odczytać dowolny obraz z usługi magazynu obrazów, jednak nie powinna mieć możliwości modyfikacji / usuwania.
Jaki jest dobry sposób na osiągnięcie powyższego przy użyciu tokenów JWT? Niektóre omówione rozwiązania to:
Usługa magazynu obrazów udostępnia 2 interfejsy API, jeden dostępny zewnętrznie (dający użytkownikowi dostęp do CRUD), a drugi dostępny wewnętrznie (dający wewnętrzny dostęp tylko do odczytu). Wydaje się nieelastyczny - co jeśli inna usługa wewnętrzna potrzebuje dostępu do odczytu / zapisu do wszystkich obrazów (np. Taka, która automatycznie usuwa wyraźne obrazy)?
Ustawiliśmy dwa uprawnienia w JWT użytkownika, jeden to CRUD_OwnImages, drugi to READ_ForAnalysis. Usługa tagowania może sprawdzić, czy użytkownik ma uprawnienia READ_ForAnalysis, a jeśli tak, złóż odpowiednie żądanie. Mamy kolejną mikrousługę, która sprawdza, czy użytkownik ma CRUD_OwnImages do operacji CRUD na własnych obrazach użytkownika. To nakłada na każdą mikrousługę odpowiedzialność za zapewnienie, że użytkownik jest ograniczony do wymaganych działań. Dzięki temu podejściu magazyn obrazów nie ma możliwości ograniczenia każdej mikrousługi, dlatego jest potencjalnie płatkowy i podatny na błędy.
Dajemy mikroserwisowi tagowania własnego użytkownika, z uprawnieniem READ_ForAnalysis. Następnie, gdy usługa tagowania żąda obrazów z magazynu obrazów, ma do nich dostęp, ale nie wolno ich modyfikować. Użytkownik użytkownika ma tylko uprawnienie CRUD_OwnImages, więc może pobierać i uzyskiwać dostęp tylko do swoich obrazów z interfejsu użytkownika. Jeśli inna usługa potrzebuje CRUD do wszystkich danych, możemy nadać jej CRUD_AllData lub podobny. Podobało nam się to podejście, ponieważ każda usługa jest teraz odpowiedzialna za własne dane (zamiast tej logiki powielanej w wielu usługach), ale co, jeśli usługa wymaga zarówno uprawnień użytkownika, jak i uprawnień mikrousług? Czy możemy bezpiecznie wysyłać dwa tokeny JWT (zarówno użytkownika, jak i mikrousługę)? Czy istnieje sposób, aby bezpiecznie łączyć uprawnienia i przesyłać je przez? na przykład
Problem nasila się, jeśli informacje o użytkowniku są potrzebne w dalszej części procesu (w odległości 2 lub 3 mikrousług). Czy po prostu zakładamy, że od pojedynczych mikrousług zależą tylko działania, których potrzebują, a nie wyraźne?
Odpowiedzi:
Ogólnie rzecz biorąc, jak najwięcej operacji należy powiązać z rzeczywistym, ludzkim użytkownikiem. Zmusza ludzi do prawidłowego uwierzytelnienia, dąży do opracowania jednej spójnej strategii autoryzacji i jest ważną częścią zapewniania spójnej ścieżki audytu.
Ogólnie rzecz biorąc, istnieją trzy rodzaje scenariuszy z mikrousługami:
1. Użytkownik wchodzi, przesyła zdjęcie i należy je oznaczyć. Świetny. Usługa fotograficzna może po prostu przekazać JWT do usługi tagowania (lub odwrotnie, w zależności od kierunku zależności), a jeśli użytkownik nie ma uprawnień do wykonania podoperacji, należy podjąć odpowiednie działanie (być może przesłać zdjęcie bez tagu , może zwrócić błąd, może coś innego).
2. Użytkownik wchodzi, przesyła zdjęcie i należy je oznaczyć ... ale nie teraz. Chłodny. Teraz traktujesz zdjęcie jak zwykle. Później, gdy nastąpi tagowanie (obsługa zdarzeń / komunikatów, przetwarzanie komend w stylu CQRS, niektóre okresowe przetwarzanie zadań, cokolwiek) usługa tagowania podszywa się pod użytkownika (najprawdopodobniej za pomocą wspólnego klucza tajnego, aby poprosić o niestandardowy JWT od autoryzacji), a następnie zrobić podoperacja w imieniu pierwotnego wnioskodawcy (ze wszystkimi ich uprawnieniami i ograniczeniami). Ta metoda ma zwykły problem z operacjami asynchronicznymi, w których trudno jest przekazać użytkownikowi błędy, jeśli sprawy nie idą gładko, ale jeśli używasz tego wzorca do operacji obejmujących wiele usług, już to rozwiązałeś.
3. Niektóre podsystemy muszą wykonywać czynności poza kontekstem użytkownika. Może masz jakąś nocną pracę do archiwizacji starych zdjęć. Być może twoje tagi wymagają konsolidacji ... W tym przypadku prawdopodobnie chcesz, aby każdy z tych aktorów miał własnego pseudo-użytkownika z ograniczonymi uprawnieniami i unikalnym identyfikatorem dla ścieżki audytu.
Które stosować będą się różnić w zależności od scenariusza, potrzeb i tolerancji ryzyka. I oczywiście są to po prostu niepełny zestaw uogólnień o szerokim obrysie.
Ale ogólnie same mikrousługi nie powinny być użytkownikami, jeśli to możliwe.
źródło