סנכרון סודות עם סודות של Kubernetes

במאמר הזה מתואר איך מסנכרנים סודות שמאוחסנים ב-Secret Manager עם סודות של Kubernetes באשכולות Google Kubernetes Engine ‏ (GKE).

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

המלצה: התכונה של סנכרון סודות היא חלופה לתוסף Secret Manager, שמעלה סודות כקבצים בזיכרון ישירות ל-Pods. מומלץ להשתמש בתוסף Secret Manager בכל פעם שהאפליקציה תומכת בו, כי זו שיטה מאובטחת יותר לגשת לסודות מ-Secret Manager ב-GKE.

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

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

  • מפעילים את Secret Manager ואת Google Kubernetes Engine APIs, אם הם לא מופעלים כבר.

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, צריך את ההרשאה serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין בממשק Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידים

    הפעלת ממשקי ה-API

  • מתקינים ואז מפעילים את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, תוכלו להריץ את הפקודה gcloud components update כדי לקבל את הגרסה העדכנית.

  • מוודאים שאשכול GKE פועל. התכונה הזו דורשת GKE מגרסה 1.33 ואילך.

  • מוודאים שאיחוד זהויות של עומסי עבודה ל-GKE מופעל באשכול GKE. הפרטים האלה נדרשים לאימות. איחוד זהויות של עומסי עבודה ל-GKE מופעל כברירת מחדל באשכול Autopilot.

  • מוודאים שיש לכם את ההרשאות הנדרשות לניהול זהויות והרשאות גישה (IAM) כדי לנהל את אשכולות GKE ואת Secret Manager.

הפעלת סנכרון של סודות באשכול GKE

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

הפעלת סנכרון סודות באשכול חדש

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

אשכול רגיל

כדי להשתמש ב-Secret Manager בשורת הפקודה, קודם צריך להתקין את Google Cloud CLI או לשדרג לגרסה 378.0.0 ואילך. ב-Compute Engine או ב-GKE, צריך להזדהות באמצעות ההיקף cloud-platform.

הפעלת סנכרון סודות ללא רוטציה אוטומטית.

gcloud container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --workload-pool=PROJECT_ID.s3ns.svc.id.goog \
    --enable-secret-sync

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

gcloud container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --workload-pool=PROJECT_ID.s3ns.svc.id.goog \
    --enable-secret-sync \
    --enable-secret-sync-rotation

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

gcloud container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --workload-pool=PROJECT_ID.s3ns.svc.id.goog \
    --enable-secret-sync \
    --enable-secret-sync-rotation \
    --secret-sync-rotation-interval=60s

מחליפים את מה שכתוב בשדות הבאים:

  • ‫CLUSTER_NAME: השם של אשכול GKE
  • ‫CONTROL_PLANE_LOCATION: האזור או האזור של מישור הבקרה של האשכול, למשל us-central1 או us-east1-a
  • ‫PROJECT_ID: מזהה הפרויקט ב- Cloud de Confiance by S3NS

אשכול במצב אוטומטי

כדי להשתמש ב-Secret Manager בשורת הפקודה, קודם צריך להתקין את Google Cloud CLI או לשדרג לגרסה 378.0.0 ואילך. ב-Compute Engine או ב-GKE, צריך להזדהות באמצעות ההיקף cloud-platform.

הפעלת סנכרון סודות ללא רוטציה אוטומטית.

gcloud container clusters create-auto CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync

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

gcloud container clusters create-auto CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync \
    --enable-secret-sync-rotation

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

gcloud container clusters create-auto CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync \
    --enable-secret-sync-rotation \
    --secret-sync-rotation-interval=60s

מחליפים את מה שכתוב בשדות הבאים:

  • ‫CLUSTER_NAME: השם של אשכול GKE
  • ‫CONTROL_PLANE_LOCATION: האזור או האזור של מישור הבקרה של האשכול, למשל us-central1 או us-east1-a

הפעלת סנכרון של סודות באשכול קיים

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

gcloud

כדי להשתמש ב-Secret Manager בשורת הפקודה, קודם צריך להתקין את Google Cloud CLI או לשדרג לגרסה 378.0.0 ואילך. ב-Compute Engine או ב-GKE, צריך להזדהות באמצעות ההיקף cloud-platform.

הפעלת סנכרון של סודות באשכול קיים

gcloud container clusters update CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync

הפעלה של רוטציה עם מרווח זמן מותאם אישית

gcloud container clusters update CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync-rotation \
    --secret-sync-rotation-interval=300s

השבתת הסיבוב

gcloud container clusters update CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --no-enable-secret-sync-rotation

מחליפים את מה שכתוב בשדות הבאים:

  • ‫CLUSTER_NAME: השם של אשכול GKE
  • ‫CONTROL_PLANE_LOCATION: האזור או האזור של מישור הבקרה של האשכול, למשל us-central1 או us-east1-a

הגדרת סנכרון של סודות

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

  1. יוצרים Kubernetes ServiceAccount באמצעות הפקודה הבאה:

    kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫KSA_NAME: השם של חשבון השירות של Kubernetes
    • ‫NAMESPACE: מרחב השמות של Kubernetes שבו רוצים ליצור את חשבון השירות
  2. יוצרים מדיניות הרשאה ב-IAM שמפנה אל KubernetesServiceAccount החדש ומעניקים לחשבון השירות הרשאה לגשת לסוד:

    gcloud

    כדי להשתמש ב-Secret Manager בשורת הפקודה, קודם צריך להתקין את Google Cloud CLI או לשדרג לגרסה 378.0.0 ואילך. ב-Compute Engine או ב-GKE, צריך להזדהות באמצעות ההיקף cloud-platform.

    gcloud secrets add-iam-policy-binding SECRET_NAME \
       --role=roles/secretmanager.secretAccessor \
       --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.s3ns.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫SECRET_NAME: השם של הסוד ב-Secret Manager
    • ‫PROJECT_NUMBER: מספר הפרויקט ב- Cloud de Confiance
    • ‫PROJECT_ID: מזהה הפרויקט ב- Cloud de Confiance
    • ‫NAMESPACE: מרחב השמות של Kubernetes
    • ‫KSA_NAME: השם של חשבון השירות שלכם ב-Kubernetes
  3. יוצרים משאב מותאם אישית מסוג SecretProviderClass באמצעות מניפסט YAML. משאב SecretProviderClass מגדיר את הסודות הספציפיים לאחזור מ-Secret Manager, כולל שמות המשאבים והנתיבים שלהם. התוסף Secret Manager משתמש גם במשאב SecretProviderClass כדי לרשום את הסודות להרכבה ואת שם הקובץ שבו הם יורכבו.

    יוצרים קובץ spc.yaml עם התוכן הבא:

    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: SECRET_PROVIDER_CLASS_NAME
      namespace: NAMESPACE
    spec:
      provider: gke
      parameters:
        secrets: |
          -   resourceName: "projects/SECRET_PROJECT_ID/secrets/SECRET_NAME_1/versions/SECRET_VERSION_1"
              path: "FILENAME.txt"
          -   resourceName: "projects/SECRET_PROJECT_ID/secrets/SECRET_NAME_2/versions/SECRET_VERSION_2"
              path: "FILENAME1.txt"
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫SECRET_PROVIDER_CLASS_NAME: השם של אובייקט SecretProviderClass.
    • ‫NAMESPACE: מרחב השמות ב-Kubernetes שבו יוצרים את המשאב הזה.
    • ‫resourceName: מזהה המשאב המלא של הסוד ב-Secret Manager. המחרוזת הזו צריכה לכלול את מזהה הפרויקט, שם הסוד והגרסה בפורמט הבא: projects/SECRET_PROJECT_ID/secrets/SECRET_NAME/versions/SECRET_VERSION.
      • ‫SECRET_PROJECT_ID: מזהה Cloud de Confiance by S3NS הפרויקט שבו מאוחסן הסוד. הערך יכול להיות זהה לערך של PROJECT_ID אם הסוד מאוחסן באותו פרויקט שבו נמצא אשכול GKE.
      • ‫SECRET_NAME: שם הסוד.
      • ‫SECRET_VERSION: גרסת הסוד. הגרסה של הסוד צריכה להיות באותו אזור כמו האשכול.
    • ‫path: שם הקובץ המקומי או הכינוי שערך הסוד יוצג כמותו בסביבת Kubernetes. זהו המזהה הייחודי שמקשר בין גרסה ספציפית של Secret Manager לבין הייצוג המקומי שבו משתמש האשכול. כשמבצעים סנכרון של הסוד עם סוד של Kubernetes באמצעות המשאב SecretSync, הנתיב הזה מפנה לשדה sourcePath כדי לאתר את ערך הסוד לצורך הסנכרון. אפשר למפות כמה סודות (מוגדרים על ידי resourceName) לשמות נתיבים שונים באותו SecretProviderClass.
  4. כדי להחיל את קובץ המניפסט, מריצים את הפקודה הבאה:

    kubectl apply -f spc.yaml
    
  5. יוצרים משאב מותאם אישית של SecretSync באמצעות מניפסט YAML. המשאב הזה מורה לבקר הסנכרון ליצור או לעדכן Kubernetes Secret על סמך התוכן שמוגדר ב-SecretProviderClass.

    יוצרים קובץ secret-sync.yaml עם התוכן הבא:

    apiVersion: secret-sync.gke.io/v1
    kind: SecretSync
    metadata:
      name: KUBERNETES_SECRET_NAME
      namespace: NAMESPACE
    spec:
      serviceAccountName: KSA_NAME
      secretProviderClassName: SECRET_PROVIDER_CLASS_NAME
      secretObject:
        type: KUBERNETES_SECRET_TYPE
        data:
          -   sourcePath: "FILENAME.txt"
              targetKey: "TARGET_KEY1"
          -   sourcePath: "FILENAME1.txt"
              targetKey: "TARGET_KEY2"
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫KUBERNETES_SECRET_NAME: השם שרוצים לתת ל-Kubernetes Secret החדש שייווצר על ידי משאב SecretSync.
    • ‫NAMESPACE: מרחב השמות של Kubernetes שבו נוצר המשאב החדש. זה צריך להיות אותו מרחב שמות כמו SecretProviderClass.
    • ‫KSA_NAME: השם של חשבון השירות ב-Kubernetes שהבקר SecretSync משתמש בו כדי ליצור ולעדכן את הסוד ב-Kubernetes. לחשבון השירות הזה צריכות להיות ההרשאות הנדרשות כדי לגשת לסודות חיצוניים מ-Secret Manager.
    • ‫SECRET_PROVIDER_CLASS_NAME: השם של אובייקט SecretProviderClass שיצרתם בשלב הקודם. המשאב SecretSync משתמש בזה כדי למצוא את ההגדרה הנכונה של הסודות.
    • ‫KUBERNETES_SECRET_TYPE: סוג הסוד של Kubernetes שייווצר, כמו Opaque,‏ tls או docker-registry. ההגדרה הזו קובעת איך Kubernetes מטפל בנתונים של הסוד.
    • ‫sourcePath: שם הקובץ המקומי או הכינוי (הערך של השדה path ב-SecretProviderClass) שמזהה את נתוני הסוד שיש לאחזר. הבקר SecretSync משתמש ב-sourcePath כדי לבקש את התוכן הסודי הספציפי ולהמיר אותו לסוד חדש של Kubernetes.
    • ‫targetKey: המפתח שישמש בקטע data של סוד Kubernetes החדש שנוצר. המאפיין הזה מגדיר את השם של תוכן הסוד שמאוחזר באמצעות sourcePath ואת האופן שבו הוא מאוחסן באובייקט הסוד הסופי של Kubernetes. שימוש בכמה רשומות במערך הנתונים מאפשר להגדיר כמה צמדים של מפתח-ערך באותו סוד יעד.
  6. כדי להחיל את קובץ המניפסט, מריצים את הפקודה הבאה:

    kubectl apply -f secret-sync.yaml
    

    בקר הסנכרון יוצר סוד של Kubernetes במרחב השמות שצוין. הסוד הזה מכיל את הנתונים שמופים מ-Secret Manager.

  7. מוודאים שנוצר סוד של Kubernetes:

    kubectl get secret KUBERNETES_SECRET_NAME -n NAMESPACE -o yaml
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫KUBERNETES_SECRET_NAME: השם של הסוד החדש ב-Kubernetes
    • ‫NAMESPACE: מרחב השמות ב-Kubernetes שבו נוצר הסוד החדש
  8. כדי לפתור בעיה בסנכרון, משתמשים בפקודה הבאה:

    kubectl describe secretSync KUBERNETES_SECRET_NAME -n NAMESPACE
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫KUBERNETES_SECRET_NAME: השם של הסוד החדש ב-Kubernetes
    • ‫NAMESPACE: מרחב השמות של Kubernetes שבו צריך ליצור את הסוד החדש

ניהול סבב סודות

אם מפעילים את הדגל --enable-secret-sync-rotation באשכול, בקר הסנכרון בודק מעת לעת את Secret Manager כדי לראות אם יש גרסאות חדשות של הסודות שצוינו במשאב SecretProviderClass. הדגל --secret-sync-rotation-interval קובע באיזו תדירות בודק בקר העדכונים אם יש עדכונים.

אם בקר מזהה גרסה חדשה של סוד ב-Secret Manager, הבקר מעדכן את הסוד התואם ב-Kubernetes. הבקר משווה בין הגיבובים של התוכן הסודי כדי לעדכן את הסודות רק כשמתרחשים שינויים.

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

השבתת סנכרון הסודות

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

gcloud

כדי להשתמש ב-Secret Manager בשורת הפקודה, קודם צריך להתקין את Google Cloud CLI או לשדרג לגרסה 378.0.0 ואילך. ב-Compute Engine או ב-GKE, צריך להזדהות באמצעות ההיקף cloud-platform.

gcloud container clusters update CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --no-enable-secret-sync

מחליפים את מה שכתוב בשדות הבאים:

  • ‫CLUSTER_NAME: השם של אשכול GKE
  • ‫CONTROL_PLANE_LOCATION: האזור או האזור של מישור הבקרה של האשכול, למשל us-central1 או us-east1-a

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

מחיקת סודות מסונכרנים

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

    kubectl delete secretsync KUBERNETES_SECRET_NAME --namespace NAMESPACE

מחליפים את מה שכתוב בשדות הבאים:

  • ‫KUBERNETES_SECRET_NAME: השם של הסוד ב-Kubernetes
  • ‫NAMESPACE: מרחב השמות ב-Kubernetes שבו קיים הסוד

מעבר מ-Secrets Store CSI Driver הקיים

אם אתם מבצעים העברה מההתקנה הקיימת של Secrets Store CSI Driver, אתם צריכים לפעול לפי השלבים הבאים:

  1. מעדכנים את השדה provider ב-SecretProviderClass מ-gcp ל-gke. בדוגמה הבאה אפשר לראות איך מעדכנים את השדה provider:

    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: app-secrets-gke
    spec:
      provider: gke
      parameters:
        secrets: |
          -   resourceName: "projects/87654321/secrets/api-key-secret/versions/2"
              path: "good1.txt"
    
  2. יוצרים משאב SecretSync. משתמשים בהגדרות לדוגמה הבאות:

    apiVersion: secret-sync.gke.io/v1
    kind: SecretSync
    metadata:
      name: my-kube-secret
      namespace: NAMESPACE
    spec:
      serviceAccountName: KSA_NAME
      secretProviderClassName: my-app-secrets
      secretObject:
        type: Opaque # Or other Kubernetes Secret types
        data:
          -   sourcePath: "my-secret.txt"
              targetKey: "USERNAME"
          -   sourcePath: "another-secret.txt"
              targetKey: "PASSWORD"
    

שיקולי אבטחה

‫Secret Manager מציע תכונות אבטחה כמו בקרת גישה באמצעות IAM, מפתחות הצפנה בניהול הלקוח (CMEK) ורישום ביומן ביקורת. הסודות מוצפנים כשהם מאוחסנים ובזמן ההעברה ב-Secret Manager. כשמסנכרנים סודות עם סודות של Kubernetes, האבטחה שלהם באשכול תלויה בהגדרה של אשכול GKE. כמה נקודות שכדאי לחשוב עליהן:

  • אחסון: סודות של Kubernetes מאוחסנים ב-etcd, שהוא מאגר הנתונים הראשי של GKE. כברירת מחדל, GKE מצפין נתונים במנוחה. כדי לשפר את האבטחה, אפשר להצפין סודות של Kubernetes בשכבת האפליקציה באמצעות מפתח שמנוהל ב-Cloud Key Management Service ‏(Cloud KMS). הצפנה של סודות מספקת שכבת אבטחה נוספת לעומסי עבודה רגישים.

  • בקרת גישה: GKE תומך בכמה אפשרויות לניהול גישה למשאבים בפרויקטים ובאשכולות שלהם באמצעות בקרת גישה מבוססת-תפקידים (RBAC). הרשאות RBAC רחבות מדי עלולות לחשוף סודות לעומסי עבודה או למשתמשים לא מכוונים. צריך להעניק גישה בהתאם לעיקרון של הרשאות מינימליות ולבצע ביקורת על הגישה ל-Secret Manager ולסודות של Kubernetes באופן קבוע.

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

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