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

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

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

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

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

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

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

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

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

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

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

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

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

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

כדי לאשר למשתמשים גישה באמצעות חשבונות 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.

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

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

ל-Roles ול-ClusterRoles יש תחביר זהה. לכל כלל יש קטע rules שבו מגדירים את המשאבים שהכלל חל עליהם ואת הפעולות שמותרות לתפקיד. לדוגמה, התפקיד הבא מעניק גישת קריאה (get,‏ watch ו-list) לכל הפודים במרחב השמות 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 חלות על כל האשכול, ולכן אפשר להשתמש ב-ClusterRole כדי לשלוט בגישה לסוגים שונים של משאבים, שלא ניתן לשלוט בהם באמצעות Roles. למשל:

  • משאבים בהיקף אשכול, כמו צמתים
  • נקודות קצה של 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, משתמשים ביומן הביקורת Admin activity, שמופעל בכל האשכולות כברירת מחדל. אם הגישה למשאב או לפעולה נדחית בגלל חוסר הרשאות מספיקות, שרת ה-API מתעד שגיאה RBAC DENY, יחד עם מידע נוסף כמו חברי קבוצה של המשתמש באופן מרומז וגלוי. אם אתם משתמשים בקבוצות Google ל-RBAC, ‏ google groups מופיע בהודעת היומן.

מגבלות

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

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

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

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

משתמשים אנונימיים (system:unauthenticated) מקבלים במקום זאת את system:public-info-viewer ClusterRole, שמעניק גישת קריאה בלבד לממשקי 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 או ליצור קשר חדש בין תפקיד למשתמש שמשתמש במזהה הייחודי.

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

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

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

  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, כי אז המתקשר יכול להעניק כל הרשאה לכל תפקיד.

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