Cloud Service Mesh by example: Authorization

במדריך הזה תלמדו מהי הרשאה ואיך להפעיל אותה באמצעות Cloud Service Mesh באפליקציה לדוגמה, כדי להבין איך להפעיל מדיניות הרשאות במיקרו-שירותים. תצטרכו ליצור AuthorizationPolicy כדי DENY לגשת למיקרו-שירות, ואז ליצור AuthorizationPolicy כדי ALLOW גישה ספציפית למיקרו-שירות.

מהו אישור?

אימות מאמת זהות – האם השירות הזה הוא מי שהוא אומר שהוא? ההרשאה מאמתת את ההרשאה – האם השירות הזה מורשה לבצע את הפעולה הזו? הזהות היא מרכיב בסיסי ברעיון הזה. עם Cloud Service Mesh,‏ AuthorizationPolicies מאפשרים לשלוט בתקשורת בין עומסי העבודה ברשת כדי לשפר את האבטחה והגישה.

בארכיטקטורת מיקרו-שירותים, שבה מתבצעות קריאות מעבר לגבולות הרשת, כללי חומת אש מבוססי-IP לרוב לא מספיקים כדי לאבטח את הגישה בין עומסי עבודה. בעזרת Cloud Service Mesh, אתם יכולים להגדיר כללי הרשאה כדי:

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

הסבר מפורט על הגדרת מדיניות ושיטות מומלצות זמין במאמר הרשאות ב-Cloud Service Mesh.

עלויות

במדריך הזה השתמשנו ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

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

לפני שמתחילים

פריסת שער כניסה

  1. מגדירים את ההקשר הנוכחי של kubectl לאשכול:

    gcloud container clusters get-credentials CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  2. יוצרים מרחב שמות לשער הכניסה:

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

    מנוהל (TD)

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

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

    מנוהל (Istiod)

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

      kubectl label namespace asm-ingress \
          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.

    2. מחילים את תווית הגרסה על מרחב השמות:

      kubectl label namespace asm-ingress \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      

    בתוך האשכול

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

      kubectl label namespace asm-ingress \
          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-ingress \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  4. פורסים את השער לדוגמה במאגר anthos-service-mesh-samples:

    kubectl apply -n asm-ingress \
    -f docs/shared/asm-ingress-gateway
    

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

    serviceaccount/asm-ingressgateway configured
    service/asm-ingressgateway configured
    deployment.apps/asm-ingressgateway configured
    gateway.networking.istio.io/asm-ingressgateway configured
    

פריסה של אפליקציית Online Boutique לדוגמה

  1. אם לא עשיתם זאת, מגדירים את ההקשר הנוכחי של kubectl לאשכול:

    gcloud container clusters get-credentials CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  2. יוצרים את מרחב השמות לאפליקציה לדוגמה:

    kubectl create namespace onlineboutique
    
  3. מתייגים את מרחב השמות onlineboutique כדי להחדיר אוטומטית שרתי proxy של Envoy. פועלים לפי השלבים להפעלת הוספה אוטומטית של קובץ sidecar.

  4. פורסים את האפליקציה לדוגמה, את VirtualService לקצה הקדמי ואת חשבונות השירות לעומסי העבודה. במדריך הזה תפרסו את Online Boutique, אפליקציית הדגמה של מיקרו-שירות.

    kubectl apply \
    -n onlineboutique \
    -f docs/shared/online-boutique/virtual-service.yaml
    kubectl apply \
    -n onlineboutique \
    -f docs/shared/online-boutique/service-accounts
    

צפייה בשירותים

  1. מציגים את ה-pods במרחב השמות onlineboutique:

    kubectl get pods -n onlineboutique
    

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

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    כל הפודים של האפליקציה צריכים לפעול, ובעמודה READY צריך להופיע 2/2. המשמעות היא שה-pods קיבלו בהצלחה הזרקה של Envoy sidecar proxy. אם הסמל 2/2 לא מופיע אחרי כמה דקות, אפשר להיעזר במדריך לפתרון בעיות.

  2. מקבלים את כתובת ה-IP החיצונית ומגדירים אותה כמשתנה:

    kubectl get services -n asm-ingress
    export FRONTEND_IP=$(kubectl --namespace asm-ingress \
    get service --output jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}' \
    )
    

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

    NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
    asm-ingressgateway   LoadBalancer   10.19.247.233   35.239.7.64   80:31380/TCP,443:31390/TCP,31400:31400/TCP   27m
    
    
  3. נכנסים לכתובת EXTERNAL-IP בדפדפן האינטרנט. החנות Online Boutique אמורה להופיע בדפדפן.

    ממשק המשתמש של חנות בוטיק אונליין

דחיית הרשאה (DenyAll) לעומס עבודה

בקטע הזה נוסף AuthorizationPolicy כדי לדחות את כל התנועה הנכנסת לשירות המטבע. AuthorizationPolicies פועל על ידי המרה של AuthorizationPolicies להגדרות שניתן לקרוא ב-Envoy, והחלת ההגדרות על פרוקסי מסוג sidecar. כך אפשר להשתמש ב-Envoy proxy כדי לאשר או לדחות בקשות נכנסות לשירות.

  1. החלת AuthorizationPolicy על currencyservice. שימו לב להתאמה לתווית currencyservice בקובץ ה-YAML.

    kubectl apply -f docs/authorization/currency-deny-all.yaml -n onlineboutique
    
    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: currency-policy
    spec:
      selector:
        matchLabels:
          app: currencyservice
  2. נסו לגשת ל-EXTERNAL-IP של השער כדי לראות את Online Boutique בדפדפן האינטרנט. צריכה להופיע שגיאת הרשאה (500 שגיאת שירות פנימית) מ-currency service.

    שגיאת authz rbac 500

עיון ביומנים של שרת ה-proxy מסוג sidecar

כדי לראות מה קורה ב-קובץ עזר חיצוני, אפשר לבדוק את היומנים ב-Pod.

  1. מקבלים את השם של ה-pod של currencyservice:

    CURRENCY_POD=$(kubectl get pod -n onlineboutique |grep currency|awk '{print $1}')
    
  2. מגדירים את שרת ה-proxy של Envoy כך שיאפשר יומנים ברמת המעקב. כברירת מחדל, שיחות הרשאה חסומות לא נרשמות ביומן:

    kubectl debug --image istio/base --target istio-proxy -it $CURRENCY_POD -n onlineboutique -- curl -X POST "http://localhost:15000/logging?level=trace"
    

    הפלט הצפוי: none {:.devsite-disable-click-to-copy} active loggers: admin: trace alternate_protocols_cache: trace ... tracing: trace upstream: trace udp: trace wasm: trace

  3. משתמשים ב-curl כדי לשלוח תנועה אל EXTERNAL_IP כדי ליצור יומנים:

    for i in {0..10}; do
    curl -s -I $FRONTEND_IP ; done
    
  4. צפייה ביומנים שקשורים לבקרת גישה מבוססת-תפקידים (RBAC) ב-istio-proxy:

    kubectl logs -n onlineboutique $CURRENCY_POD -c istio-proxy | grep -m5 rbac
    

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

    2022-07-08T14:19:20.442920Z     debug   envoy rbac      checking request: requestedServerName: outbound_.7000_._.currencyservice.onlineboutique.svc.cluster.local, sourceIP: 10.8.8.5:34080, directRemoteIP: 10.8.8.5:34080, remoteIP: 10.8.8.5:34080,localAddress: 10.8.0.6:7000, ssl: uriSanPeerCertificate: spiffe://christineskim-tf-asm.svc.id.goog/ns/onlineboutique/sa/default, dnsSanPeerCertificate: , subjectPeerCertificate: OU=istio_v1_cloud_workload,O=Google LLC,L=Mountain View,ST=California,C=US, headers: ':method', 'POST'
    2022-07-08T14:19:20.442944Z     debug   envoy rbac      enforced denied, matched policy none
    2022-07-08T14:19:20.442965Z     debug   envoy http      [C73987][S13078781800499437460] Sending local reply with details rbac_access_denied_matched_policy[none]
      ```
    

בסוף היומנים אמורה להופיע הודעה enforced denied, שבה מצוין ש-currencyservice מוגדר לחסימת בקשות נכנסות.

מתן גישה מוגבלת

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

בקטע הזה מפעילים את השירותים frontend ו-checkout כדי לאפשר להם לתקשר עם השירות currency.

  1. בקובץ הבא אפשר לראות שללקוח source.principal מסוים יש גישה ל-currencyservice:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: currency-policy
spec:
  selector:
    matchLabels:
      app: currencyservice
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/onlineboutique/sa/frontend"]
  - from:
    - source:
        principals: ["cluster.local/ns/onlineboutique/sa/checkoutservice"]
  1. החלת המדיניות:

    kubectl apply -f docs/authorization/currency-allow-frontend-checkout.yaml -n onlineboutique
    
  2. עכשיו אתם אמורים להיות מסוגלים לגשת ל-Online Boutique.EXTERNAL-IP

הסרת המשאבים

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

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

מחיקת הפרויקט

ב-Cloud Shell, מוחקים את הפרויקט:

gcloud projects delete PROJECT_ID

מחיקת המשאבים

  • אם רוצים לשמור את האשכול ולהסיר את הדוגמה של Online Boutique:

    1. מוחקים את מרחבי השמות של האפליקציה:

      kubectl delete namespace onlineboutique
      

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

      namespace "onlineboutique" deleted
      
    2. מחיקת מרחב השמות של Ingress Gateway:

      kubectl delete namespace asm-ingress
      

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

      amespace "asm-ingress" deleted
      
  • כדי למנוע חיובים נוספים, צריך למחוק את האשכול:

    gcloud container clusters delete  CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    

המאמרים הבאים