סקירה כללית של מדיניות ההרשאות

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

בדף הזה מופיעה סקירה כללית על AuthorizationPolicy (משאב בהתאמה אישית) למפעילי אפליקציות. כללי מדיניות הרשאה מאפשרים לכם להפעיל בקרת גישה על עומסי עבודה בשכבות האפליקציה (L7) והתעבורה (L3/4). מגדירים כללי מדיניות הרשאה כדי לציין הרשאות – מה מותר לשירות או למשתמש לעשות?

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

כברירת מחדל, מותר לשלוח בקשות בין שירותים ברשת (ובין משתמשי קצה לשירותים). משתמשים ב-CR של AuthorizationPolicy כדי להגדיר מדיניות מפורטת לעומסי העבודה. אחרי שמחילים את כללי מדיניות ההרשאה, Cloud Service Mesh מפיץ אותם לקובצי העזר החיצוניים. כשהבקשות מגיעות לעומס עבודה, קובץ העזר החיצוני בודק את מדיניות ההרשאות כדי לקבוע אם לאשר או לדחות את הבקשה.

בקטע תכונות נתמכות מפורט אילו שדות של AuthorizationPolicy CR נתמכים בכל פלטפורמה.

היקף המדיניות

אפשר להחיל מדיניות על כל Service mesh, על מרחב שמות או על עומס עבודה ספציפי.

  • כדי להחיל מדיניות על כל הרשת, מציינים את מרחב השמות הבסיסי, istio-system, בשדה metadata:namespace:

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "mesh-wide"
      namespace: istio-system
    spec:
    ...
    
  • כדי להחיל מדיניות על מרחב שמות, מציינים את מרחב השמות בשדה metadata:namespace:

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "currencyservice"
      namespace: currencyservice
    spec:
    ...
    
  • כדי להגביל מדיניות לעומס עבודה ספציפי, צריך לכלול את השדה selector.

    apiVersion: "security.istio.io/v1beta1"
    kind: "AuthorizationPolicy"
    metadata:
      name: "frontend"
      namespace: demo
    spec:
      selector:
        matchLabels:
          app: frontend
       ...
    

מבנה בסיסי

מדיניות הרשאה כוללת את היקף המדיניות, action ורשימה של rules:

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

  • השדה action מציין אם ALLOW או DENY את הבקשה. אם לא מציינים פעולה, הפעולה שמוגדרת כברירת מחדל היא ALLOW. כדי שהפקודה תהיה ברורה, מומלץ תמיד לציין את הפעולה. (כללי מדיניות ההרשאה תומכים גם בפעולות AUDIT ו-CUSTOM. הפעולה AUDIT נתמכת רק בחלק מהפלטפורמות. לפרטים, ראו תכונות נתמכות.

  • השדות rules מציינים מתי להפעיל את הפעולה.

    • השדה from ב-rules מציין את המקורות של הבקשה.

    • השדה to ב-rules מציין את הפעולות של הבקשה.

    • בשדה when מציינים תנאים נוספים שצריכים להתקיים כדי שהכלל יחול.

בדוגמה הבאה:

  • המדיניות חלה על בקשות לשירות frontend במרחב השמות demo.

  • הבקשות מותרות כשה-request header של הבקשה כולל את "hello:world", אחרת הבקשות נדחות.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "hello-world"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: frontend
  action: ALLOW
  rules:
  - when:
    - key: request.headers[hello]
      values: ["world"]

בקרת גישה לפעולת בקשה

כדי לשלוט בגישה לפעולות ספציפיות של בקשות, כמו שיטות HTTP או יציאות TCP, מוסיפים קטע to מתחת ל-rules. בדוגמה הבאה, רק השיטות GET ו-POST של HTTP מותרות ל-currencyservice במרחב השמות demo.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: currencyservice
 namespace: demo
spec:
 selector:
   matchLabels:
     app: currencyservice
 action: ALLOW
 rules:
 - to:
   - operation:
       methods: ["GET", "POST"]

בקרת גישה לזהות מאומתת

בדוגמאות הקודמות, כללי המדיניות מאפשרים בקשות מעומסי עבודה לא מאומתים. אם הפעלתם את STRICT Mutual TLS (mTLS), אתם יכולים להגביל את הגישה לפי הזהות של עומס העבודה או מרחב השמות שממנו נשלחה הבקשה בקטע source.

  • משתמשים בשדה principals או notPrincipal כדי לשלוט בגישה ברמת עומס העבודה.

  • משתמשים בשדה namespaces או notNamespaces כדי לשלוט בגישה ברמת מרחב השמות.

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

עומס העבודה שזוהה

בדוגמה הבאה, בקשות ל-currencyservice מותרות רק מהשירות frontend. בקשות ל-currencyservice מעומסי עבודה אחרים נדחות.

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "currencyservice"
  namespace: demo
spec:
  selector:
    matchLabels:
      app: currencyservice
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["example-project-1234.svc.id.goog/ns/demo/sa/frontend-sa"]

כדי לציין חשבון שירות, הערך של principals צריך להיות בפורמט הבא:

principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]

אם אתם משתמשים ב-Cloud Service Mesh באשכול עם Citadel CA, אז cluster.local הוא מתחם האמון. בכל שאר המקרים, PROJECT_ID.svc.id.goog הוא מתחם האמון של הרשת.

מתחם אמון (trust domain) תואם ל-Root of Trust (קיצור: RoT) של מערכת, והוא חלק מ-Workload Identity. ב-Cloud Service Mesh, מתחם האמון משמש ליצירת כל הזהויות בתוך רשת. לדוגמה, במזהה SPIFFE spiffe://mytrustdomain.com/ns/default/sa/myname, מחרוזת המשנה mytrustdomain.com מציינת שעומס העבודה הוא ממתחם אמון שנקרא mytrustdomain.com.

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

יכולים להיות לכם כמה מתחמי אמון ברשת עם כמה אשכולות, כל עוד לאשכולות יש את אותו שורש אמון.

מרחב השמות שזוהה

בדוגמה הבאה מוצגת מדיניות שדוחה בקשות אם המקור הוא לא מרחב השמות foo:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["foo"]

התאמת ערכים

רוב השדות במדיניות ההרשאה תומכים בכל סכימות ההתאמה הבאות:

  • התאמה מדויקת: התאמה מדויקת של מחרוזת.
  • התאמה של תו כללי לחיפוש באמצעות התו הכללי לחיפוש "*":
    • התאמת קידומת: מחרוזת שמסתיימת ב-"*". לדוגמה, "test.example.*" תואם ל-"test.example.com" או ל-"test.example.com.cn".
    • התאמת סיומת: מחרוזת שמתחילה ב-"*". לדוגמה, "*.example.com" תואם ל-"eng.example.com" או ל-"test.eng.example.com".
  • התאמה לנוכחות: כדי לציין ששדה חייב להיות קיים ולא ריק, משתמשים בפורמט fieldname: ["*"]. זה שונה מהשארת שדה לא מוגדר, שמשמעותה היא התאמה לכל דבר, כולל שדה ריק.

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

  • השדה key בקטע when
  • האפשרות ipBlocks בקטע source
  • השדה ports בקטע to

מדיניות לדוגמה שמאפשרת גישה לנתיבים עם הקידומת /test/* או הסיומת */info:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: tester
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/test/*", "*/info"]

התאמה להחרגה

כדי להתאים תנאים שליליים כמו notValues בשדה when, notIpBlocks בשדה source ו-notPorts בשדה to, ב-Cloud Service Mesh יש תמיכה בהתאמה להחרגה. בדוגמה הבאה נדרשת בקשה חוקית principals, שנובעת מאימות JWT, אם נתיב הבקשה הוא לא /healthz. לכן, המדיניות מחריגה בקשות לנתיב /healthz מאימות JWT:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: disable-jwt-for-healthz
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        notPaths: ["/healthz"]
    from:
    - source:
        requestPrincipals: ["*"]

דחיית בקשות בטקסט פשוט

ב-Cloud Service Mesh, פרוטוקול mTLS מופעל אוטומטית כברירת מחדל. עם mTLS אוטומטי, קובץ עזר חיצוני בצד הלקוח מזהה באופן אוטומטי אם לשרת יש קובץ עזר חיצוני. ה-sidecar של הלקוח שולח mTLS לעומסי עבודה עם sidecars ושולח טקסט פשוט לעומסי עבודה בלי sidecars. כדי ליהנות מהאבטחה הטובה ביותר, מומלץ להפעיל את STRICT mTLS.

אם אתם לא מצליחים להפעיל mTLS במצב STRICT לעומס עבודה או למרחב שמות, אתם יכולים:

  • ליצור מדיניות הרשאה שתאפשר באופן מפורש תנועה עם namespaces לא ריק או principals לא ריק, או
  • לדחות תנועה עם namespaces או principals ריקים.

מכיוון שאפשר לחלץ את namespaces ו-principals רק באמצעות בקשת mTLS, כללי המדיניות האלה דוחים בפועל כל תנועה בטקסט פשוט.

המדיניות הבאה דוחה את הבקשה אם חשבון המשתמש בבקשה ריק (כמו בבקשות טקסט פשוט). המדיניות מאפשרת בקשות אם החשבון הראשי לא ריק. הערך ["*"] מייצג התאמה לא ריקה, והשימוש ב-notPrincipals מייצג התאמה לחשבון משתמש ריק.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-mtls
  namespace: NAMESPACE
spec:
  action: DENY
  rules:
  - from:
    - source:
        notPrincipals: ["*"]

קדימות של מדיניות הרשאות

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

קדימות של מדיניות הרשאה

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

לא לאשר כלום

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

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-nothing
spec:
  action: ALLOW

שיטת אבטחה מומלצת היא להתחיל עם מדיניות allow-nothing, ולהוסיף בהדרגה עוד כללי מדיניות של ALLOW כדי לפתוח יותר גישה לעומס עבודה.

דחיית כל בקשות הגישה

בדוגמה הבאה מוצגת מדיניות DENY שתואמת לכל דבר. מכיוון שכללי המדיניות של DENY נבדקים לפני כללי המדיניות של ALLOW, כל הבקשות נדחות גם אם יש מדיניות ALLOW שתואמת לבקשה.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
spec:
  action: DENY
  rules:
  - {}

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

אישור גישה מלאה

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

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all
spec:
  action: ALLOW
  rules:
  - {}

מדיניות allow-all שימושית אם רוצים לחשוף באופן זמני גישה מלאה לעומס עבודה. אם יש כללי מדיניות של DENY, יכול להיות שהבקשות עדיין יידחו כי כללי המדיניות של DENY נבדקים לפני כללי המדיניות של ALLOW.

שיטות מומלצות

  1. יוצרים חשבון שירות של Kubernetes לכל שירות, ומציינים את חשבון השירות ב-Deployment. לדוגמה:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: frontend-sa
      namespace: demo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      namespace:demo
    spec:
      selector:
        matchLabels:
          app: frontend
      template:
        metadata:
          labels:
            app: frontend
        spec:
          serviceAccountName: frontend-sa
        ...
    
  2. מתחילים עם מדיניות allow-nothing ומוסיפים בהדרגה עוד כללי מדיניות של ALLOW כדי לפתוח גישה נוספת לעומסי עבודה.

  3. אם אתם משתמשים באסימוני JWT בשירות שלכם:

    1. יוצרים מדיניות DENY כדי לחסום בקשות לא מאומתות, לדוגמה:

      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: requireJWT
        namespace: admin
      spec:
        action: DENY
        rules:
        -  from:
          - source:
              notRequestPrincipals: ["*"]
      
    2. החלת מדיניות של "לא לאפשר כלום".

    3. מגדירים כללי מדיניות של ALLOW לכל עומס עבודה. לדוגמאות, ראו אסימון JWT.

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

מידע נוסף על אמצעי האבטחה של Cloud Service Mesh:

מידע נוסף על כללי מדיניות הרשאה זמין במסמכי התיעוד של Istio: