AI Gateway - Część 2, Kontrola dostępu
W poprzednim artykule omówiłem scenariusze balansowania ruchu przez APIM (Azure API Management) pomiędzy wieloma instancjami Azure OpenAI. Jeśli jeszcze nie miałaś/eś okazji się z nim zapoznać, gorąco zapraszam do lektury!
W tej części skupię się na scenariuszach kontroli dostępu do usługi. Jakie modele dostępu są wspierane przez Azure OpenAI i jak zaprząc do tego APIMa, by zrealizować wymagania uwierzytelniania i autoryzacji w Twojej firmie lub projekcie.
Metody uwierzytelniania w Azure OpenAI
Usługa wspiera dwa sposoby uwierzytelniania wysyłanych żądań do API, są to:
- Uwierzytelnianie przy pomocy klucza. W takim podejściu mamy obowiązek załączyć nagłówek HTTP o nazwie “api-key” i w jego wartości przekazać współdzielony klucz do usługi.
- Uwierzytelnianie przy pomocy tożsamości Entra ID (użytkownicy, aplikacje, managed identity). W takim przypadku “logujemy się” do Azure pozyskując token JWT. Następnie token dołączamy w nagłówku HTTP “Authorization” jako Bearer.
W tym miejscu warto podkreślić, że według Azure Security Benchmark wskazane jest używanie Entra ID. Może się jednak zdarzyć, że biblioteki lub rozwiązania integrujące się z OpenAI nie potrafią posłużyć się logowaniem z Entra ID. Wykonujemy wtedy analizę ryzyka i docelowo włączamy klucze jako odstępstwo od tej reguły.
Pewnie się zastanawiasz, dlaczego klucze nie są rekomendowane. Oto kilka powodów:
- Nie wspierają granularnych uprawnień.
- Jeden klucz jest przekazywany do wielu aplikacji i trudno zweryfikować kto wysyła żądanie.
- Mocno utrudnione jest zarządzanie ich cyklem życia. Klucze trzeba rotować jednorazowo w wielu aplikacjach i systemach.
- Nie mamy kontroli gdzie, kiedy i jak taki klucz jest przechowywany w aplikacji, a to grozi jego wyciekiem.
Kontrola dostępu - RBAC
Jeżeli skonfigurujesz usługę Azure OpenAI zgodnie z powyższymi rekomendacjami możesz ustawić poszczególnym osobom czy aplikacjom uprawnienia w oparciu o RBAC (Role-Based Access Control).
Takie uprawnienia mogą być nadawane całym grupom, na różnych poziomach w usłudze, wliczając w to pojedyncze modele. Istnieje oczywiści możliwość budowania własnych ról z uprawieniami, ja jednak preferuje te wbudowane, dostarczone przez platformę Azure.
Poniższa tabela zawiera informacje na temat uprawnień wynikających z poszczególnych ról w usłudze. Tabela nie zawiera wprawdzie wszystkich “built-in”, ale daje niezły pogląd na kierunek w jakim możesz podążać. Koniecznie zwróć uwagę na uprawienie do wysyłania żądań API do modeli (zaznaczone na czerwono).
APIM i walidacja tokenów
Załóżmy że używamy już APIMa chociażby z powodu balansowania ruchu opisanego w artykule, lub będziemy go używać do rozliczania tokenów, limitowania, logowania. W najprostszym scenariuszu możemy zwyczajnie przepuścić żądanie HTTP dalej bez jakichkolwiek modyfikacji na poziomie kontroli dostępu. Zrzucamy wszystkie decyzje autoryzacyjne na barki Azure OpenAI.
Bardziej zaawansowane podejście będzie wiązało się z wykonaniem prewalidacji tokenu - co kryje się pod tym pojęciem?
Na wejściu “oglądamy” token JWT i jeżeli spełnia nasze wymagania (czas życia, kto go wystawił, komu wystawił, czy docelowym systemem jest OpenAI), puszczamy żądanie dalej i znów oddajemy decyzję autoryzacyjną instancji Azure OpenAI (i jej ustawieniom RBAC). Tym sposobem jesteśmy w stanie odciąć, centralnie monitorować i poprawnie obsłużyć wszystkie nieuwierzytelnione wywołania usługi. Kod polityki może wyglądać wtedy następująco:
<policies>
<inbound>
<base />
<validate-azure-ad-token tenant-id= header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<client-application-ids>
<application-id></application-id>
<application-id></application-id>
</client-application-ids>
<required-claims>
<claim name=...>
<value>...</value>
</claim>
</required-claims>
</validate-azure-ad-token>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
W trzecim scenariuszu, jeżeli chcemy by aplikacje lub użytkownicy nie mieli bezpośredniego RBAC na instancjach Azure OpenAI możemy nadać takie uprawnienia tylko APIMowi. W takim modelu APIM ogląda token, sprawdza wymagane claimy i już z tokenem swojego MSI wykonuje pod spodem żądanie. Kod jest dość podobny, ale tym razem generujemy token MSI dla APIMa i robimy podmianę.
<inbound>
<base />
<validate-azure-ad-token tenant-id= header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<client-application-ids>
<application-id></application-id>
<application-id></application-id>
</client-application-ids>
<required-claims>
<claim name=...>
<value>...</value>
</claim>
</required-claims>
</validate-azure-ad-token>
<authentication-managed-identity resource="https://cognitiveservices.azure.com" output-token-variable-name="managed-id-access-token" ignore-error="false" />
<set-header name="Authorization" exists-action="override">
<value>@("Bearer " + (string)context.Variables["managed-id-access-token"])</value>
</set-header>
</inbound>
Autoryzacja tożsamości spoza naszej firmy
Powyższe scenariusze działają w przypadku gdy bazujemy na Entra ID, czy naszym Active Directory podłączonym do Entry. Sprawa komplikuje się, gdy w organizacji używane są inne rozwiązania do zarządzania tożsamością. W tym przypadku pewnie i tak ustawiona jest federacja i RBAC funkcjonuje poprawnie. Co jednak, gdy wystawiamy aplikację na zewnątrz i nie dajemy potencjalnym użytkownikom “loginu” w naszej firmie? Tutaj mamy kilka opcji:
- Użytkownicy i aplikacje uwierzytelniają się w oparciu o znaną nam zewnętrzną tożsamość (np rozwiązanie klasy CIAM).
- Zezwalamy użytkownikom na rejestrację przez Deweloper Portal w APIM, czyli miejsce gdzie po naszej akceptacji zakładają sobie sami konta, sami generują klucze/tokeny. Model ten jest popularny w aplikacjach SaaS i wszelkich podejściach “na subskrypcję”.
- Odwołujemy się do bliżej nieokreślonego zewnętrznego systemu autoryzacyjnego. W mojej praktyce zdarzało się integrować z takimi systemami stworzonymi w firmie, które pomijały popularne standardy i robiły rzeczy po swojemu.
W pierwszym przypadku używamy ponownie prewalidacji tokenu, ale tym razem zamiast “validate-azure-ad-token” używamy jej bardziej zaawansowanej odmiany “validate-jwt”. Poprzez wskazanie wystawcy tokenów (issuer) możemy się zintegrować z praktycznie każdym IDP, które wspiera OpenID Connect. Możemy walidować tokeny za pomocą kluczy z JWKS lub dostarczonych lokalnie, wspieramy szyfrowanie tokenów, dopuszczamy odchylenia czasowe itp.
W drugim przypadku subskrypcje APIM ogranie nam samodzielnie. Musimy jedynie wymusić na poziomie wystawianego API, by wymagał aktywnej subskrypcji w Deweloper Portalu dla wskazanego użytkownika. W takim przypadku użytkownik będzie zmuszony dokleić swój klucz subskrypcyjny do wysyłanego żądania.
W trzecim przypadku musimy się trochę bardziej napracować. W zależności od systemu zewnetrznego może to być użycie bardziej rozbudowanych polityk, w tym takich które wykonują dodatkowe zapytania autoryzacyjne albo wykorzystują inne algorytmy szyfrowania. Przykład takiej polityki znajdziesz tutaj i tutaj.
Oczywiście powyższe scenariusze nie wykluczają użycia klasycznego basic authentication, certificate authentication lub mTLS. Te z kolei metody ponownie mogą być zastąpione w locie tożsamością APIMa i jego MSI, jak to opisywałem wcześniej.
Podsumowanie
Jak widzisz tematyka kontroli dostępu w Azure OpenAI i w APIM nie należy do najłatwiejszych i wymaga specyficznej wiedzy. W zależności od założeń architektonicznych możemy jednak wykorzystać któreś z powyższych podejść.
Najważniejsze rzeczy do zapamiętania:
- W Azure OpenAI możemy uwierzytelniać się za pomocą Entra ID z RBAC, oraz za pomocą kluczy. Uzycie kluczy nie jest rekomendowane.
- W APIM możemy walidować tokeny pochodzące zarówno z Entra ID, sfederowanych z nią systemów, jak też innych rozwiązań bazujących na OpenID Connect.
- Podczas walidacji możemy puszczać żądania dalej (pass-thru), lub podstawiać token APIMa.
- Bardziej zaawansowane scenariusze mogą skutkować potrzebą tworzenia skomplikowanych polityk w APIM.
Za tydzień opublikuje kolejny artykuł o tym, jak kontrolować wykorzystanie tokenów OpenAI przy pomocy APIMa. Zapraszam do śledzenia mojego profilu, by go nie przegapić.
Comments