אישור פעולות באשכולות באמצעות בקרת גישה מבוססת-תפקידים

בדף הזה מוסבר איך לאשר פעולות במשאבים באשכולות של Google Kubernetes Engine ‏ (GKE) באמצעות מנגנון בקרת הגישה המובנה שמבוסס על תפקידים (RBAC) ב-Kubernetes. ‫Kubernetes RBAC מופעל כברירת מחדל, ומאפשר לכם שליטה מפורטת בגישה לאשכול.

תלמדו איך להגדיר ולהקצות הרשאות מדויקות, ליצור תפקידים וקישורי תפקידים כדי לנהל את הגישה של המשתמשים, לאמת את הגישה ל-API כדי לבדוק את רמת הגישה, לפתור בעיות נפוצות ולהבין את המגבלות כשעובדים עם RBAC ב-GKE.

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

לפני שקוראים את הדף הזה, חשוב להכיר את המושגים הבאים:

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

לפני שמתחילים, חשוב לוודא שביצעתם את המשימות הבאות:

  • מפעילים את Google Kubernetes Engine API.
  • הפעלת Google Kubernetes Engine API
  • כדי להשתמש ב-Google Cloud CLI למשימה הזו, מתקינים ואז מאתחלים את ה-CLI של gcloud. אם כבר התקנתם את ה-CLI של gcloud, הריצו את הפקודה gcloud components update כדי לקבל את הגרסה העדכנית. יכול להיות שבגרסאות קודמות של ה-CLI של gcloud אי אפשר להריץ את הפקודות שבמסמך הזה.

אינטראקציה עם ניהול זהויות והרשאות גישה (IAM)

כדי לשלוט בגישה לאשכול GKE, אתם יכולים להשתמש גם בניהול זהויות והרשאות גישה (IAM) וגם ב-Kubernetes RBAC:

  • ‫IAM לא ספציפי ל-Kubernetes. הוא מספק ניהול זהויות לכמה מוצרים של Google Cloud , ופועל בעיקר ברמת הפרויקט ב- Google Cloud .

  • ‫RBAC ב-Kubernetes הוא רכיב ליבה של Kubernetes, שמאפשר ליצור ולהקצות תפקידים (קבוצות של הרשאות) לכל אובייקט או סוג אובייקט בתוך האשכול.

  • כדי לאשר פעולה, GKE בודק קודם אם יש מדיניות RBAC. אם אין מדיניות RBAC, ‏GKE בודק את הרשאות ה-IAM.

ב-GKE, מערכת IAM ו-Kubernetes RBAC משולבים כדי לאשר למשתמשים לבצע פעולות אם יש להם הרשאות מספיקות לפי אחד מהכלים. זהו חלק חשוב באתחול של אשכול GKE, כי כברירת מחדל למשתמשי Google Cloud אין קישורי תפקידים (RoleBindings) של RBAC ב-Kubernetes.

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

כמעט בכל המקרים, אפשר להשתמש ב-Kubernetes RBAC במקום ב-IAM. משתמשי GKE צריכים לפחות את הרשאת ה-IAM‏ container.clusters.get בפרויקט שמכיל את האשכול. ההרשאה הזו כלולה בתפקיד container.clusterViewer ובתפקידים אחרים עם הרשאות ברמה גבוהה יותר. ההרשאה container.clusters.get נדרשת למשתמשים כדי לאמת את האשכולות בפרויקט, אבל לא מאשרת להם לבצע פעולות בתוך האשכולות האלה. לאחר מכן, אפשר לספק הרשאה באמצעות IAM או Kubernetes RBAC.

הגדרה והקצאה של הרשאות

אפשר להגדיר כללי RBAC באובייקטים ClusterRole ו-Role, ואז להקצות את הכללים האלה לאובייקטים ClusterRoleBinding ו-RoleBinding באופן הבא:

  • ‫ClusterRole: קיבוץ של משאבים ופעולות מותרות ברמת האשכול, שאפשר להקצות למשתמש או לקבוצה באמצעות RoleBinding או ClusterRoleBinding.
  • תפקיד: קבוצה של משאבים ופעולות מותרות במרחב שמות, שאפשר להקצות למשתמש או לקבוצת משתמשים באמצעות RoleBinding.
  • ‫ClusterRoleBinding: הקצאת ClusterRole למשתמש או לקבוצה לכל מרחבי השמות באשכול.
  • ‫RoleBinding: הקצאת Role או ClusterRole למשתמש או לקבוצה במרחב שמות ספציפי.

כשמשתמשים ב-RoleBinding כדי להקצות ClusterRole למשתמש או לקבוצה, המשתמשים והקבוצות האלה יכולים לגשת רק למשאבים במרחב השמות שציינתם ב-RoleBinding. אם רוצים שהמשתמשים או הקבוצות יוכלו לגשת למשאבים בכל מרחבי השמות, צריך להשתמש ב-ClusterRoleBinding.

הגדרת הרשאות באמצעות Roles או ClusterRoles

אתם מגדירים הרשאות בתוך אובייקט Role או ClusterRole. תפקיד מגדיר גישה למשאבים במרחב שמות אחד, ואילו ClusterRole מגדיר גישה למשאבים בכל האשכול.

התחביר של Roles ו-ClusterRoles זהה. לכל אחד מהם יש קטע rules, שבו מגדירים את המשאבים שהכלל חל עליהם ואת הפעולות שמותר לבצע בתפקיד. לדוגמה, התפקיד הבא מעניק גישת קריאה (get,‏ watch ו-list) לכל ה-Pods במרחב השמות accounting:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: accounting
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

הרשימה המלאה של השדות המותרים מופיעה במאמרי העזרה של ה-API בנושא Role ו-ClusterRole.

Role לעומת ClusterRole

מכיוון שההרשאות שניתנות על ידי ClusterRole חלות על כל האשכול, אפשר להשתמש ב-ClusterRoles כדי לשלוט בגישה לסוגים שונים של משאבים, בניגוד ל-Roles. למשל:

  • משאבים בהיקף אשכול, כמו צמתים
  • נקודות קצה (endpoints) של REST שאינן משאבים, כמו /healthz
  • משאבים עם מרחב שמות בכל מרחבי השמות (לדוגמה, כל ה-Pods בכל האשכול, בלי קשר למרחב השמות)

הקצאת תפקידים באמצעות RoleBindings או ClusterRoleBindings

אחרי שיוצרים Role או ClusterRole, מקצים אותו למשתמש או לקבוצת משתמשים על ידי יצירת RoleBinding או ClusterRoleBinding. משתמשים וקבוצות נקראים subjects, ויכולים להיות כל אחד מהבאים:

סוג הנושא הערך של kind הערך של name
Google Cloud חשבון משתמש User כתובת האימייל הרשומה שלGoogle Cloud
חשבון שירות ב-Kubernetes ServiceAccount השם של אובייקט Kubernetes ServiceAccount באשכול
חשבון שירות ב-IAM User כתובת אימייל של חשבון שירות ב-IAM שנוצרה באופן אוטומטי
כתובת של קבוצה ב-Google בדומיין מאומת Group כתובת האימייל של קבוצה ב-Google Workspace שחברה בקבוצה gke-security-groups. הוראות להגדרת קבוצות Google ל-RBAC מפורטות במאמר הגדרת קבוצות Google ל-RBAC.

ה-RoleBinding הבא מקצה את התפקיד pod-reader למשתמש, לחשבון שירות של Kubernetes, לחשבון שירות של IAM ולקבוצה ב-Google:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-reader-binding
  namespace: accounting
subjects:
# Google Cloud user account
- kind: User
  name: janedoe@example.com
# Kubernetes service account
- kind: ServiceAccount
  name: johndoe
# IAM service account
- kind: User
  name: test-account@test-project.iam.gserviceaccount.com
# Google Group
- kind: Group
  name: accounting-group@example.com
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

אימות הגישה ל-API באמצעות kubectl

‫kubectl מספק את פקודת המשנה auth can-i כדי לשלוח במהירות שאילתות לשכבת ההרשאות של ה-API. כאדמינים בפלטפורמה, יכול להיות שתצטרכו להתחזות למשתמשים כדי לקבוע אילו פעולות הם יכולים לבצע. אפשר להשתמש ב-auth can-i ולהעביר דגל --as נוסף.

כשמריצים את הפקודה kubectl auth can-i בלי הדגל --as, ניהול הזהויות והרשאות הגישה (IAM) מבצע את ההרשאה. לעומת זאת, כשמוסיפים את הדגל --as, האימות מתבצע באמצעות RBAC ב-Kubernetes. לכן, תצטרכו ליצור את האובייקטים הנדרשים של Role ו-RoleBinding בשביל RBAC.

מידע נוסף זמין במאמר אימות הגישה ל-API.

שימוש ב-API ודוגמאות

כדי לקבל מידע מלא על השימוש ב-Kubernetes API ליצירת האובייקטים הנדרשים של Role,‏ ClusterRole,‏ RoleBinding ו-ClusterRoleBinding בשביל RBAC, קראו את המאמר שימוש בהרשאה של בקרת גישה מבוססת-תפקידים במסמכי התיעוד של Kubernetes.

פתרון בעיות ב-RBAC

כדי לנפות באגים בבעיות שקשורות ל-RBAC, אפשר להשתמש ביומן הביקורת של פעילות האדמין, שמופעל כברירת מחדל בכל האשכולות. אם הגישה למשאב או לפעולה נדחית בגלל שאין מספיק הרשאות, שרת ה-API מתעד שגיאת RBAC DENY ביומן, יחד עם מידע נוסף כמו החברות המשתמעת והמפורשת של המשתמש בקבוצה. אם אתם משתמשים בקבוצות Google בשביל RBAC, הערך google groups מופיע בהודעת היומן.

מגבלות

בקטעים הבאים מתוארות אינטראקציות שאולי לא נראות ברורות כשעובדים עם Kubernetes RBAC ו-IAM.

תפקידי ברירת המחדל של Discovery

אשכולות נוצרים עם קבוצה של ClusterRoles ו-ClusterRoleBindings שמוגדרים כברירת מחדל. בקשות שבוצעו עם פרטי כניסה תקינים ממוקמות בקבוצה system:authenticated, וכל שאר הבקשות ממוקמות בקבוצה system:unauthenticated.

ה-ClusterRole‏ system:basic-user מאפשר למשתמשים ליצור SelfSubjectAccessReviews כדי לבדוק את ההרשאות שלהם באשכול. התפקיד system:discovery מאפשר למשתמשים לקרוא ממשקי API של גילוי, שיכולים לחשוף מידע על CustomResourceDefinitions שנוספו לאשכול.

במקום זאת, משתמשים לא רשומים (system:unauthenticated) מקבלים את ClusterRole‏ system:public-info-viewer, שמעניק הרשאת קריאה בלבד לממשקי ה-API‏ /healthz ו-/version.

כדי לראות את נקודות הקצה ל-API שמותרות על ידי ClusterRole של system:discovery, מריצים את הפקודה הבאה:

kubectl get clusterroles system:discovery -o yaml

שגיאת Forbidden בחשבונות שירות במכונות וירטואליות של Google Cloud

השגיאה הבאה יכולה להתרחש כשבמכונה הווירטואלית אין את ההיקף userinfo-email:

Error from server (Forbidden): error when creating ... "role-name" is forbidden: attempt to grant extra privileges:...

לדוגמה, נניח שלמכונה הווירטואלית יש את ההיקף cloud-platform אבל אין לה את ההיקף userinfo-email. כשהמכונה הווירטואלית מקבלת אסימון גישה, Google Cloudמשייך את האסימון הזה להיקף ההרשאות של cloud-platform. כששרת ה-API של Kubernetes מבקש מ- Google Cloud את הזהות שמשויכת לאסימון הגישה, הוא מקבל את המזהה הייחודי של חשבון השירות ולא את כתובת האימייל של חשבון השירות.

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

כדי ליצור מכונה וירטואלית חדשה עם ההיקף userinfo-email, מריצים את הפקודה הבאה:

gcloud compute instances create INSTANCE_NAME \
    --service-account SERVICE_ACCOUNT_EMAIL \
    --scopes userinfo-email

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

  1. מזהים את המזהה הייחודי של חשבון השירות:

    gcloud iam service-accounts describe SERVICE_ACCOUNT_EMAIL
    

    לדוגמה, הפלט הבא מציג את uniqueId של חשבון השירות my-iam-account@somedomain.com:

    displayName: Some Domain IAM service account
    email: my-iam-account@somedomain.com
    etag: BwWWja0YfJA
    name: projects/project-name/serviceAccounts/my-iam-account@somedomain.com
    oauth2ClientId: '123456789012345678901'
    projectId: project-name
    uniqueId: '123456789012345678901'
    
  2. יוצרים קישור תפקיד באמצעות ה-uniqueId של חשבון השירות:

    kubectl create clusterrolebinding CLUSTERROLEBINDING_NAME \
        --clusterrole cluster-admin \
        --user UNIQUE_ID
    

הרשאה ליצור או לעדכן תפקידים וקישורי תפקידים

ב-Kubernetes, אפשר ליצור או לעדכן תפקיד או קישור תפקיד עם הרשאות ספציפיות רק אם עומדים בתנאים הבאים:

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

אם ההרשאות שאתם מקצים בתפקיד הוקצו לכם במקור באמצעות מדיניות הרשאה של IAM במקום RBAC, יכול להיות שהבקשה שלכם לתפקיד או לקישור תפקיד תיכשל. לדוגמה, נניח שמשתמש עם ההרשאות container.pods.* ו-container.roles.create ב-IAM שלח את הבקשה הבאה ליצירת תפקיד:

kubectl create role allowed-to-view-pods --resource pods --verb list,get

אם למשתמש ניתנו רק הרשאות באמצעות IAM, יכול להיות שתופיע השגיאה הבאה:

Error from server (Forbidden): clusterroles.rbac.authorization.k8s.io "allowed-to-view-pods" is forbidden:
user "caller@example.com" (groups=["system:authenticated"]) is attempting to grant RBAC permissions not currently held:
{APIGroups:[""], Resources:["pods"], Verbs:["list" "get"]}

כדי לעקוף את המגבלה הזו, אתם יכולים להשתמש ב-RBAC במקום ב-IAM כדי לתת למבצע הקריאה את ההרשאות שבתפקיד.

לחלופין, אפשר להשתמש ב-RBAC או ב-IAM כדי להעניק למבצע הקריאה את הפועל escalate, את הפועל bind או את שניהם. עם זאת, ב-GKE לא מומלץ להשתמש בגישה הזו, כי הגורם שמבצע את הקריאה יכול להעניק כל הרשאה לכל תפקיד.

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