הגדרת אימות משתמשים ב-Cloud Service Mesh
אם יש לכם TRAFFIC_DIRECTOR
הטמעה של מישור הבקרה, התכונה הזו נתמכת רק על ידי רשימת היתרים. כדי להוסיף את התכונה הזו לרשימת ההיתרים בארגון שלכם, צריך לפנות לתמיכה.
אימות משתמשים ב-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 ב-ingress. המודל הזה מספק בקרת גישה היקפית לתנועה ברשת. אם המשתמש מורשה לגשת למשאב, ה-RCToken מועבר גם למיקרו-שירותים כדי לקבל מידע על הגורם המורשה ולאכוף בקרת גישה ברמת דיוק גבוהה.
בתרשים הבא מוצג המיקום של authservice ברשת ואיך הוא קשור לחלקים אחרים ברשת, כמו תעבורת נתונים נכנסת (ingress), עומסי העבודה, הדפדפן של המשתמש וכל IdP קיים.
אדמינים יכולים להתקין את authservice כתוסף על התקנה של Cloud Service Mesh. אחרי ההתקנה, authservice קורא את ההגדרות של נקודת הקצה של OIDC ואת ההגדרות המשויכות האחרות שמוגדרות במשאב המותאם אישית UserAuth. האדמין יכול להשתמש בממשקי API של Cloud Service Mesh ExternalAuthorization כדי להגדיר את auth_server כמסנן ב-Ingress.
התקנה של שירות אימות המשתמש
בשלבים הבאים מוסבר איך להגדיר את authservice.
דרישות מוקדמות
פועלים לפי השלבים במאמר התקנת כלים תלויי-הקשר ואימות האשכול כדי:- אם אתם משתמשים ב-Cloud Service Mesh מנוהל באשכול פרטי, אתם צריכים לוודא שהאשכול יכול לשלוח תעבורת נתונים יוצאת (egress) לספק הזהויות.
בנוסף, צריך לוודא שאתם עומדים בדרישות המוקדמות באמצעות השלבים הבאים.
התאמה אישית של שכבת-העל לאימות משתמשים בהתקנה
כדי להתקין את שירות אימות המשתמשים, צריך להתאים אישית את ההתקנה של 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כדי להפנות אל ספק ההרשאות החיצוני שצוין על ידיAuthorizationPolicy.pkg/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.
עוברים אל יצירת פרטי כניסה ובוחרים באפשרות מזהה לקוח OAuth. אם נדרש, מגדירים את האפשרויות של מסך ההסכמה ל-OAuth, ואז מגדירים את האפשרויות הבאות:
- מגדירים את Application type (סוג האפליקציה) ל-Web application (אפליקציית אינטרנט).
- מגדירים את כתובת ה-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. היא גם מגדירה את הכניסה כדי ליירט את כל הבקשות.
מורידים את חבילת 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שער ה-Ingress ביציאה 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 ב-Ingress כדי לוודא שמתבצעת בדיקת הרשאות לכל משתמש מאומת:
kubectl apply -f ./samples/httpbin-authz.yaml -n asm-user-authהקובץ
httpbin-authz.yamlמגדיר את שער הכניסה (ingress) לאימות של טוקן 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. המפתח הציבורי מועבר אל ה-sidecars על ידי istiod לצורך אימות JWT. חשוב מאוד שקובצי ה-sidecar יקבלו את המפתח הציבורי החדש לפני ש-authservice יתחיל להשתמש במפתח הפרטי החדש כדי לחתום על RCToken. לכן, authservice מתחיל לפרסם את המפתח הציבורי מיד אחרי שהמפתח נוסף, אבל מחכה פרק זמן משמעותי לפני שהוא מתחיל להשתמש בו כדי לחתום על RCToken.
לסיכום, כשמבצעים רוטציות של מפתחות, מומלץ:
- מבצעים רוטציות מפתחות באופן קבוע או לפי דרישה, בהתאם לצורך.
- בפורמט JSON, צריך לכלול גם את המפתחות הנוכחיים וגם את המפתחות החדשים. המפתחות החדשים צריכים להיות משויכים לחותמת זמן עתידית. מומלץ לציין חותמת זמן לפחות כמה שעות לפני השעה הנוכחית.
- עוקבים אחרי השירותים ומוודאים שהם עדיין תקינים אחרי שהמפתח החדש נמצא בשימוש. צריך להמתין לפחות יום אחד אחרי השימוש במפתח החדש לפני שעוברים לשלב הבא.
- מסירים את המפתחות הישנים מהערכים ב-JSON. הם כבר לא נחוצים.
Multi Cluster Deployment
אימות משתמשים ב-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 כדי להגדיר מיפויים מאסימון המזהה של ספק הזהויות המקורי. המפתח יהיה שם הטענה ב-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 |
הפניות לסוד מסוג Kubernetes Opaque שמכיל 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. אם לא תזינו ערך, המערכת תשתמש במארח מכתובת היעד, ותבנה את כתובת ה-URI להפניה אוטומטית באופן דינמי. אפשר להשתמש בערך הזה כשרוצים סשן SSO לאימות משתמש בדומיין ברמה גבוהה יותר. לדוגמה, כדי להפעיל כניסה יחידה בין profile.example.com/ לבין admin.example.com/, אפשר להגדיר את הערך הזה כ-example.com. כך תופעל סשן אימות משתמש ב-example.com, שישותף בין כל תתי-הדומיין. הערה: אם כמה דומיינים מוגשים מאותה רשת, למשל example1.com ו-example2.com, אי אפשר להשתמש בתכונה הזו, ועדיף להשאיר את השדה הזה ריק. |
authentication.oidc.redirectURIPath |
נתיב נקודת הקצה שבו authservice יסיים את תהליך OAuth. צריך לרשום את נתיב ה-URI הזה בתוספת המארח כ-URI מורשה להפניה אוטומטית בשרת ההרשאות של authentication.oidc.clientID.בנוסף, ה-URI הזה צריך להיות מוגש מאותה Service mesh ומאותו Ingress שבהם מופעל authservice. |
authentication.oidc.scopes |
היקף ההרשאות של OAuth שצריך לבקש בבקשת האימות. רשימה של מזהים מופרדים בפסיקים שמשמשים לציון אילו הרשאות גישה נדרשות בנוסף להיקף openid, למשל: "groups,allatclaim". |
authentication.oidc.groupsClaim |
אם idtoken מכיל טענה לגבי קבוצות, משתמשים בשדה הזה כדי לציין את השם שלה. אם מציינים את הנתונים האלה, השירות יעביר את הנתונים בטענה הזו לטענה groups ב-RCToken של הפלט. התביעה הזו צריכה להכיל רשימה מופרדת בפסיקים של מחרוזות, למשל: ["group1", "group2"]. |
authentication.oidc.attributeMapping |
מכיל מיפוי אחד או יותר של טענות מ-idtoken ואחריו ביטויי CEL. כל הטענות
צריכות להיות מופנות אל assertion.X, assertion מופנה אל
ה-IDToken המקורי, לדוגמה aud_copy: assertion.aud |
authentication.outputJWTAudience |
הקהל שאמור להשתמש ב-RCToken שנוצר על ידי authservice. ה-sidecars יכולים לאמת את ה-RCToken הנכנס מול ערך הקהל הזה. |
פתרון בעיות
נגישות רשת ל-IdP.
יומן אפשרי:
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 כדי להגדיל את יכולת ההרחבה האופקית.