הגדרת אימות משתמשים ב-Cloud Service Mesh

אם יש לכם TRAFFIC_DIRECTOR הטמעה של מישור הבקרה, התכונה הזו נתמכת רק על ידי רשימת היתרים. כדי לבקש גישה, צריך לפנות לתמיכה.

אימות משתמשים ב-Cloud Service Mesh הוא פתרון משולב לאימות משתמשי קצה מבוסס-דפדפן ולבקרת גישה לעומסי העבודה שפרסתם. הוא מאפשר לכם לבצע אינטגרציה עם ספקי זהויות (IDP) קיימים לצורך אימות משתמשים, ומשתמש בממשקי API ובמדיניות הרשאות של Istio לניהול גישה. זוהי חלופה ידידותית למשתמש לאימות של JSON Web Token ‏ (JWT) ב-Istio.

תרחיש שימוש טיפוסי הוא כאשר ארגון משתמש ב-Cloud Service Mesh כדי לארח אפליקציית אינטרנט עבור כוח העבודה שלו כדי לגשת אליה דרך דפדפן אינטרנט. בנוסף, הארגון צריך להשתמש בספק הזהויות הקיים שלו כדי לנהל את זהויות המשתמשים. אימות משתמש של Cloud Service Mesh מאפשר למשתמשים לבצע אימות בקלות באמצעות זרימת התחברות והסכמה סטנדרטית מבוססת אינטרנט של OpenID Connect (OIDC). כשהמשתמש מבצע אימות, Cloud Service Mesh אוכף את מדיניות ההרשאות של Istio, ואם ההרשאה מצליחה, הוא מעביר את הזהות לעומסי העבודה בפורמט מאובטח של פרטי כניסה.

איך זה עובד

אימות משתמשים ב-Cloud Service Mesh כולל רכיב חדש, authservice. רכיב זה משתלב עם ה-ingress מבוסס Envoy כשירות הרשאה חיצוני שמיירט את כל בקשות האימות הנכנסות. authservice מיישם את צד הלקוח של פרוטוקול OIDC ומאפשר למשתמשים גישת אפליקציות דרך דפדפן, שבו משתמשים משלימים תהליך אימות והסכמה אינטראקטיבי כדי ליצור סשן קצר מועד. authservice מיישם פרוטוקולים סטנדרטיים בתעשייה כדי להשתלב עם כל ספק זהויות שיכול לשמש כשרת הרשאות OIDC. כאשר המשתמש מאומת, המידע העיקרי מוקפץ בקובץ RCToken בפורמט JWT, חתום על ידי authservice, אותו מעביר לשכבת ההרשאה של Istio ב-ingress. המודל הזה מספק בקרת גישה היקפית לתנועה ברשת. אם למשתמש יש אישור גישה למשאב, 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 בתוך האשכול.

מנוהל

  1. מעדכנים את ConfigMap כך שיכלול את MeshConfig של אימות המשתמש. בפקודה הבאה, צריך להשתמש באותו REVISION_LABEL שבו השתמשתם כשהקציתם משאבים ל-Cloud Service Mesh מנוהל (למשל, asm-managed, asm-managed-rapid או asm-managed-stable):

    kubectl edit configmap istio-REVISION_LABEL -n istio-system
    
  2. הוסף את הטקסט הבא תחת השדה mesh ב-MeshConfig:

    mesh: |-
    ...
      extensionProviders:
      - name: "asm-userauth-grpc"
        envoyExtAuthzGrpc:
          service: "authservice.asm-user-auth.svc.cluster.local"
          port: "10003"
    
  3. יוצרים מרחב שמות asm-user-auth.

    kubectl create namespace asm-user-auth
    
  4. מפעילים את מרחב השמות להחדרה. השלבים תלויים בהטמעה של מישור הבקרה.

    מנוהל (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: מומלץ להשתמש בהזרקה של ברירת המחדל, אבל נתמכת גם הזרקה מבוססת-עדכון. פועלים לפי ההוראות הבאות:

    1. מריצים את הפקודה הבאה כדי לאתר את ערוצי ההפצה הזמינים:
    kubectl -n istio-system get controlplanerevision
    

    הפלט אמור להיראות כך:

    NAME                AGE
    asm-managed-rapid   6d7h
    

    בפלט, הערך בעמודה NAME הוא תווית הגרסה שתואמת לערוץ ההפצה שזמין לגרסה של Cloud Service Mesh.

    1. החלת תווית הגרסה על מרחב השמות:

      kubectl label namespace asm-user-auth \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  5. מתקינים את שער Istio במרחב השמות asm-user-auth.

    kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
    

באשכול

  1. אפשר לקבל את הדוגמה של שכבת-על לאימות משתמשים ולעדכן אותה אם יש התאמות אישיות ברשת שלכם. מומלץ לשמור את קובץ ה-overlay הזה בבקרת המקור שלך.

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/asm-user-auth/v1.2.3/overlay/user-auth-overlay.yaml > user-auth-overlay.yaml
    
  2. כדי להתקין את 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.

  3. יוצרים מרחב שמות asm-user-auth.

    kubectl create namespace asm-user-auth
    
  4. מפעילים את מרחב השמות להחדרה.

    מומלץ: מריצים את הפקודה הבאה כדי להחיל את תווית ברירת המחדל של הזרקה על מרחב השמות:

      kubectl label namespace asm-user-auth \
          istio.io/rev- istio-injection=enabled --overwrite
    

    מומלץ להשתמש בהחדרה שמוגדרת כברירת מחדל, אבל יש תמיכה גם בהחדרה שמבוססת על עדכון: פועלים לפי ההוראות הבאות:

    1. משתמשים בפקודה הבאה כדי לאתר את תווית הגרסה ב-istiod:

      kubectl get deploy -n istio-system -l app=istiod -o \
        jsonpath={.items[*].metadata.labels.'istio\.io\/rev'}'{"\n"}'
      
    2. מחילים את תווית הגרסה על מרחב השמות. בפקודה הבאה, REVISION_LABEL הוא הערך של התווית istiod revision שרשמתם בשלב הקודם.

      kubectl label namespace asm-user-auth \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  5. מתקינים את שער Istio במרחב השמות asm-user-auth.

    kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
    

הכן את תצורת לקוח ה-OIDC

כדי להגדיר את לקוח ה-OIDC: מדריך זה משתמש בגוגל כ-IDP, אך ניתן להשתמש בכל IDP התומך באימות OIDC.

  1. במסוף Google Cloud , עוברים אל API & Services > Credentials.

    כניסה לדף Credentials

  2. עבור אל צור אישורים, לאחר מכן בחר מזהה לקוח OAuth. במידת הצורך, הגדר את אפשרויות מסך ההסכמה של OAuth ולאחר מכן קבע את האפשרויות הבאות:

    • הגדר את סוג האפליקציה ל-אפליקציית אינטרנט.
    • הגדר את URI להפניה מחדש מורשית ל-https://REDIRECT_HOST/REDIRECT_PATH. לדוגמה, בשביל localhost אפשר להגדיר את הערך https://localhost:8443/_gcp_asm_authenticate.

    לאחר מכן, לוחצים על שמירה.

  3. בנוסף, שמור את תצורת לקוח ה-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.3 .
cd asm-user-auth/

הגדר את כתובת ה-URL לניתוב מחדש ואת הסוד עבור שער הכניסה

OAuth2 דורש כתובת URL להפניה אוטומטית שמתארחת בנקודת קצה שמוגנת באמצעות HTTPS. הפקודות האלה הן דוגמאות שמפשטות את ההגדרה על ידי יצירת אישור בחתימה עצמית לשער הכניסה של Istio.

  1. יצירת אישור בחתימה עצמית:

    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
     -days 365 -nodes -subj '/CN=localhost'
    
  2. יוצרים סוד לשער Ingress כדי לארח תנועת HTTPS:

    kubectl create -n asm-user-auth secret tls userauth-tls-cert --key=key.pem \
    --cert=cert.pem
    

החלת מפתחות ההצפנה והחתימה

כדי שהמערכת תפעל בצורה תקינה, צריך שני סטים של מפתחות.authservice הראשון הוא מפתח סימטרי להצפנה ולפענוח. מפתח זה משמש להצפנת מצב ההפעלה לפני הגדרתו כעוגייה.

קבוצת המפתחות השנייה היא זוג מפתחות ציבורי/פרטי. מפתח זה משמש לחתימה על פרטי המשתמש המאומתים בפורמט JWT כ-RCToken. המפתח הציבורי מהזוג הזה מתפרסם בנקודת קצה מוגדרת מראש, שקובצי ה-sidecar יכולים להשתמש בה כדי לאמת את ה-JWT.

חבילת kpt לאימות משתמשים מכילה שני מפתחות לדוגמה להגדרה מהירה. עם זאת, באפשרותך להשתמש במערכת ניהול המפתחות המועדפת עליך כדי ליצור מפתחות אלה במקום זאת.

  1. מכינים את מפתח ההצפנה של הסשן בפורמט הבא או משתמשים בדוגמה מתוך חבילת ה-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
    
  2. הכינו את מפתח החתימה של RCToken בפורמט הבא או השתמשו בדוגמה מהחבילה, אותה תוכלו לצפות עד 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 לצרכי בדיקה באורך 256 ביט באמצעות הפקודה הבאה:

    openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:256
    
  3. יוצרים את הסוד של 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.

ביצוע משימות לאחר ההתקנה

אחרי שמסיימים את שלבי ההתקנה הקודמים, צריך לבצע את המשימות הבאות.

הפעל אימות משתמשים עבור היישומים שלך

בקטע הזה מוסבר איך להפעיל אימות משתמשים, באמצעות 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
  1. מרחב השמות של התווית default כדי להפעיל הוספה אוטומטית של istio-proxy לפריסות.

    kubectl label namespace default istio.io/rev=REVISION --overwrite
    
  2. פורסים את httpbin למרחב השמות default.

    kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml -n default
    
  3. עדכן את httpbin כדי להשתמש בשער זה כדי לשרת תעבורת HTTPS, ולהשתמש בהעברת פורטים כדי לגשת לאפליקציה באופן מקומי:

    kubectl apply -f./samples/httpbin-route.yaml -n default
    kubectl port-forward service/istio-ingressgateway 8443:443 -n asm-user-auth
    
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
      namespace: default
    spec:
      gateways:
      - asm-user-auth/userauth
      hosts:
      - '*'
      http:
      - match:
        - uri:
            prefix: /ip
        - uri:
            prefix: /headers
        name: httpbin-routes
        route:
        - destination:
            host: httpbin.default.svc.cluster.local
            port:
              number: 8000
    

    שער הכניסה ביציאה 8443 יועבר אל localhost כדי לאפשר גישה לאפליקציה באופן מקומי.

  4. פורסים את 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 מחייב את משתמש הקצה להתחבר דרך ספק הזהויות שהוגדר.

  1. ודא שאתה יכול לגשת ישירות ל-/ip על ידי ביקור ב-https://localhost:8443/ip.

  2. כדי לוודא שדף הכניסה של OIDC מוצג, נכנסים לכתובת https://localhost:8443/headers.

  3. לאחר הכניסה, לחץ על הבא וודא שהפעולה מפנה אותך לדף /headers.

הגדרת מדיניות הרשאות

לאחר שתסיים את התצורה בשלבים הקודמים, כל משתמש ינותב דרך זרימת אימות מבוססת אינטרנט. כאשר הזרימה תושלם, ה-authservice ייצור RCToken בפורמט JWT, שישמש להעברת פרטי המשתמש המאומתים.

  1. מוסיפים מדיניות הרשאות של Istio בנקודת הכניסה כדי לוודא שמתבצעת בדיקת הרשאות לכל משתמש מאומת:

    kubectl apply -f ./samples/httpbin-authz.yaml -n asm-user-auth
    
  2. הקובץ 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 מהימן עם אישורי הבסיס של המערכת, אפשר להשאיר את השדה הזה ריק. אם ישנו פרוקסי HTTPS שמסיים את חיבור ה-HTTPS, יש להגדיר אותו לאישור הבסיס של הפרוקסי.

ניהול מפתחות וביצוע רוטציה שלהם

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 משתמשת במפתח סימטרי להצפנת נתוני סשן המאוחסנים בעוגיות של הדפדפן. כדי להבטיח את תוקפן של פעילויות קיימות, authservice מנסה לפענח באמצעות כל המפתחות בקבוצת המפתחות. במהלך הסיבוב, authservice ישתמש במפתח החדש להצפנת סשנים חדשים, וימשיך לנסות לפענח באמצעות המפתחות הישנים.

זוג המפתחות הציבורי/פרטי משמש לחתימה על RCToken. המפתח הציבורי מועבר אל sidecars על ידי istiod לצורך אימות JWT. חשוב מאוד שקובצי ה-sidecar יקבלו את המפתח הציבורי החדש לפני ש-authservice יתחיל להשתמש במפתח הפרטי החדש כדי לחתום על RCToken. לשם כך, authservice מתחיל לפרסם את המפתח הציבורי מיד לאחר הוספת המפתח, אך ממתין זמן רב לפני שיתחיל להשתמש בו כדי לחתום על RCToken.

לסיכום, כשמבצעים רוטציה של מפתחות, מומלץ:

  1. מבצעים רוטציות של מפתחות באופן קבוע או לפי דרישה, בהתאם לצורך.
  2. בפורמט JSON, יש לכלול גם את המפתח הנוכחי וגם את המפתח החדש. המפתחות החדשים צריכים להיות משויכים לחותמת זמן עתידית. מומלץ לציין חותמת זמן לפחות כמה שעות לפני השעה הנוכחית.
  3. עוקבים אחרי השירותים ומוודאים שהם עדיין תקינים אחרי שהמפתח החדש נמצא בשימוש. צריך להמתין לפחות יום אחד אחרי שמתחילים להשתמש במפתח החדש לפני שעוברים לשלב הבא.
  4. מסירים את המפתחות הישנים מהערכים ב-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 ייכשל, הטענה תתעלם מהערך בלי לגרום לכשל בתהליך האימות.

שדרוגים של אימות משתמשים

  1. התקן שוב את חבילות user-auth מכיוון שהן מכילות את הקובץ הבינארי המעודכן עבור גרסת user-auth החדשה:

    kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.3 .
    cd asm-user-auth/
    
  2. שמור את תצורת לקוח ה-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
    
  3. לפרוס את שירות אימות המשתמשים כדי לשדרג לגרסה חדשה.

פרטים על הגדרת אימות משתמשים

בטבלה הבאה מתואר כל שדה ב-CRD:

שם השדה תיאור
authentication.oidc בקטע הזה מופיעה ההגדרה של נקודת הקצה של OIDC והפרמטרים שמשמשים בתהליך OIDC.
authentication.oidc.certificateAuthorityData זהו אישור הבסיס של ה-SSL של הדומיין של שרת ההרשאות של OIDC או של שרת ה-proxy של HTTPS, אם יש כזה.
authentication.oidc.oauthCredentialsSecret הפניות סודיות לסוד מסוג Kubernetes Opaque המכיל את ה-OAuth2 OIDC client_id ו-client_secret במטען 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 זה מאותה רשת שירות וכניסה שבהם authservice מופעל.
authentication.oidc.scopes היקף ההרשאות של OAuth שצריך לבקש בבקשת האימות. רשימה של מזהים מופרדים בפסיקים שמשמשים לציון הרשאות הגישה המבוקשות בנוסף להיקף openid, למשל: קבוצות,כל תביעה.
authentication.oidc.groupsClaim אם ה-idtoken מכיל תביעת קבוצה, השתמש בשדה זה כדי לציין את שמה. אם מציינים את השדה הזה, השירות יעביר את הנתונים בטענה הזו אל הטענה groups ב-RCToken של הפלט. טענה זו צריכה להכיל רשימה מופרדת בפסיקים של מחרוזות, לדוגמה. ‪['group1', 'group2'].
authentication.oidc.attributeMapping מכיל מיפוי תביעה אחד או יותר מביטויי CEL שעוקבים אחריהם idtoken. כל התביעות צריכות להיות מופנות על ידי assertion.X, assertion מופנה ל-IDToken המקורי, לדוגמה aud_copy: assertion.aud.
authentication.outputJWTAudience הקהל שאמור להשתמש ב-RCToken שנוצר על ידי authservice. ה-sidecars יכולים לאמת את ה-RCToken הנכנס מול הערך הזה של קהל היעד.

פתרון בעיות

  1. הגישה של ספק הזהויות לרשת.

    יומן אפשרי: error: TLS handshake failed..

    כדי לאמת, מריצים את הפקודה curl מהקונטיינר האפמרי שמצורף ל-istio-proxy כדי לקרוא ל-URI של מנפיק IDP. לדוגמה, ראו איסוף יומנים של Cloud Service Mesh.

    אם אתם לא מצליחים להתחבר, כדאי לבדוק את כללי חומת האש או הגדרות רשת אחרות של האשכול.

  2. אישור CA בסיס.

    יומן אפשרי: error: The server's TLS certificate did not match expectations. או error: TLS handshake failed..

    מוודאים שבתיבת הטקסט certificateAuthorityData מופיע אישור ה-CA הבסיסי הנכון. אם אין שרת proxy של HTTPS שמסיים את תנועת ה-HTTPS, צריך להזין כאן את אישור ה-CA הבסיסי של ספק הזהויות. אם יש כזה, זה אמור להכיל את הפרוקסי במקום זאת.

  3. הגדרת נתיב ההפניה האוטומטית.

    תצפית אפשרית: מתקבל דף שגיאה 404 במהלך תהליך אימות OIDC.

    פונקציית User Auth מחזירה את כותרת ה-"Set-Cookie" מבלי להשתמש בתכונה path, אשר כברירת מחדל הדפדפן משתמש בספרייה של כתובת ה-URL של הבקשה כנתיב קובץ ה-cookie (היקף קובץ ה-cookie הקשור ל-path). לכן אנו ממליצים לא לכלול "/" בנתיב ההפניה אלא אם כן הכוונה היא לכך.

  4. קובץ העזר לא יכול לאחזר את jwksUri.

    בתרחישים מסוימים, הגבלה של sidecar עלולה לגרום לכשל באחזור של jwksUri. אם מרחב השמות אינו קיים באמצעות תו כללי (לדוגמה, ./* או istio-system/*), פעולה זו לא תעבוד. צריך להוסיף באופן ידני את מרחב השמות שלהם ב-sidecar של היציאה.

שאלות נפוצות

  1. איך משדרגים את Cloud Service Mesh עם אימות משתמשים מופעל?

    פועלים לפי תהליך השדרוג של Cloud Service Mesh ומציינים את קובץ השכבה העליונה על ידי הוספת --custom_overlay user-auth-overlay.yaml בשורת הפקודה אל asmcli install.

  2. כמה משאבים צריך להקצות ל-authservice? וכמה בקשות לשנייה הוא יכול לטפל?

    כברירת מחדל, authservice מוגדר עם 2.0 vCPU ו-256Mi זיכרון. בהגדרה כזו, authservice יכול לטפל ב-500 בקשות לשנייה. כדי לטפל בכמויות גדולות יותר של בקשות, צריך להקצות יותר CPU, באופן שפרופורציונלי בערך לקיבולת הטיפול בבקשות. אפשר גם להגדיר כמה רפליקות של authservice כדי להגדיל את יכולת ההרחבה האופקית.