Wdrożenie Keycloak na Kubernetes z przykładową aplikacją w NSIS
Keycloak to duży pakiet Open-Source do zarządzania tożsamością, który może obsługiwać szeroki zakres przypadków zastosowań związanych z tożsamością.
Korzystając z Keycloak, można łatwo wdrożyć solidne rozwiązanie uwierzytelniania/autoryzacji dla swoich aplikacji. Po wstępnym wdrożeniu można je łatwo skonfigurować, aby spełniało nowe wymagania związane z tożsamością, na przykład uwierzytelnianie wieloskładnikowe, federację z dostawcami usług społecznościowych, niestandardowe zasady dotyczące haseł i wiele innych.
Co zamierzamy zrobić?
Wdrożenie Keycloak w klastrze Kubernetes
Konfiguracja Keycloak: utworzenie domeny, klienta i użytkownika
Wdrożenie przykładowej aplikacji internetowej w języku Python przy użyciu uwierzytelniania przez Keycloak
Wymagania wstępne
Nr 1 Hosting
Wymagane jest konto hostingowe NSIS z interfejsem Horizon https://horizon.cloudferro.com.
Nr 2 Uruchomiony klaster Kubernetes i aktywowany kubectl.
Aby utworzyć klaster Kubernetes, patrz artykuł Jak utworzyć klaster Kubernetes przy użyciu NSIS OpenStack Magnum. Aby aktywować kubectl, zobacz artykuł Jak uzyskać dostęp do klastra Kubernetes po wdrożeniu przy użyciu Kubectl na NSIS OpenStack Magnum?.
Nr 3 Podstawowa znajomość języka Python i zarządzania pakietami pip
Wymagana jest podstawowa znajomość języka Python i zarządzania pakietami pip. Python 3 i pip powinny być już zainstalowane i dostępne na lokalnym komputerze.
Nr 4 Znajomość terminologii OpenID Connect (OIDC)
Wymagana jest pewna znajomość terminologii OpenID Connect (OIDC). Niektóre kluczowe terminy zostaną pokrótce wyjaśnione w tym artykule.
Krok 1 Wdrożenie Keycloak na Kubernetes
Najpierw utwórzmy dedykowaną przestrzeń nazw Kubernetes dla Keycloak. Jest to opcjonalne, ale stanowi dobrą praktykę:
kubectl create namespace keycloak
Następnie w tej przestrzeni nazw należy wdrożyć Keycloak:
kubectl create -f https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/latest/kubernetes-examples/keycloak.yaml -n keycloak
Keycloak domyślnie jest udostępniany jako usługa Kubernetes typu LoadBalancer na porcie 8080. Musisz znaleźć publiczny adres IP usługi za pomocą następującego polecenia (pamiętaj, że może to zająć kilka minut):
kubectl get services -n keycloak
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
keycloak LoadBalancer 10.254.8.94 64.225.128.216 8080:31228/TCP 23h
Informacja
W naszym przypadku zewnętrzny adres IP to 64.225.128.216, więc właśnie tego adresu będziemy używać w tym artykule. Pamiętaj, aby zastąpić go własnym adresem IP.
Tak więc, wpisz http://64.225.128.216:8080/ do przeglądarki, aby uzyskać dostęp do Keycloak:
Następnie kliknij Administration Console, nastąpi przekierowanie do ekranu logowania, gdzie możesz zalogować się jako administrator (login/hasło admin/admin).
Pełnoekranowy widok okna Keycloak wygląda następująco :
Krok 2 Utworzenie obszaru Keycloak
W terminologii Keycloak, realm (obszar) jest dedykowaną przestrzenią do zarządzania izolowanym podzbiorem użytkowników, ról i innych powiązanych podmiotów. Keycloak ma początkowo główny obszar używany do administrowania samym Keycloak.
Następnym krokiem jest utworzenie własnego obszaru i rozpoczęcie pracy w jego kontekście. Aby go utworzyć, kliknij najpierw pole master w lewym górnym rogu, a następnie kliknij przycisk Create Realm.
Wprowadzimy tylko nazwę obszaru myrealm, pozostawiając resztę opcji bez zmian:
Kiedy obszar zostanie utworzona (i wybrany), będziemy pracować w tym obszarze:
W lewym górnym rogu zamiast master jst teraz wyświetlana nazwa wybranego obszaru (myrealm).
Krok 3 Utworzenie i konfiguracja klienta Keycloak
Klienty są w Keycloak podmiotami, które mogą zażądać od Keycloak uwierzytelnienia użytkowników. W praktyce można je traktować jako reprezentację poszczególnych aplikacji, które chcą korzystać z uwierzytelniania / autoryzacji zarządzanej przez Keycloak.
W obszarze myrealm utworzymy teraz klienta myapp, który będzie reprezentował aplikację internetową, którą utworzymy w jednym z dalszych kroków. Aby utworzyć takiego klienta, kliknij panel Clients w lewym menu, a następnie przycisk Create Client.
Pojawi się kreator zawierający 3 kroki. W pierwszym kroku wprowadzamy jedynie ID klienta (w naszym przypadku jest to myapp), pozostawiając pozostałe ustawienia bez zmian:
Następny ekran zawiera wybór niektórych kluczowych ustawień związanych z wymaganiami uwierzytelniania/autoryzacji określonej aplikacji.
Wybór opcji zależy od konkretnego scenariusza:
- Scenariusz 1 Tradycyjne aplikacje serwerowe
Na potrzeby tego artykułu i naszej aplikacji demonstracyjnej używamy tradycyjnej aplikacji klient-serwer. Następnie musimy włączyć przełącznik „Client Authentication”.
- Scenariusz 2 Aplikacje jednostronicowe (SPA)
W przypadku aplikacji jednostronicowych można pozostać przy ustawieniach domyślnych, w których przełącznik „Client Authentication” jest wyłączony.
W naszej aplikacji demonstracyjnej będziemy wymagać uwierzytelnienia za pomocą tajnego kodu, więc pamiętaj, aby włączyć opcję Client Authenication. Po jej włączeniu będziemy mogli uzyskać wartość secret później, w kroku 5.
Ostatnim krokiem kreatora jest ustawienie kilku kluczowych parametrów naszej aplikacji klienckiej. Te, które modyfikujemy, obejmują:
- Root URL
W naszym przypadku chcemy wdrożyć aplikację lokalnie, więc ustawiliśmy katalog główny jako http://localhost . Musisz to zmienić, jeśli Twoja aplikacja będzie dostępna jako usługa publiczna.
- Valid redirect URIs
To ustawienie reprezentuje trasę w naszej aplikacji, do której użytkownik zostanie przekierowany po pomyślnym zalogowaniu z Keycloak. W naszym przypadku pozostawiamy to ustawienie bardzo permisywnie jako „*”, umożliwiając przekierowanie do dowolnej ścieżki w naszej aplikacji. W przypadku środowiska produkcyjnego należy to zrobić bardziej wyraźnie, używając do tego celu dedykowanej trasy, ba przykład /callback.
- Web origins
To ustawienie określa hosty, które mogą wysyłać żądania do Keycloak. Żądania z innych hostów nie przejdą kontroli cross-origin i zostaną odrzucone. Również tutaj jesteśmy bardzo permisywni, ustawiając „*”. Podobnie jak powyżej, zdecydowanie rozważ zmianę tego ustawienia w przypadku środowiska produkcyjnego i ograniczenie go tylko do zaufanych źródeł.
Po naciśnięciu przycisku Save klient zostanie utworzony. Następnie można zmienić wcześniej wybrane ustawienia utworzonego klienta i dodać nowe, bardziej szczegółowe. Istnieją ogromne możliwości dalszego dostosowywania w zależności od specyfiki aplikacji, jednak wykracza to poza zakres tego artykułu.
Krok 4 Utworzenie użytkownika w Keycloak
Po utworzeniu klienta przejdziemy do utworzenia pierwszego użytkownika w Keycloak. Aby to zrobić, kliknij kartę Users po lewej stronie, a następnie kliknij przycisk Create New User:
Ponownie będziemy bardzo selektywni i wybierzemy tylko test jako nazwę użytkownika, pozostawiając inne opcje bez zmian:
Następnie ustawimy poświadczenia hasła dla nowo utworzonego użytkownika. Wybierz kartę Credentials, a następnie Set password. W formularzu wpisz hasło, potwierdź je i naciśnij przycisk Save:
Krok 5 Pobranie tajnego klucza klienta z Keycloak
Po skonfigurowaniu Keycloak będziemy musieli wyodrębnić tajny kod klienta, aby Keycloak ustanowił zaufanie do naszej aplikacji.
Tajny kod client_secret można wyodrębnić, przechodząc do obszaru myrealm, wybierając myapp jako klienta, a następnie pobierając tajny kod klienta za pomocą następującej sekwencji poleceń:
Clients –> Client detail –> Credentials
Po przejściu na kartę Credenials tany kod będzie dostępny w polu Client secret:
Ze względu na prywatność, na powyższym zrzucie jest on zamalowany na żółto. W twoim przypadku zanotuj jego wartość, ponieważ w następnym kroku będzie trzeba ją wkleić do kodu aplikacji.
Krok 6 Utworzenie aplikacji Flask wykorzystującej uwierzytelnianie Keycloak
Do zbudowania aplikacji użyjemy Flask, który jest lekkim frameworkiem webowym opartym na języku Python. Keycloak obsługuje również wiele innych technologii. Użyjemy biblioteki Flask-OIDC, która rozszerza Flask o możliwość uruchamiania scenariuszy uwierzytelniania/autoryzacji OpenID Connect.
Jako wymaganie wstępne należy zainstalować następujące pakiety pip, aby obsłużyć łańcuch zależności. Najlepiej uruchamiać polecenia z już zainstalowanego wirtualnego środowiska Python:
pip install Werkzeug==2.3.8
pip install Flask==2.0.1
pip install wheel==0.40.0
pip install flask-oidc==1.4.0
pip install itsdangerous==2.0.1
Następnie należy utworzyć 2 pliki: app.py i keycloak.json. Będzie konieczne wykonanie w tych plikach następujących zmian:
- Zastąp adres IP
W pliku keycloak.json zastąp 64.225.128.216 własnym zewnętrznym adresem IP z kroku 1.
- Zastąp client_secret
Również w pliku keycloak.json zastąp wartość zmiennej client_secret tajnym kodem z Kroku5.
- Zastąp client_secret
W pliku app.py zastąp wartość SECRET_KEY tym samym tajnym kodem z Kroku 5.
Utwórz nowy plik o nazwie app.py i wklej do niego poniższą zawartość:
from flask import Flask, g
from flask_oidc import OpenIDConnect
import json
app = Flask(__name__)
app.config.update(
SECRET_KEY='XXXXXX',
OIDC_CLIENT_SECRETS='keycloak.json',
OIDC_INTROSPECTION_AUTH_METHOD='client_secret_post',
OIDC_TOKEN_TYPE_HINT='access_token',
OIDC_SCOPES=['openid','email','profile'],
OIDC_OPENID_REALM='myrealm'
)
oidc = OpenIDConnect(app)
@app.route('/')
def index():
if oidc.user_loggedin:
info = oidc.user_getinfo(["preferred_username", "email", "sub"])
return 'Welcome %s' % info.get("preferred_username")
else:
return '<h1>Not logged in</h1>'
@app.route('/login')
@oidc.require_login
def login():
token = oidc.get_access_token()
info = oidc.user_getinfo(["preferred_username", "email", "sub"])
username = info.get("preferred_username")
return "Token: " + token + "<br/><br/> Username: " + username
@app.route('/logout')
def logout():
oidc.logout()
return '<h2>Hi, you have been logged out! <a href="/">Return</a></h2>'
Kod aplikacji uruchamia aplikację Flask i zapewnia konfiguracje niezbędne dla flask_oidc. Należy skonfigurować następujące parametry:
nazwa obszaru
klient secret_key oraz
dodatkowe ustawienia, które odzwierciedlają nasz specyficzny przepływ dla próbki.
Ponadto ta konfiguracja wskazuje na inny plik konfiguracyjny, keycloak.json, który odzwierciedla dalsze ustawienia naszego obszaru Keycloak. W szczególności można w nim znaleźć identyfikator klienta i tajny kod, a także punkty końcowe, w których Keycloak udostępnia dalsze informacje o ustawieniach obszaru.
Utwórz wymagany plik keycloak.json, w tym samym katalogu roboczym co plik app.py:
{
"web": {
"client_id": "myapp",
"client_secret": "XXXXXX",
"auth_uri": "http://64.225.128.216:8080/realms/myrealm/protocol/openid-connect/auth",
"token_uri": "http://64.225.128.216:8080/realms/myrealm/protocol/openid-connect/token",
"issuer": "http://64.225.128.216:8080/realms/myrealm",
"userinfo_uri": "http://64.225.128.216:8080/realms/myrealm/protocol/openid-connect/userinfo",
"token_introspection_uri": "http://64.225.128.216:8080/realms/myrealm/protocol/openid-connect/token/introspect",
"redirect_uris": [
"http://localhost:5000/*"
]
}
}
Zauważ, że app.py tworzy 3 trasy:
- /
W tej trasie wyświetlana jest strona zawierająca nazwę zalogowanego użytkownika. Alternatywnie, jeśli użytkownik nie jest jeszcze zalogowany, wyświetlany jest monit o zalogowanie.
- /login
Ta trasa przekierowuje użytkownika do strony logowania Keycloak i po pomyślnym uwierzytelnieniu podaje nazwę użytkownika i token
- /logout
Wprowadzenie tej trasy powoduje wylogowanie użytkownika.
Krok 7 Test aplikacji
Aby przetestować aplikację, wykonaj poniższe polecenie z katalogu roboczego, w którym znajduje się plik app.py:
flask run
Wynik w oknie CLI jest następujący:
Teraz wiemy, że localhost uruchomia serwer Flask na porcie 5000. Wpisz localhost:5000 w pasku adresu przeglądarki, zostanie wtedy wyświetlona strona obsługiwana na trasie podstawowej: / . Użytkownik nie został jeszcze zalogowany, dlaetego jest wyświetlany odpowiedni komunikat:
Następnym krokiem jest wprowadzenie trasy /login. W pasku adresu przeglądarki należy wpisać localhost:5000/login. Spowoduje to przekierowanie do Keycloak z prośbą o zalogowanie się do myapp:
Aby się uwierzytelnić, wprowadź nazwę użytkownika utworzoną w kroku 3 (nazwa użytkownika: test) oraz hasło użyte do utworzenia tego użytkownika. Przy domyślnych ustawieniach, po pierwszym zalogowaniu może pojawić się prośba o zmianę hasła, wtedy należy postępować zgodnie z instrukcjami. Po zalogowaniu nasza nazwa użytkownika i token zostaną wyświetlone (ze względów bezpieczeństwa, część tokena jest zamalowana na żółto):
Ostatnią trasą do przetestowania jest /logout . Po wpisaniu localhost:5000/logout w przeglądarce można zobaczyć poniższy ekran. Wpisanie tej trasy wywołuje metodę flask-oidc, która wylogowuje użytkownika oraz czyści plik cookie sesji.