הגדרת אימות משתמשים ב-Cloud Service Mesh
אימות משתמשים ב-Cloud Service Mesh הוא פתרון משולב לאימות משתמשי קצה מבוסס-דפדפן ולבקרת גישה לעומסי העבודה שפרסתם. הוא מאפשר לכם לבצע אינטגרציה עם ספקי זהויות (IDP) קיימים לצורך אימות משתמשים, ומשתמש בממשקי API ובמדיניות הרשאות של Istio לניהול גישה. זוהי חלופה ידידותית למשתמש לאימות של Istio JSON Web Token (JWT).
תרחיש שימוש אופייני הוא כשארגון משתמש ב-Cloud Service Mesh כדי לארח אפליקציית אינטרנט שהעובדים יכולים לגשת אליה דרך דפדפן אינטרנט. בנוסף, הארגון צריך להשתמש בספק הזהויות הקיים שלו כדי לנהל את זהויות המשתמשים. אימות משתמשים ב-Cloud Service Mesh מאפשר למשתמשים לבצע אימות בקלות באמצעות תהליך כניסה והסכמה רגיל מבוסס-אינטרנט של OpenID Connect (OIDC). כשהמשתמש מבצע אימות, Cloud Service Mesh אוכף את מדיניות ההרשאות של Istio, ואם ההרשאה מצליחה, הוא מעביר את הזהות לעומסי העבודה בפורמט מאובטח של פרטי כניסה.
איך זה עובד
אימות משתמשים ב-Cloud Service Mesh כולל רכיב חדש, authservice.
הרכיב הזה משולב עם שער הכניסה מבוסס-Envoy כשירות הרשאה חיצוני שמיירט את כל הבקשות הנכנסות לאימות. authservice מטמיע את הצד של הלקוח בפרוטוקול OIDC ומאפשר למשתמשים לגשת לאפליקציות דרך דפדפן, שבו המשתמשים משלימים תהליך אימות והסכמה אינטראקטיבי כדי ליצור סשן קצר טווח.
authservice מטמיע פרוטוקולים סטנדרטיים בתעשייה כדי להשתלב עם כל ספק זהויות שיכול לשמש כשרת הרשאות OIDC. כשמתבצעת אימות של המשתמש, פרטי הגורם המרכזי מוצפנים ב-RCToken בפורמט JWT, נחתמים על ידי authservice ומועברים לשכבת ההרשאה של Istio בנקודת הכניסה. המודל הזה מספק בקרת גישה היקפית לתנועה שנכנסת לרשת. אם למשתמש יש הרשאה לגשת למשאב, ה-RCToken הזה מועבר גם למיקרו-שירותים כדי לקבל מידע על הגורם המורשה ולאכוף בקרת גישה ברמת דיוק גבוהה.
בתרשים הבא מוצג המיקום של authservice ברשת, והקשר שלו לחלקים אחרים ברשת, כמו תעבורת הכניסה, עומסי העבודה, הדפדפן של המשתמש וכל ספק זהויות קיים.
אדמינים יכולים להתקין את authservice כתוסף על גבי התקנה של Cloud Service Mesh. אחרי ההתקנה, authservice קורא את ההגדרות של נקודת הקצה של OIDC והגדרות משויכות אחרות שמוגדרות במשאב המותאם אישית UserAuth. האדמין יכול להשתמש בממשקי API של Cloud Service Mesh ExternalAuthorization כדי להגדיר את auth_server כמסנן בתעבורת הכניסה.
התקנה של שירות אימות המשתמש
בשלבים הבאים מוסבר איך להגדיר את authservice.
דרישות מוקדמות
פועלים לפי השלבים במאמר התקנת כלים תלויי-הקשר ואימות האשכול כדי:- אם אתם משתמשים ב-Cloud Service Mesh מנוהל באשכול פרטי, אתם צריכים לוודא שהאשכול יכול לשלוח תנועת נתונים יוצאת אל ספק הזהויות.
בנוסף, צריך לוודא שאתם עומדים בדרישות המוקדמות באמצעות השלבים הבאים.
התאמה אישית של שכבת-העל לאימות משתמשים בהתקנה
כדי להתקין את שירות אימות המשתמשים, צריך להתאים אישית את ההתקנה של Cloud Service Mesh כדי להוסיף ספק הרשאות חיצוני ברמת הרשת. השלבים הנדרשים תלויים בשאלה אם אתם משתמשים ב-Cloud Service Mesh מנוהל או ב-Cloud Service Mesh בתוך האשכול.
מנוהל
מעדכנים את ConfigMap כדי לכלול את MeshConfig של אימות המשתמש. בפקודה הבאה, צריך להשתמש באותו
REVISION_LABELשבו השתמשתם כשהקציתם Cloud Service Mesh מנוהל (למשל,asm-managed,asm-managed-rapidאוasm-managed-stable):kubectl edit configmap istio-REVISION_LABEL -n istio-systemמוסיפים את הטקסט הבא בשדה
meshב-MeshConfig:mesh: |- ... extensionProviders: - name: "asm-userauth-grpc" envoyExtAuthzGrpc: service: "authservice.asm-user-auth.svc.cluster.local" port: "10003"יוצרים מרחב שמות
asm-user-auth.kubectl create namespace asm-user-authמפעילים את מרחב השמות להחדרה. השלבים תלויים בהטמעה של מישור הבקרה.
מנוהל (TD)
מחילים את תווית ההזרקה שמוגדרת כברירת מחדל על מרחב השמות:
kubectl label namespace asm-user-auth \ istio.io/rev- istio-injection=enabled --overwriteמנוהל (Istiod)
מומלץ: מריצים את הפקודה הבאה כדי להחיל את תווית ברירת המחדל של הזרקה על מרחב השמות:
```sh kubectl label namespace asm-user-auth \ istio.io/rev- istio-injection=enabled --overwrite ```אם אתם משתמשים קיימים במישור הבקרה המנוהל של Istiod: מומלץ להשתמש בהזרקה שמוגדרת כברירת מחדל, אבל יש תמיכה גם בהזרקה מבוססת-עדכון. פועלים לפי ההוראות הבאות:
- מריצים את הפקודה הבאה כדי לאתר את ערוצי ההפצה הזמינים:
kubectl -n istio-system get controlplanerevisionהפלט אמור להיראות כך:
NAME AGE asm-managed-rapid 6d7hבפלט, הערך בעמודה
NAMEהוא תווית הגרסה שתואמת לערוץ ההפצה שזמין לגרסה של Cloud Service Mesh.מחילים את תווית הגרסה על מרחב השמות:
kubectl label namespace asm-user-auth \ istio-injection- istio.io/rev=REVISION_LABEL --overwrite
מתקינים את שער Istio במרחב השמות
asm-user-auth.kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
בתוך האשכול
אפשר להוריד את הדוגמה של שכבת-על לאימות משתמשים ולעדכן אותה אם יש התאמות אישיות ברשת שלכם. מומלץ לשמור את קובץ השכבה העליונה הזה בבקרת המקור.
curl https://raw.githubusercontent.com/GoogleCloudPlatform/asm-user-auth/v1.2.5/overlay/user-auth-overlay.yaml > user-auth-overlay.yamlכדי להתקין את Cloud Service Mesh עם שכבת-על של אימות משתמשים, צריך לפעול לפי ההוראות במאמר התקנת Cloud Service Mesh עם שכבת-על ולהשתמש בסקריפט שסופק על ידי Google. לדוגמה:
./asmcli install \ --project_id PROJECT_ID \ --cluster_name CLUSTER_NAME \ --cluster_location CLUSTER_LOCATION \ --fleet_id FLEET_PROJECT_ID \ --output_dir DIR_PATH \ --enable_all \ --custom_overlay user-auth-overlay.yamlחבילות האימות של המשתמש יוצרות
kptכדי להפנות לספק ההרשאות החיצוני שצוין על ידיAuthorizationPolicypkg/ext-authz.yaml.יוצרים מרחב שמות
asm-user-auth.kubectl create namespace asm-user-authמפעילים את מרחב השמות להחדרה.
מומלץ: מריצים את הפקודה הבאה כדי להחיל את תווית ברירת המחדל של הזרקה על מרחב השמות:
kubectl label namespace asm-user-auth \ istio.io/rev- istio-injection=enabled --overwriteמומלץ להשתמש בהחדרה שמוגדרת כברירת מחדל, אבל יש תמיכה גם בהחדרה שמבוססת על תיקון: פועלים לפי ההוראות הבאות:
משתמשים בפקודה הבאה כדי לאתר את תווית הגרסה ב-
istiod:kubectl get deploy -n istio-system -l app=istiod -o \ jsonpath={.items[*].metadata.labels.'istio\.io\/rev'}'{"\n"}'מחילים את תווית הגרסה על מרחב השמות. בפקודה הבאה,
REVISION_LABELהוא הערך של התוויתistiodrevision שרשמתם בשלב הקודם.kubectl label namespace asm-user-auth \ istio-injection- istio.io/rev=REVISION_LABEL --overwrite
מתקינים את שער Istio במרחב השמות
asm-user-auth.kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
הכנת ההגדרות של לקוח OIDC
כדי להגדיר את לקוח ה-OIDC: במדריך הזה נעשה שימוש ב-Google כספק זהויות, אבל אפשר להשתמש בכל ספק זהויות שתומך באימות OIDC.
במסוף Google Cloud , נכנסים אל API & Services > Credentials.
עוברים אל Create Credentials (יצירת פרטי כניסה) ובוחרים באפשרות OAuth client ID (מזהה לקוח OAuth). אם נדרש, מגדירים את האפשרויות של מסך ההסכמה ל-OAuth, ואז מגדירים את האפשרויות הבאות:
- מגדירים את Application type (סוג האפליקציה) ל-Web application (אפליקציית אינטרנט).
- מגדירים את Authorized redirect URI (כתובת ה-URI המורשית להפניה אוטומטית) לערך
https://REDIRECT_HOST/REDIRECT_PATH. לדוגמה, בשביל localhost אפשר להגדיר את הערךhttps://localhost:8443/_gcp_asm_authenticate.
לאחר מכן, לוחצים על שמירה.
בנוסף, שומרים את הגדרות הלקוח של OIDC לשימוש מאוחר יותר.
export OIDC_CLIENT_ID=CLIENT_ID export OIDC_CLIENT_SECRET=CLIENT_SECRET export OIDC_ISSUER_URI=ISSUER_URI export OIDC_REDIRECT_HOST=REDIRECT_HOST export OIDC_REDIRECT_PATH=REDIRECT_PATH
קבלת חבילות kpt
כדי להתקין את ההגדרה המומלצת authservice ממאגר ציבורי, פועלים לפי השלבים הבאים. הפקודות האלה מאחזרות את מאגר authservice העדכני ומפעילות אותו כ-Pod במרחב השמות asm-user-auth. היא גם מגדירה את ה-ingress ליירוט של כל הבקשות.
מורידים את חבילת kpt:
kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.5 .
cd asm-user-auth/
הגדרת כתובת ה-URL להפניה אוטומטית והסוד של שער הכניסה
OAuth2 דורש כתובת URL להפניה אוטומטית שמתארחת בנקודת קצה שמוגנת באמצעות HTTPS. הפקודות האלה הן דוגמאות שמפשטות את ההגדרה על ידי יצירת אישור בחתימה עצמית לשער הכניסה של Istio.
יצירת אישור בחתימה עצמית:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \ -days 365 -nodes -subj '/CN=localhost'יוצרים סוד בשביל שער הכניסה כדי לארח תנועת HTTPS:
kubectl create -n asm-user-auth secret tls userauth-tls-cert --key=key.pem \ --cert=cert.pem
החלת מפתחות ההצפנה והחתימה
כדי שהמערכת תפעל בצורה תקינה, צריך שני סטים של מפתחות.authservice הראשון הוא מפתח סימטרי להצפנה ולפענוח. המפתח הזה משמש להצפנה של מצב הסשן לפני שמגדירים אותו כקובץ Cookie.
קבוצת המפתחות השנייה היא זוג מפתחות ציבוריים/פרטיים. המפתח הזה משמש לחתימה על פרטי המשתמש המאומת בפורמט JWT בתור RCToken. המפתח הציבורי מהזוג הזה מתפרסם בנקודת קצה מוגדרת מראש, שקובצי ה-sidecar יכולים להשתמש בה כדי לאמת את ה-JWT.
חבילת kpt לאימות משתמשים מכילה שני מפתחות לדוגמה להגדרה מהירה.
עם זאת, אפשר להשתמש במערכת ניהול המפתחות המועדפת כדי ליצור את המפתחות האלה.
מכינים את מפתח ההצפנה של הסשן בפורמט הבא או משתמשים בדוגמה מתוך חבילת ה-pkg, שאפשר לראות אותה באמצעות
cat ./samples/cookie_encryption_key.json.{ "keys":[ { "kty":"oct", "kid":"key-0", "K":"YOUR_KEY", "useAfter": 1612813735 } ] }אפשר ליצור מפתח AES לבדיקה באמצעות הפקודה הבאה:
openssl enc -aes-256-cbc -k mycustomkey -P -md sha1 | grep keyמכינים את מפתח החתימה של RCToken בפורמט הבא או משתמשים בדוגמה מ-pkg, שאפשר לראות אותה באמצעות
cat ./samples/rctoken_signing_key.json.{ "keys":[ { "kty":"RSA", "kid":"rsa-signing-key", "K":"YOUR_KEY", # k contains a Base64 encoded PEM format RSA signing key. "useAfter": 1612813735 # unix timestamp } ] }אפשר ליצור מפתח פרטי של RSA ל-512 ביט לבדיקה באמצעות הפקודה הבאה:
openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:512יוצרים את הסוד של Kubernetes, ש-
authserviceיותקן במערכת קבצים משלו.kubectl create secret generic secret-key \ --from-file="session_cookie.key"="./samples/cookie_encryption_key.json" \ --from-file="rctoken.key"="./samples/rctoken_signing_key.json" \ --namespace=asm-user-auth
פריסת שירות אימות המשתמש
הפקודות הבאות יוצרות את שירות אימות המשתמשים ואת הפריסה במרחב השמות asm-user-auth.
מגדירים את הערכים הנדרשים להגדרת אימות משתמשים. מזהה הלקוח והסוד מאוחסנים כסודות של Kubernetes, ולכן אנחנו משתמשים ב-Base64 כדי לקודד אותם. אפשר לעיין בכל הפונקציות הזמינות להגדרת מאפיינים במאגר הציבורי.
kpt fn eval pkg --image gcr.io/kpt-fn/apply-setters:v0.2 --truncate-output=false -- \
client-id="$(echo -n ${OIDC_CLIENT_ID} | base64 -w0)" \
client-secret="$(echo -n ${OIDC_CLIENT_SECRET} | base64 -w0)" \
issuer-uri="${OIDC_ISSUER_URI}" \
redirect-host="${OIDC_REDIRECT_HOST}" \
redirect-path="${OIDC_REDIRECT_PATH}"
החלת החבילה kpt:
# Remove the potential alpha version CRD if exists.
kubectl delete crd userauthconfigs.security.anthos.io
kubectl apply -f ./pkg/asm_user_auth_config_v1beta1.yaml
kubectl apply -f ./pkg
authservice משתמש ב-CRD UserAuthConfig כדי לספק אימות למשתמשי קצה. UserAuthConfig ניתן להגדרה בזמן הריצה, ואפשר לעדכן אותו כדי לשנות את ההתנהגות של authservice ולהגדיר אותו עם נקודות קצה לכל שרת הרשאות OIDC.
אפשר לראות את הקובץ באמצעות cat pkg/user_auth_config.yaml, והוא מכיל את השדות הבאים:
apiVersion: security.anthos.io/v1beta1
kind: UserAuthConfig
metadata:
name: user-auth-config
namespace: asm-user-auth
spec:
authentication:
oidc:
certificateAuthorityData: "" # kpt-set: ${ca-cert}
issuerURI: "<your issuer uri>" # kpt-set: ${issuer-uri}
proxy: "" # kpt-set: ${proxy}
oauthCredentialsSecret:
name: "oauth-secret" # kpt-set: ${secret-name}
namespace: "asm-user-auth" # kpt-set: ${secret-namespace}
redirectURIHost: "" # kpt-set: ${redirect-host}
redirectURIPath: "/_gcp_asm_authenticate" # kpt-set: ${redirect-path}
scopes: "" # kpt-set: ${scopes}
groupsClaim: "" # kpt-set: ${groups}
outputJWTAudience: "test_audience" # kpt-set: ${jwt-audience}
במאמר פרטים על הגדרת אימות משתמשים מופיעים תיאורים מפורטים של השדות user_auth_config.yaml.
הגדרת מזהים של בקשות API
מזהי בקשות API הם קבוצה של ביטויים ב-Common Expression Language (CEL) שמשמשים לאימות משתמשים ב-Cloud Service Mesh כדי לזהות בקשות API. הגדרת המזהים האלה מאפשרת לאימות המשתמשים ב-Cloud Service Mesh לטפל בצורה סמנטית בכשלים באימות בקשות API.
באופן ספציפי, כשמספקים ביטויי CEL שמזהים את בקשות ה-API, מאפשרים לאימות המשתמשים ב-Cloud Service Mesh להיכשל בבקשות API לא מאומתות עם קוד סטטוס 401-Unauthorized. זה חשוב במיוחד ללקוחות כמו ממשקי שורת פקודה (CLI) וחשבונות שירות, שמצפים לקוד הסטטוס הזה עבור בקשות API לא מאומתות.
בלי מזהים של בקשות API, אימות המשתמשים ב-Cloud Service Mesh יפנה מחדש את כל הבקשות שלא אומתו לספק OpenID Connect (OIDC) שהוגדר, ויחזיר קוד סטטוס 302-Found. בדרך כלל, התנהגות ההפניה האוטומטית הזו לא רצויה לבקשות API, שצפויות לקבל שגיאה 401 (לא מורשה) אם הן נכשלות.
כדי להגדיר את המזהים של בקשת ה-API, מוסיפים קטע apiRequestIdentifier אל UserAuthConfig CR. כך אפשר להוסיף כמה ביטויי CEL. אם מציינים כמה ביטויי CEL, בקשה נחשבת לבקשת API אם היא תואמת לפחות לאחד מהם.
בדוגמה הבאה מוצגות דרכים להגדיר בקשה כבקשת API: כל בקשה שמכילה את הכותרת example-api-header, כל בקשה שמופנית למארח api.example.com או כל בקשה שמטרגטת נתיב מתחת ל-/v1/api/.
apiVersion: security.anthos.io/v1beta1
kind: UserAuthConfig
metadata:
name: user-auth-config
namespace: asm-user-auth
spec:
authentication:
oidc:
certificateAuthorityData: "" # kpt-set: ${ca-cert}
issuerURI: "<your issuer uri>" # kpt-set: ${issuer-uri}
proxy: "" # kpt-set: ${proxy}
oauthCredentialsSecret:
name: "oauth-secret" # kpt-set: ${secret-name}
namespace: "asm-user-auth" # kpt-set: ${secret-namespace}
redirectURIHost: "" # kpt-set: ${redirect-host}
redirectURIPath: "/_gcp_asm_authenticate" # kpt-set: ${redirect-path}
scopes: "" # kpt-set: ${scopes}
groupsClaim: "" # kpt-set: ${groups}
outputJWTAudience: "test_audience" # kpt-set: ${jwt-audience}
apiRequestIdentifier:
name: "api-request-identifiers"
expressions:
- "'example-api-header' in http_request.headers"
- "http_request.host == 'api.example.com'"
- "matches(http_request.path, '/v1/api/(.*)')"
# other expressions go here
אפשר ליצור ביטויי CEL לאימות משתמשים ב-Cloud Service Mesh מהשדות הבאים:
http_request.headers: מפה של כותרות בקשות ה-HTTP, שבה המפתחות הם מחרוזות באותיות קטנות והערכים הם וקטורים של מחרוזות.משתמשים בשדה הזה בביטוי CEL כדי לציין בקשות עם כותרות ספציפיות כבקשות API.
http_request.host: המארח של כתובת ה-URL של ה-HTTP המבוקשת (למשלapi.example.com).אפשר להשתמש בשדה הזה בביטוי CEL כדי לציין בקשות למארחים ספציפיים כבקשות API.
http_request.path: נתיב כתובת ה-URL של ה-HTTP המבוקשת (לדוגמה,/example-api-path). הנתיב תמיד מתחיל ב-'/' ולא מכיל את רכיב השאילתה של כתובת ה-URL של הבקשה.משתמשים בשדה הזה בביטוי CEL כדי לציין בקשות עם נתיבים ספציפיים כבקשות API.
בקטע הבא מוצגות דוגמאות לביטויי CEL שבודקים חלקים מהשדות האלה ומתאימים אותם כדי להודיע לאימות המשתמשים ב-Cloud Service Mesh איך לקבוע אילו בקשות הן בקשות API.
ביטויים לדוגמה
התאמה לכל הבקשות שמכילות את הכותרת X-API-Key:
"'x-api-key' in http_request.headers"
התאמה של כל הבקשות עם הכותרת X-API-Key שהערך שלה מוגדר לערך מסוים:
"'x-api-key' in http_request.headers && http_request.headers['x-api-key'].values == ['example-value ']"
התאמה של כל הבקשות למארח api.example.com:
"http_request.host == api.example.com"
התאמה של כל הבקשות לנתיב /api/query:
"http_request.path == /api/query"
התאמה של כל הבקשות לכל נתיב מתחת ל-/api/:
"matches(http_request.path, '/api/(.*)')"
ביצוע משימות אחרי ההתקנה
אחרי שמסיימים את שלבי ההתקנה הקודמים, צריך לבצע את המשימות הבאות.
הפעלת אימות משתמשים באפליקציות
בקטע הזה מוסבר איך להפעיל אימות משתמשים, באמצעות httpbin כדוגמה.
אימות משתמשים ב-Cloud Service Mesh מתבצע באמצעות מדיניות הרשאות מוקלדת CUSTOM כדי להפעיל את תהליך OIDC.
אחרי ההתקנה של שער Istio, מגדירים אותו להצגת תנועת HTTPS באמצעות אישור ה-TLS userauth-tls-cert שיצרתם למעלה. בהמשך מוצגת ההגדרה של pkg/gateway.yaml שהתקנתם.
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: userauth
namespace: asm-user-auth
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: userauth-tls-cert
---
# This ensures the OIDC endpoint has at least some route defined.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: userauth-oidc
namespace: asm-user-auth
spec:
gateways:
- userauth
hosts:
- '*'
http:
- match:
- uri:
prefix: /status
- uri:
prefix: "your-oidc-redirect-path"
name: user-auth-route
route:
- destination:
host: authservice
port:
number: 10004
מרחב השמות של התווית
defaultכדי להפעיל הוספה אוטומטית שלistio-proxyלפריסות.kubectl label namespace default istio.io/rev=REVISION --overwriteפורסים את
httpbinלמרחב השמותdefault.kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml -n defaultמעדכנים את
httpbinכדי להשתמש בשער הזה להצגת תנועת HTTPS, ומשתמשים בהעברת פורטים כדי לגשת לאפליקציה באופן מקומי:kubectl apply -f./samples/httpbin-route.yaml -n default kubectl port-forward service/istio-ingressgateway 8443:443 -n asm-user-authשער הכניסה ביציאה 8443 יועבר אל
localhostכדי לאפשר גישה לאפליקציה באופן מקומי.פורסים את
samples/rctoken-authz.yamlכדי להפעיל את RequestAuthentication ואת AuthorizationPolicy כדי לאמת את ה-RCToken עבור הבקשות.kubectl apply -f ./samples/rctoken-authz.yaml -n asm-user-authדוגמה
samples/rctoken-authz.yaml:apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: require-rc-token spec: selector: matchLabels: istio: ingressgateway jwtRules: - issuer: "authservice.asm-user-auth.svc.cluster.local" audiences: - "test_audience" jwksUri: "http://authservice.asm-user-auth.svc.cluster.local:10004/_gcp_user_auth/jwks" fromHeaders: - name: X-ASM-RCTOKEN forwardOriginalToken: true --- apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: require-rc-token spec: selector: matchLabels: istio: ingressgateway action: ALLOW rules: - when: - key: request.auth.claims[iss] values: - authservice.asm-user-auth.svc.cluster.local - key: request.auth.claims[aud] values: - test_audience
אימות משתמשים
ה-httpbin משרת שתי נתיבים, /ip נגיש לציבור ו-/headers מחייב את משתמש הקצה להתחבר דרך ספק הזהויות שהוגדר.
מוודאים שיש לכם גישה ישירה ל-
/ipדרךhttps://localhost:8443/ip.כדי לוודא שדף הכניסה של OIDC מוצג, נכנסים לכתובת
https://localhost:8443/headers.אחרי הכניסה לחשבון, לוחצים על הבא ומוודאים שמופנים לדף
/headers.
הגדרת מדיניות הרשאות
אחרי שתסיימו את ההגדרה בשלבים הקודמים, כל משתמש יופנה מחדש לתהליך אימות מבוסס-אינטרנט. בסיום התהליך, authservice יוצר RCToken בפורמט JWT, שמשמש להעברת פרטי המשתמש המאומת.
מוסיפים מדיניות הרשאות של Istio בנקודת הכניסה כדי לוודא שמתבצעת בדיקת הרשאות לכל משתמש מאומת:
kubectl apply -f ./samples/httpbin-authz.yaml -n asm-user-authהקובץ
httpbin-authz.yamlמגדיר את שער הכניסה כדי לאמת את אסימון ה-RC שהונפק על ידי authservice, ולאשר גישה רק אם ה-JWT מכיל את השדות הרצויים, כמו קהלים ומנפיקים.דוגמה למדיניות הרשאות:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: require-rc-token spec: selector: matchLabels: istio: ingressgateway action: ALLOW rules: - to: - operation: paths: ["/ip"] - to: when: - key: request.auth.claims[iss] values: - authservice.asm-user-auth.svc.cluster.local - key: request.auth.claims[aud] values: - test_audience - key: request.auth.claims[sub] values: - allowed_user_sub_1 # Change this with the "sub" claim in the RC token. Wildcard '*' will match everything.
הגדרת הגדרות ספציפיות לסביבה
בשלבים הקודמים נעשה שימוש ב-localhost ובאישור HTTPS בחתימה עצמית כדי להגדיר את הכל במהירות. לשימוש אמיתי בסביבת הייצור, צריך להשתמש בדומיין משלכם, כמו example.com.
בנוסף, צריך לוודא ש-certificateAuthorityData מכיל את התוכן הרצוי של אישור הבסיס. לדוגמה, אם ספק ה-IDP מהימן עם אישורי הבסיס של המערכת, אפשר להשאיר את השדה הזה ריק. אם יש שרת proxy של HTTPS שמסיים את חיבור ה-HTTPS, צריך להגדיר אותו לאישור הבסיס של ה-proxy.
ניהול מפתחות ורוטציה שלהם
authservice משתמש בשני סטים של מפתחות. אפשר לסובב כל מקש בנפרד. עם זאת, לפני שמבצעים רוטציה של המפתחות, חשוב להבין איך הרוטציה פועלת.
שני המפתחות הם בפורמט JSON. השדה useAfter מציין את חותמת הזמן שממנה ואילך המפתח יהיה בשימוש. במהלך רוטציית מפתחות, צריך לכלול ב-JSON גם את המפתחות הישנים וגם את המפתחות החדשים. לדוגמה, בדוגמה הבאה, המערכת תשתמש ב-new-key רק אחרי חותמת הזמן 1712813735.
{
"keys":[
{
"kty":"RSA",
"kid":"old-key",
"K":"...", # k contains a Base64 encoded PEM format RSA signing key.
"useAfter": 1612813735, # unix timestamp
}
{
"kty":"RSA",
"kid":"new-key",
"K":"...", # k contains a Base64 encoded PEM format RSA signing key.
"useAfter": 1712813735, # unix timestamp
}
]
}
Cloud Service Mesh משתמש במפתח הסימטרי להצפנת נתוני סשן שמאוחסנים בקובצי Cookie בדפדפן. כדי לוודא שהסשנים הקיימים תקפים, authservice
מנסה לפענח עם כל המפתחות בקבוצת המפתחות. במהלך הרוטציה, authservice
ישתמש במפתח החדש להצפנת סשנים חדשים, וימשיך לנסות
לפענח באמצעות המפתחות הישנים.
זוג המפתחות הציבורי/הפרטי משמש לחתימה על RCToken. המפתח הציבורי מועבר אל קבצי ה-sidecar על ידי istiod לצורך אימות של JWT. חשוב מאוד שמכלי ה-sidecar יקבלו את המפתח הציבורי החדש לפני ש-authservice יתחיל להשתמש במפתח הפרטי החדש כדי לחתום על RCToken. לכן, authservice מתחיל לפרסם את המפתח הציבורי מיד אחרי הוספת המפתח, אבל מחכה פרק זמן משמעותי לפני שהוא מתחיל להשתמש בו כדי לחתום על RCToken.
לסיכום, כשמבצעים רוטציות של מפתחות, מומלץ:
- מבצעים רוטציות קבועות של מפתחות או לפי דרישה, בהתאם לצורך.
- בפורמט JSON, צריך לכלול גם את המפתחות הנוכחיים וגם את המפתחות החדשים. המפתחות החדשים צריכים להיות משויכים לחותמת זמן עתידית. מומלץ לציין חותמת זמן לפחות כמה שעות לפני השעה הנוכחית.
- עוקבים אחרי השירותים ומוודאים שהם עדיין תקינים אחרי שהמפתח החדש נמצא בשימוש. צריך להמתין לפחות יום אחד אחרי שמתחילים להשתמש במפתח החדש לפני שעוברים לשלב הבא.
- מסירים את המפתחות הישנים מהערכים ב-JSON. הם כבר לא נחוצים.
פריסה של כמה אשכולות
אימות משתמשים ב-Cloud Service Mesh תומך בפריסה של כמה אשכולות. צריך לפרוס אימות משתמשים בכל אשכול כמו שמתואר למעלה. צריך לשכפל בכל אשכול את הגדרות אימות המשתמש, כמו משאב מותאם אישית של UserAuth, סוד לקוח של OIDC ומפתחות הצפנה.
כברירת מחדל, שער הכניסה יבצע איזון עומסים של בקשות האימות לכל אחד מהמופעים של authservice. אפשר להשתמש בכלל יעד כדי להגדיר את שער הכניסה לשליחת בקשות אל authservice באותו אשכול, ורק אם השליחה נכשלת, להעביר את הבקשות אל authservice באשכולות אחרים.
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: authservice-fail-over
namespace: asm-user-auth
spec:
host: authservice.asm-user-auth.svc.cluster.local
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
failover:
- from: us-east
to: us-west
- from: us-west
to: us-east
בדומה להגדרות אחרות, צריך להגדיר את זה בכל אשכול.
מיפוי טענות בהתאמה אישית
כדי להגדיר מיפוי של הצהרות מותאמות אישית, מגדירים את spec.authentication.oidc.attributeMapping כדי להגדיר מיפויים מ-IDToken של ספק הזהויות המקורי. המפתח יהיה שם ההצהרה ב-RCToken, והערך יהיה ביטוי CEL שמציין איך לנתח את ההצהרה מ-IDToken. כדי להפנות אל IDToken, צריך להשתמש ב-assertion.
דוגמה:
spec:
authentication:
oidc:
attributeMapping:
aud_copy: assertion.aud
decision: 'assertion.sub.startsWith("123") ? "success" : "fail"'
ב-RCToken, טענה מוטמעת attributes מכילה את הטענות שהוגדרו:
"attributes": {
"aud_copy": "foo.googleusercontent.com",
"decision": "success"
}
אם ניתוח הערך מ-IDToken באמצעות ביטוי CEL נכשל, הטענה תתעלם מהערך בלי לגרום לכשל בתהליך האימות.
שדרוגים של אימות משתמשים
מתקינים מחדש את חבילות אימות המשתמשים, כי הן מכילות את הקובץ הבינארי המעודכן לגרסה החדשה של אימות המשתמשים:
kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.5 . cd asm-user-auth/שומרים את הגדרות הלקוח של OIDC:
export OIDC_CLIENT_ID=CLIENT_ID export OIDC_CLIENT_SECRET=CLIENT_SECRET export OIDC_ISSUER_URI=ISSUER_URI export OIDC_REDIRECT_HOST=REDIRECT_HOST export OIDC_REDIRECT_PATH=REDIRECT_PATHפורסים את שירות אימות המשתמשים כדי לשדרג לגרסה חדשה.
פרטי ההגדרה של אימות המשתמש
בטבלה הבאה מתואר כל שדה ב-CRD:
| שם השדה | תיאור |
|---|---|
authentication.oidc |
בקטע הזה מופיעות ההגדרות של נקודת הקצה של OIDC והפרמטרים שמשמשים בתהליך OIDC. |
authentication.oidc.certificateAuthorityData |
זהו אישור הבסיס של ה-SSL של הדומיין של שרת ההרשאות של OIDC או של שרת ה-proxy של HTTPS, אם יש כזה. |
authentication.oidc.oauthCredentialsSecret |
הפניות לסוד מסוג Opaque ב-Kubernetes שמכיל את client_id ואת client_secret של OAuth2 OIDC במטען ייעודי (payload) בפורמט JSON. |
authentication.oidc.issuerURI |
ה-URI שבו יש להשתמש כמנפיק ב-RCToken של הפלט. |
authentication.oidc.proxy |
שרת Proxy ל-IdP שתומך ב-OIDC, אם רלוונטי. בפורמט http://user:password@10.10.10.10:8888. |
authentication.oidc.redirectURIHost |
המארח שישמש ל-URI של סיום OAuth. אם משאירים את השדה הזה ריק, המערכת משתמשת במארח מכתובת ה-URL של היעד ומרכיבה את כתובת ה-URI להפניה אוטומטית באופן דינמי. אפשר להשתמש בערך הזה כשרוצים סשן SSO לאימות משתמשים בדומיין ברמה גבוהה יותר. לדוגמה, כדי להפעיל כניסה יחידה בין profile.example.com/ לבין admin.example.com/, אפשר להגדיר את הערך הזה כ-example.com. כך תופעל סשן אימות משתמש ב-example.com, שישותף בין כל תתי-הדומיין. הערה: אם כמה דומיינים מוגשים מאותה רשת Mesh, למשל example1.com ו-example2.com, אי אפשר להשתמש בתכונה הזו, ועדיף להשאיר אותה ריקה. |
authentication.oidc.redirectURIPath |
נתיב נקודת הקצה שבו authservice יסיים את תהליך OAuth. צריך לרשום את נתיב ה-URI הזה בתוספת המארח כ-URI מורשה להפניה אוטומטית בשרת ההרשאות של authentication.oidc.clientID.בנוסף, ה-URI הזה צריך להיות מוגש מאותו Service mesh ומאותו שער כניסה שבהם מופעל authservice. |
authentication.oidc.scopes |
היקף ההרשאות של OAuth שצריך לבקש בבקשת האימות. רשימה מופרדת בפסיקים של מזהים שמשמשים לציון הרשאות הגישה המבוקשות בנוסף להיקף openid, למשל: "groups,allatclaim". |
authentication.oidc.groupsClaim |
אם idtoken מכיל טענת קבוצות, צריך להשתמש בשדה הזה כדי לציין את השם שלה. אם מציינים את השירות, הוא מעביר את הנתונים בהצהרה הזו להצהרה groups ב-RCToken של הפלט. התביעה הזו צריכה להכיל רשימה מופרדת בפסיקים של מחרוזות, למשל: ["group1", "group2"]. |
authentication.oidc.attributeMapping |
מכיל מיפוי אחד או יותר של טענות מ-idtoken ואחריו ביטויי CEL. כל הטענות צריכות להיות מופנות אל assertion.X, assertion מופנה אל אסימון המזהה המקורי, לדוגמה aud_copy: assertion.aud |
authentication.outputJWTAudience |
הקהל שאמור להשתמש ב-RCToken שנוצר על ידי authservice. קובצי ה-sidecar יכולים לאמת את ה-RCToken הנכנס מול ערך הקהל הזה. |
פתרון בעיות
הגישה לרשת לספק הזהויות.
יומן אפשרי:
error: TLS handshake failed..כדי לאמת, מריצים את הפקודה
curlמהקונטיינר הזמני שמצורף ל-istio-proxyכדי לקרוא ל-URI של מנפיק IDP. לדוגמה, ראו איסוף יומנים של Cloud Service Mesh.אם אתם לא מצליחים להתחבר, כדאי לבדוק את כללי חומת האש או הגדרות רשת אחרות של האשכול.
אישור CA בסיסי.
יומן אפשרי:
error: The server's TLS certificate did not match expectations.אוerror: TLS handshake failed..מוודאים שב-
certificateAuthorityDataמופיע אישור ה-CA הבסיסי הנכון. אם אין שרת proxy של HTTPS שמסיים תנועת HTTPS, השדה הזה צריך להכיל את אישור ה-CA הבסיסי של ספק הזהויות. אם יש כזה, הוא צריך להכיל את כתובת ה-proxy.הגדרת נתיב ההפניה האוטומטית.
תצפית אפשרית: מתקבל דף שגיאה 404 במהלך תהליך האימות של OIDC.
האימות של המשתמש מחזיר את הכותרת Set-Cookie בלי להשתמש במאפיין path. כברירת מחדל, הדפדפן משתמש בספרייה של כתובת ה-URL של הבקשה כנתיב של קובץ ה-Cookie (ההיקף של קובץ ה-Cookie שקשור לנתיב). לכן מומלץ לא לכלול את התו '/' בנתיב ההפניה, אלא אם זו הכוונה.
קובץ העזר לא יכול לאחזר את jwksUri.
בתרחישים מסוימים, הגבלה של sidecar עלולה לגרום לכשל באחזור של jwksUri. אם מרחב השמות לא מופיע כשמשתמשים בתו כללי לחיפוש (לדוגמה,
./*אוistio-system/*), הפעולה לא תצליח. צריך להוסיף את מרחב השמות שלהם באופן ידני ב-sidecar של היציאה.
שאלות נפוצות
איך משדרגים את Cloud Service Mesh עם אימות משתמשים מופעל?
פועלים לפי תהליך השדרוג של Cloud Service Mesh ומציינים את קובץ השכבה העליונה על ידי הוספת
--custom_overlay user-auth-overlay.yamlבשורת הפקודה אלasmcli install.כמה משאבים צריך להקצות ל-
authservice? וכמה בקשות לשנייה הוא יכול לטפל?כברירת מחדל,
authserviceמוגדר עם 2.0 vCPU וזיכרון של 256Mi. בהגדרה כזו,authserviceיכול לטפל ב-500 בקשות לשנייה. כדי לטפל בכמות גדולה יותר של בקשות, צריך להקצות יותר CPU, באופן שפרופורציונלי בערך לקיבולת הטיפול בבקשות. אפשר גם להגדיר כמה רפליקות של authservice כדי להגדיל את יכולת ההרחבה האופקית.