הגדרת אבטחת שירות באמצעות Envoy

במדריך הזה מוסבר איך להגדיר אימות והרשאה לשירותים שנפרסו באמצעות Cloud Service Mesh ושרתי proxy של Envoy. למידע מלא על אבטחת השירות של Cloud Service Mesh, קראו את המאמר אבטחת השירות של Cloud Service Mesh.

דרישות

לפני שמגדירים את אבטחת השירות ב-Cloud Service Mesh עם Envoy, צריך לוודא שההגדרה עומדת בדרישות המוקדמות הבאות:

הכנות להגדרה

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

  • עדכון של Google Cloud CLI
  • הגדרת משתנים
  • הפעלת ממשקי ה-API שנדרשים ל-Cloud Service Mesh כדי לעבוד עם Certificate Authority Service

עדכון כלי שורת הפקודה של gcloud

כדי לעדכן את Google Cloud CLI, מריצים את הפקודה הבאה במכונה המקומית:

gcloud components update

הגדרת משתנים

כדי שתוכלו להעתיק ולהדביק קוד עם ערכים עקביים בזמן העבודה על הדוגמה שבמסמך הזה, הגדירו את המשתנים הבאים. משתמשים בערכים הבאים:

  • ‫PROJECT_ID: מזהה הפרויקט.
  • ‫CLUSTER_NAME: שם האשכול שבו רוצים להשתמש, לדוגמה secure-td-cluster.
  • ‫ZONE: האזור שבו נמצא האשכול.
  • ‫GKE_CLUSTER_URL: החלפה של https://container.googleapis.com/v1/projects/PROJECT_ID/locations/ZONE/clusters/CLUSTER_NAME
  • ‫WORKLOAD_POOL: החלפה של PROJECT_ID.svc.id.goog
  • ‫K8S_NAMESPACE: החלפה של default.
  • ‫DEMO_CLIENT_SERVICEACCOUNT: השם של חשבון השירות של הלקוח ב-Kubernetes.
  • ‫DEMO_SERVER_SERVICEACCOUNT: השם של חשבון השירות של השרת ב-Kubernetes.
  • ‫PROJNUM: מחליפים את מספר הפרויקט שלכם, שאותו אפשר למצוא במסוף Google Cloud או באמצעות הפקודה הבאה:

    gcloud projects describe PROJECT_ID --format="value(projectNumber)"
    
  • ‫SA_GKE: החלפה של service-PROJNUM@container-engine-robot.iam.gserviceaccount.com

  • ‫CLUSTER_VERSION: החלפה בגרסה הזמינה האחרונה. אפשר למצוא את המידע הזה בנתוני הגרסה של הערוץ המהיר. הגרסה המינימלית הנדרשת היא 1.21.4-gke.1801. זוהי גרסת אשכול GKE שבה נשתמש בדוגמה הזו.

מגדירים את הערכים כאן:

# Substitute your project ID
PROJECT_ID=PROJECT_ID

# GKE cluster name and zone for this example.
CLUSTER_NAME=CLUSTER_NAME
ZONE=ZONE

# GKE cluster URL derived from the above
GKE_CLUSTER_URL="https://container.googleapis.com/v1/projects/PROJECT_ID/locations/ZONE/clusters/CLUSTER_NAME"

# Workload pool to be used with the GKE cluster
WORKLOAD_POOL="PROJECT_ID.svc.id.goog"

# Kubernetes namespace to run client and server demo.
K8S_NAMESPACE=K8S_NAMESPACE
DEMO_CLIENT_SERVICEACCOUNT=DEMO_CLIENT_SERVICEACCOUNT
DEMO_SERVER_SERVICEACCOUNT=DEMO_SERVER_SERVICEACCOUNT

# Compute other values
# Project number for your project
PROJNUM=PROJNUM

CLUSTER_VERSION=CLUSTER_VERSION
SA_GKE=service-PROJNUM@container-engine-robot.iam.gserviceaccount.com

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

משתמשים בפקודה gcloud services enable כדי להפעיל את כל ממשקי ה-API שנדרשים להגדרת האבטחה של Cloud Service Mesh באמצעות Certificate Authority Service.

gcloud services enable \
   container.googleapis.com \
   cloudresourcemanager.googleapis.com \
   compute.googleapis.com \
   trafficdirector.googleapis.com \
   networkservices.googleapis.com \
   networksecurity.googleapis.com \
   privateca.googleapis.com \
   gkehub.googleapis.com

יצירה או עדכון של אשכול GKE

אבטחת השירות של Cloud Service Mesh תלויה בשילוב של CA Service עם GKE. אשכול GKE צריך לעמוד בדרישות הבאות, בנוסף לדרישות להגדרה:

  • הגרסה המינימלית של האשכול צריכה להיות ‎1.21.4-gke.1801. אם אתם צריכים תכונות שקיימות בגרסה מאוחרת יותר, אתם יכולים להשיג את הגרסה הזו מערוץ ההפצה המהירה.
  • צריך להפעיל את אשכול GKE ולהגדיר אותו עם אישורי רשת, כמו שמתואר במאמר יצירת רשויות אישורים להנפקת אישורים.
  1. יוצרים אשכול חדש שמשתמש באיחוד זהויות של עומסי עבודה ל-GKE. אם אתם מעדכנים אשכול קיים, דלגו לשלב הבא. הערך שאתם נותנים ל---tags צריך להתאים לשם שמועבר לדגל --target-tags של הפקודה firewall-rules create בקטע הגדרת Cloud Service Mesh עם רכיבי Cloud Load Balancing.

    # Create a GKE cluster with GKE managed mesh certificates.
    gcloud container clusters create CLUSTER_NAME \
      --release-channel=rapid \
      --scopes=cloud-platform \
      --image-type=cos_containerd \
      --machine-type=e2-standard-2 \
      --zone=ZONE \
      --workload-pool=PROJECT_ID.svc.id.goog \
      --enable-mesh-certificates \
      --cluster-version=CLUSTER_VERSION \
      --enable-ip-alias \
      --tags=allow-health-checks \
      --workload-metadata=GKE_METADATA
    

    יצירת האשכול עשויה להימשך כמה דקות.

  2. אם אתם משתמשים באשכול קיים, הפעילו את איחוד הזהויות של עומסי עבודה ל-GKE ואת אישורי GKE mesh. מוודאים שהאשכול נוצר עם הדגל --enable-ip-alias, שאי אפשר להשתמש בו עם הפקודה update.

    gcloud container clusters update CLUSTER_NAME \
      --enable-mesh-certificates
    
  3. מריצים את הפקודה הבאה כדי לעבור לאשכול החדש כאשכול ברירת המחדל לפקודות kubectl:

    gcloud container clusters get-credentials CLUSTER_NAME \
      --zone ZONE
    

פריסה בסביבה מרובת אשכולות

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

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

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

    gcloud compute firewall-rules list \
      --filter="name~gke-{CLUSTER_NAME}-[0-9a-z]*-all" \
      --format="value(sourceRanges)"
    

    לדוגמה, לאשכולות שנקראים cluster-a ו-cluster-b, הפקודות מחזירות תוצאות כמו אלה:

    cluster-a, pod CIDR: 10.4.0.0/14, node network tag: gke-cluster-a-9cd18751-node
    cluster-b, pod CIDR: 10.8.0.0/14, node network tag: gke-cluster-b-acd14479-node
    
  3. יוצרים כללים של חומת אש ב-VPC שמאפשרים לאשכולות לתקשר זה עם זה. לדוגמה, הפקודה הבאה יוצרת כלל חומת אש שמאפשר לכתובות ה-IP של Pod ב-cluster-a לתקשר עם צמתים ב-cluster-b:

    gcloud compute firewall-rules create per-cluster-a-pods \
      --allow="tcp,udp,icmp,esp,ah,sctp" \
      --target-tags="gke-cluster-b-acd14479-node"
    

    הפקודה הבאה יוצרת כלל של חומת אש שמאפשר לכתובות ה-IP של Pod ב-cluster-b לתקשר עם צמתים של cluster-a:

    gcloud compute firewall-rules create per-cluster-b-pods \
      --allow="tcp,udp,icmp,esp,ah,sctp" \
      --target-tags="gke-cluster-a-9cd18751-node"
    

רישום אשכולות ב-fleet

רושמים את האשכול שיצרתם או עדכנתם ב-יצירת אשכול GKE עם Fleet. רישום האשכול מאפשר להגדיר בקלות אשכולות בפרויקטים מרובים.

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

  1. רושמים את האשכול ב-fleet:

    gcloud container fleet memberships register CLUSTER_NAME \
      --gke-cluster=ZONE/CLUSTER_NAME \
      --enable-workload-identity --install-connect-agent \
      --manifest-output-file=MANIFEST-FILE_NAME
    

    מחליפים את המשתנים באופן הבא:

    • ‫CLUSTER_NAME: שם האשכול.
    • ‫ZONE: האזור של האשכול.
    • ‫MANIFEST-FILE_NAME: הנתיב שבו הפקודות האלה יוצרות את המניפסט לרישום.

    אם תהליך הרישום יצליח, תופיע הודעה כמו זו:

    Finished registering the cluster CLUSTER_NAME with the fleet.
  2. מחילים את קובץ המניפסט שנוצר על האשכול:

    kubectl apply -f MANIFEST-FILE_NAME
    

    אם תהליך הגשת הבקשה יצליח, יופיעו הודעות כמו:

    namespace/gke-connect created
    serviceaccount/connect-agent-sa created
    podsecuritypolicy.policy/gkeconnect-psp created
    role.rbac.authorization.k8s.io/gkeconnect-psp:role created
    rolebinding.rbac.authorization.k8s.io/gkeconnect-psp:rolebinding created
    role.rbac.authorization.k8s.io/agent-updater created
    rolebinding.rbac.authorization.k8s.io/agent-updater created
    role.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    clusterrole.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-feature-authorizer-20210416-01-00 created
    rolebinding.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    role.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    rolebinding.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    secret/http-proxy created
    deployment.apps/gke-connect-agent-20210416-01-00 created
    service/gke-connect-monitoring created
    secret/creds-gcp create
    
  3. מקבלים את משאב החברות מהאשכול:

    kubectl get memberships membership -o yaml
    

    הפלט צריך לכלול את מאגר הזהויות של עומסי העבודה שהוקצה על ידי ה-fleet, כאשר PROJECT_ID הוא מזהה הפרויקט:

    workload_identity_pool: PROJECT_ID.svc.id.goog
    

    זה אומר שהאשכול נרשם בהצלחה.

יצירת רשויות אישורים להנפקת אישורים

כדי להנפיק אישורים ל-Pods, צריך ליצור מאגר של שירות CA ואת רשויות האישורים (CA) הבאות:

  • רשות אישורים ברמה הבסיסית (root). זהו שורש האמון של כל אישורי הרשת שהונפקו. אם יש לכם רשות אישורים בסיסית קיימת, אתם יכולים להשתמש בה. יוצרים את רשות האישורים ברמה הבסיסית (root CA) ברמה enterprise, שמיועדת להנפקת אישורים לטווח ארוך ובנפח נמוך.
  • רשות אישורים משנית. רשות האישורים הזו מנפיקה אישורים לעומסי עבודה. יוצרים את רשות האישורים המשנית באזור שבו האשכול פרוס. יוצרים את רשות האישורים המשנית ברמה devops, שמיועדת להנפקת אישורים לטווח קצר ובנפח גבוה.

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

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

אלה האזורים שנתמכים ב-CA Service:

שם האזור תיאור האזור
asia-east1 טייוואן
asia-east2 הונג קונג
asia-northeast1 טוקיו
asia-northeast2 אוסקה
asia-northeast3 סיאול
asia-south1 מומבאי
asia-south2 דלהי
asia-southeast1 סינגפור
asia-southeast2 ג'קארטה
australia-southeast1 סידני
australia-southeast2 מלבורן
europe-central2 ורשה
europe-north1 פינלנד
europe-southwest1 מדריד
europe-west1 בלגיה
europe-west2 לונדון
europe-west3 פרנקפורט
europe-west4 הולנד
europe-west6 ציריך
europe-west8 מילאנו
europe-west9 פריז
europe-west10 ברלין
europe-west12 טורינו
me-central1 דוחה
me-central2 דמאם
me-west1 תל אביב
northamerica-northeast1 מונטריאול
northamerica-northeast2 טורונטו
southamerica-east1 סאו פאולו
southamerica-west1 סנטיאגו
us-central1 איווה
us-east1 דרום קרוליינה
us-east4 צפון וירג'יניה
us-east5 קולומבוס
us-south1 דאלאס
us-west1 אורגון
us-west2 לוס-אנג׳לס
us-west3 סולט לייק סיטי
us-west4 לאס וגאס

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

gcloud privateca locations list
  1. מקצים את roles/privateca.caManager של IAM לאנשים שיוצרים מאגר CA ו-CA. שימו לב שהפורמט הנכון של MEMBER הוא user:userid@example.com. אם המשתמש הנוכחי הוא האדם הזה, אפשר לקבל את מזהה המשתמש הנוכחי באמצעות פקודת המעטפת $(gcloud auth list --filter=status:ACTIVE --format="value(account)").

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.caManager
    
  2. מקצים את התפקיד role/privateca.admin של CA Service למשתמשים שצריכים לשנות את מדיניות ה-IAM, כאשר MEMBER הוא משתמש שצריך את הגישה הזו, ובמיוחד משתמשים שמבצעים את השלבים הבאים שמקצים את התפקידים privateca.auditor ו-privateca.certificateManager:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.admin
    
  3. יוצרים את מאגר שירות ה-CA ברמה הבסיסית (root).

    gcloud privateca pools create ROOT_CA_POOL_NAME \
      --location ROOT_CA_POOL_LOCATION \
      --tier enterprise
    
  4. יוצרים רשות אישורי בסיס.

    gcloud privateca roots create ROOT_CA_NAME --pool ROOT_CA_POOL_NAME \
      --subject "CN=ROOT_CA_NAME, O=ROOT_CA_ORGANIZATION" \
      --key-algorithm="ec-p256-sha256" \
      --max-chain-length=1 \
      --location ROOT_CA_POOL_LOCATION
    

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

    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_NAME=pkcs2-ca
    • ROOT_CA_POOL_LOCATION=us-east1
    • ROOT_CA_ORGANIZATION="TestCorpLLC"
  5. יוצרים את מאגר המשנה ואת רשות האישורים המשנית. מוודאים שמצב ההנפקה המבוסס על הגדרות שמוגדר כברירת מחדל עדיין מותר.

    gcloud privateca pools create SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --tier devops
    
    gcloud privateca subordinates create SUBORDINATE_CA_NAME \
      --pool SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --issuer-pool ROOT_CA_POOL_NAME \
      --issuer-location ROOT_CA_POOL_LOCATION \
      --subject "CN=SUBORDINATE_CA_NAME, O=SUBORDINATE_CA_ORGANIZATION" \
      --key-algorithm "ec-p256-sha256" \
      --use-preset-profile subordinate_mtls_pathlen_0
    

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

    • SUBORDINATE_CA_POOL_NAME="td-ca-pool"
    • SUBORDINATE_CA_POOL_LOCATION=us-east1
    • SUBORDINATE_CA_NAME="td-ca"
    • SUBORDINATE_CA_ORGANIZATION="TestCorpLLC"
    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_POOL_LOCATION=us-east1
  6. מקצים את התפקיד privateca.auditor ב-IAM למאגר ה-CA ברמה הבסיסית (root), כדי לאפשר גישה מחשבון השירות של GKE:

    gcloud privateca pools add-iam-policy-binding ROOT_CA_POOL_NAME \
     --location ROOT_CA_POOL_LOCATION \
     --role roles/privateca.auditor \
     --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  7. מקצים את התפקיד privateca.certificateManager ב-IAM למאגר רשויות האישורים המשניות, כדי לאפשר גישה מחשבון השירות של GKE:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --role roles/privateca.certificateManager \
      --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  8. שומרים את הגדרת ה-YAML הבאה של WorkloadCertificateConfig כדי להורות לאשכול איך להנפיק אישורי רשת:

    apiVersion: security.cloud.google.com/v1
    kind: WorkloadCertificateConfig
    metadata:
      name: default
    spec:
      # Required. The CA service that issues your certificates.
      certificateAuthorityConfig:
        certificateAuthorityServiceConfig:
          endpointURI: ISSUING_CA_POOL_URI
    
      # Required. The key algorithm to use. Choice of RSA or ECDSA.
      #
      # To maximize compatibility with various TLS stacks, your workloads
      # should use keys of the same family as your root and subordinate CAs.
      #
      # To use RSA, specify configuration such as:
      #   keyAlgorithm:
      #     rsa:
      #       modulusSize: 4096
      #
      # Currently, the only supported ECDSA curves are "P256" and "P384", and the only
      # supported RSA modulus sizes are 2048, 3072 and 4096.
      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
      # Optional. Validity duration of issued certificates, in seconds.
      #
      # Defaults to 86400 (1 day) if not specified.
      validityDurationSeconds: 86400
    
      # Optional. Try to start rotating the certificate once this
      # percentage of validityDurationSeconds is remaining.
      #
      # Defaults to 50 if not specified.
      rotationWindowPercentage: 50
    
    

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

    • מזהה הפרויקט שבו האשכול פועל:
      PROJECT_ID
    • ה-URI המלא של רשות האישורים שמנפיקה את האישורים של רשת ה-Mesh (ISSUING_CA_POOL_URI). היא יכולה להיות רשות האישורים המשנית (מומלץ) או רשות האישורים הבסיסית. הפורמט הוא:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
  9. שומרים את הגדרת ה-YAML הבאה של TrustConfig כדי להגדיר לאשכול איך לתת אמון באישורים שהונפקו:

    apiVersion: security.cloud.google.com/v1
    kind: TrustConfig
    metadata:
      name: default
    spec:
      # You must include a trustStores entry for the trust domain that
      # your cluster is enrolled in.
      trustStores:
      - trustDomain: PROJECT_ID.svc.id.goog
        # Trust identities in this trustDomain if they appear in a certificate
        # that chains up to this root CA.
        trustAnchors:
        - certificateAuthorityServiceURI: ROOT_CA_POOL_URI
    

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

    • מזהה הפרויקט שבו האשכול פועל:
      PROJECT_ID
    • ה-URI המלא של מאגר רשויות ה-CA ברמה הבסיסית (ROOT_CA_POOL_URI). הפורמט הוא:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
  10. מחילים את ההגדרות על האשכול:

    kubectl apply -f WorkloadCertificateConfig.yaml
    kubectl apply -f TrustConfig.yaml
    

הגדרת ניהול זהויות והרשאות גישה (IAM)

כדי ליצור את המשאבים שנדרשים להגדרה, צריך את התפקיד compute.NetworkAdmin. התפקיד הזה מכיל את כל ההרשאות שנדרשות כדי ליצור, לעדכן, למחוק, להציג ולהשתמש (כלומר, להפנות אליהם במשאבים אחרים) במשאבים הנדרשים. אם אתם הבעלים והעורכים של הפרויקט, התפקיד הזה מוקצה לכם באופן אוטומטי.

שימו לב שהמדיניות של networksecurity.googleapis.com.clientTlsPolicies.use ו-networksecurity.googleapis.com.serverTlsPolicies.use לא נאכפת כשמפנים למשאבים האלה בשירות לקצה העורפי.

אם ההרשאות האלה ייאכפו בעתיד ואתם משתמשים בתפקיד compute.NetworkAdmin, לא תבחינו בבעיות כשהבדיקה הזו תיאכף.

אם אתם משתמשים בתפקידים בהתאמה אישית והבדיקה הזו תיאכף בעתיד, תצטרכו לוודא שאתם כוללים את ההרשאה .use המתאימה. אחרת, יכול להיות שבעתיד לתפקיד בהתאמה אישית לא יהיו ההרשאות הנדרשות כדי להפנות אל clientTlsPolicy או אל serverTlsPolicy משירות הקצה העורפי או ממדיניות נקודת הקצה.

בהוראות הבאות מוסבר איך ליצור את חשבונות השירות של Kubernetes ולתת להם גישה ל-API של אבטחת Cloud Service Mesh:

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

    kubectl create serviceaccount --namespace K8S_NAMESPACE DEMO_SERVER_SERVICEACCOUNT
    kubectl create serviceaccount --namespace K8S_NAMESPACE DEMO_CLIENT_SERVICEACCOUNT
    
  2. מקצים את התפקיד roles/trafficdirector.client לחשבונות השירות של Kubernetes:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member "principal://iam.googleapis.com/projects/PROJNUM/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/K8S_NAMESPACE/sa/DEMO_SERVER_SERVICEACCOUNT" \
      --role roles/trafficdirector.client \
      --condition=None
    
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member "principal://iam.googleapis.com/projects/PROJNUM/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_SERVICEACCOUNT" \
      --role roles/trafficdirector.client \
      --condition=None
    

הגדרת Cloud Service Mesh

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

התקנת רכיב להחדרת Envoy sidecar אוטומטית באשכול

כדי לפרוס ולהפעיל החדרת Envoy sidecar באשכול, צריך לפעול לפי ההוראות בשני הקטעים הבאים במאמר הגדרת Cloud Service Mesh לפודים של GKE עם החדרת Envoy אוטומטית:

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

הגדרת שירות לבדיקה

אחרי שמתקינים את רכיב Envoy להחדרת sidecar אוטומטית, משתמשים בהוראות הבאות כדי להגדיר שירות בדיקה לפריסה.

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/service_sample.yaml | sed -e s/DEMO_SERVER_KSA_PLACEHOLDER/DEMO_SERVER_SERVICEACCOUNT/g > service_sample.yaml

kubectl apply -f service_sample.yaml

הקובץ service_sample.yaml מכיל את ה-podspec של אפליקציית שרת ההדגמה. יש כמה הערות שספציפיות לאבטחה של Cloud Service Mesh.

מטא-נתונים של שרת proxy ב-Cloud Service Mesh

ה-podspec מציין את ההערה proxyMetadata:

spec:
...
      annotations:
        cloud.google.com/proxyMetadata: '{"app": "payments"}'
...

כשה-Pod מאותחל, קובץ העזר החיצוני אוסף את ההערה הזו ומעביר אותה ל-Cloud Service Mesh. לאחר מכן, Cloud Service Mesh יכול להשתמש במידע הזה כדי לשלוח בחזרה הגדרות מסוננות:

  • בהמשך המדריך, שימו לב שמדיניות נקודת הקצה מציינת התאמה לנקודת קצה.
  • ההתאמה לנקודת הקצה מציינת שרק לקוחות שמציגים תווית עם השם app והערך payments מקבלים את ההגדרות המסוננות.

שימוש באישורים ובמפתחות של רשת שירותים שנחתמו על ידי CA Service

ה-podspec מציין את ההערה enableManagedCerts:

spec:
...
      annotations:
        ...
        cloud.google.com/enableManagedCerts: "true"
...

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

הגדרת היציאה ליירוט תנועה נכנסת

ה-podspec מציין את ההערה includeInboundPorts:

spec:
...
      annotations:
        ...
        cloud.google.com/includeInboundPorts: "8000"
...

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

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

הגדרת שירותי GKE עם קבוצות של נקודות קצה ברשת (NEG)

כדי להגדיר את שירותי GKE כקצוות עורפיים של שירות לקצה העורפי של Cloud Service Mesh, צריך לחשוף אותם באמצעות קבוצות של נקודות קצה ברשת (NEG). בחבילת service_sample.yaml שסופקה עם מדריך ההגדרה הזה, נעשה שימוש בשם ה-NEG‏ service-test-neg בהערה הבאה:

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "service-test-neg"}}}'
spec:
  ports:
  - port: 80
    name: service-test
    protocol: TCP
    targetPort: 8000

אין צורך לשנות את הקובץ service_sample.yaml.

שומרים את השם של קבוצת נקודות הקצה ברשת.

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

NEG_NAME="service-test-neg"

פריסת אפליקציית לקוח ב-GKE

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

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/client_sample.yaml | sed -e s/DEMO_CLIENT_KSA_PLACEHOLDER/DEMO_CLIENT_SERVICEACCOUNT/g > client_sample.yaml

kubectl apply -f client_sample.yaml

ה-podspec של הלקוח כולל רק את ההערה enableManagedCerts. זה נדרש כדי לטעון את אמצעי האחסון שדרושים לאישורים ולמפתחות של רשת מנוהלת ב-GKE, שנחתמו על ידי המכונה של שירות ה-CA.

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

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

  1. יוצרים את בדיקת התקינות.

    gcloud compute health-checks create http td-gke-health-check \
      --use-serving-port
    
  2. יוצרים את הכלל של חומת האש כדי לאפשר את טווחי כתובות ה-IP של בודק התקינות.

    gcloud compute firewall-rules create fw-allow-health-checks \
       --action ALLOW \
       --direction INGRESS \
       --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --rules tcp
    
  3. יוצרים את השירות לקצה העורפי ומשייכים אליו את בדיקת התקינות.

    gcloud compute backend-services create td-gke-service \
      --global \
      --health-checks td-gke-health-check \
      --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  4. מוסיפים את ה-NEG שיצרתם קודם כקצה עורפי לשירות לקצה העורפי.

    gcloud compute backend-services add-backend td-gke-service \
      --global \
      --network-endpoint-group ${NEG_NAME} \
      --network-endpoint-group-zone ZONE \
      --balancing-mode RATE \
     --max-rate-per-endpoint 5
    

הגדרת משאבים ב-Mesh וב-HTTPRoute

בקטע הזה יוצרים משאבים מסוג Mesh ו-HTTPRoute.

  1. יוצרים את מפרט המשאבים של Mesh ושומרים אותו בקובץ בשם mesh.yaml.

    name: sidecar-mesh
    interceptionPort: 15001
    

    אם לא מציינים את יציאת היירוט בקובץ mesh.yaml, ברירת המחדל היא 15001.

  2. יוצרים את המשאב Mesh באמצעות המפרט mesh.yaml.

    gcloud network-services meshes import sidecar-mesh \
      --source=mesh.yaml \
      --location=global
    
  3. יוצרים את המפרט של HTTPRoute ושומרים אותו בקובץ בשם http_route.yaml.

    אפשר להשתמש ב-PROJECT_ID או ב-PROJECT_NUMBER.

    name: helloworld-http-route
    hostnames:
    - service-test
    meshes:
    - projects/PROJNUM/locations/global/meshes/sidecar-mesh
    rules:
    - action:
       destinations:
       - serviceName: "projects/PROJNUM/locations/global/backendServices/td-gke-service"
    
  4. יוצרים את המשאב HTTPRoute באמצעות המפרט בקובץ http_route.yaml.

    gcloud network-services http-routes import helloworld-http-route \
      --source=http_route.yaml \
      --location=global
    

הגדרת Cloud Service Mesh הושלמה, ועכשיו אתם יכולים להגדיר כללי מדיניות של אימות והרשאה.

הגדרת אבטחה בין שירותים

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

הפעלת mTLS ברשת

כדי להגדיר mTLS ברשת, צריך לאבטח את התנועה היוצאת לשירות לקצה העורפי ולאבטח את התנועה הנכנסת לנקודת הקצה.

הפורמט של הפניות למדיניות

שימו לב לפורמט הנדרש הבא להפניה לכללי מדיניות של TLS לשרת, TLS ללקוח והרשאה:

projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies|authorizationPolicies]/[server-tls-policy|client-mtls-policy|authz-policy]

לדוגמה:

projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
projects/PROJECT_ID/locations/global/authorizationPolicies/authz-policy

אבטחת תנועה יוצאת לשירות לקצה העורפי

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

  • ההגדרה משתמשת ב-google_cloud_private_spiffe בתור הפלאגין של clientCertificate, שמתכנת את Envoy להשתמש באישורי רשת מנוהלים של GKE בתור זהות הלקוח.
  • משתמש ב-google_cloud_private_spiffe כפלאגין של serverValidationCa, שמתכנת את Envoy להשתמש באישורי רשת מנוהלים של GKE לאימות השרת.

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

  • המדיניות הזו מחילה את מדיניות האימות ממדיניות ה-TLS של הלקוח על חיבורים יוצאים לנקודות קצה של שירות הקצה העורפי.
  • השדה SAN (שם חלופי של בעלים) מורה ללקוח לאמת את הזהות המדויקת של השרת שאליו הוא מתחבר.
  1. יוצרים את מדיניות ה-TLS של הלקוח בקובץ client-mtls-policy.yaml:

    name: "client-mtls-policy"
    clientCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. מייבאים את מדיניות ה-TLS של הלקוח:

    gcloud network-security client-tls-policies import client-mtls-policy \
        --source=client-mtls-policy.yaml --location=global
    
  3. מצרפים את מדיניות ה-TLS של הלקוח לשירות לקצה העורפי. כך מתבצעת אכיפה של אימות mTLS בכל הבקשות היוצאות מהלקוח לשירות הזה לקצה העורפי.

    gcloud compute backend-services export td-gke-service \
        --global --destination=demo-backend-service.yaml
    

    מוסיפים את השורות הבאות לקובץ demo-backend-service.yaml:

    securitySettings:
      clientTlsPolicy: projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
      subjectAltNames:
        - "spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_SERVICEACCOUNT"
    
  4. מייבאים את הערכים:

    gcloud compute backend-services import td-gke-service \
        --global --source=demo-backend-service.yaml
    
  5. אם רוצים, אפשר להריץ את הפקודה הבאה כדי לבדוק אם הבקשה נכשלה. זהו כשל צפוי, כי הלקוח מצפה לאישורים מנקודת הקצה, אבל נקודת הקצה לא מתוכנתת עם מדיניות אבטחה.

    # Get the name of the Podrunning Busybox.
    BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')
    
    # Command to execute that tests connectivity to the service service-test.
    TEST_CMD="wget -q -O - service-test; echo"
    
    # Execute the test command on the pod.
    kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"
    

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

    wget: server returned error: HTTP/1.1 503 Service Unavailable
    

אבטחת תנועה נכנסת לנקודת הקצה (endpoint)

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

  • השימוש ב-google_cloud_private_spiffe כפלאגין של serverCertificate, שמתכנת את Envoy להשתמש באישורי רשת מנוהלים של GKE כזהות השרת.
  • משתמש ב-google_cloud_private_spiffe כפלאגין ל-clientValidationCa, שמתכנת את Envoy להשתמש באישורי רשת מנוהלים של GKE לאימות לקוח.
  1. שומרים את ערכי מדיניות ה-TLS של השרת בקובץ בשם server-mtls-policy.yaml.

    name: "server-mtls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    mtlsPolicy:
      clientValidationCa:
      - certificateProviderInstance:
          pluginInstance: google_cloud_private_spiffe
    
  2. יוצרים את מדיניות ה-TLS של השרת:

    gcloud network-security server-tls-policies import server-mtls-policy \
        --source=server-mtls-policy.yaml --location=global
    
  3. יוצרים קובץ בשם ep_mtls.yaml שמכיל את ההתאמה לנקודת הקצה, ומצרפים את מדיניות ה-TLS של השרת.

    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: MATCH_ALL
        metadataLabels:
        - labelName: app
          labelValue: payments
    name: "ep"
    serverTlsPolicy: projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy
    type: SIDECAR_PROXY
    
  4. מייבאים את ההתאמה לנקודת הקצה.

    gcloud network-services endpoint-policies import ep \
        --source=ep_mtls.yaml --location=global
    

אימות ההגדרה

מריצים את הפקודה הבאה ב-curl. אם הבקשה תסתיים בהצלחה, בפלט יופיע x-forwarded-client-cert. הכותרת מודפסת רק כשהחיבור הוא חיבור mTLS.

# Get the name of the Podrunning Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test.
TEST_CMD="wget -q -O - service-test; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

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

GET /get HTTP/1.1
Host: service-test
content-length: 0
x-envoy-internal: true
accept: */*
x-forwarded-for: 10.48.0.6
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.35.0
x-forwarded-proto: http
x-request-id: redacted
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_SERVICEACCOUNT;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_SERVICEACCOUNT

שימו לב שהכותרת x-forwarded-client-cert נוספת על ידי Envoy בצד השרת, והיא מכילה את הזהות שלו (שרת) ואת הזהות של הלקוח המקורי. אנחנו רואים את הזהויות של הלקוח ושל השרת, וזה סימן לחיבור mTLS.

הגדרת גישה ברמת השירות באמצעות מדיניות הרשאה

ההוראות האלה יוצרות מדיניות הרשאה שמאפשרת בקשות שנשלחות על ידי החשבון DEMO_CLIENT_SERVICEACCOUNT שבו שם המארח הוא service-test, היציאה היא 8000 ושיטת ה-HTTP היא GET. לפני שיוצרים כללי מדיניות הרשאה, חשוב לקרוא את האזהרה במאמר הגבלת הגישה באמצעות הרשאה.

  1. יוצרים מדיניות הרשאה באמצעות יצירת קובץ בשם authz-policy.yaml.

    action: ALLOW
    name: authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_SERVICEACCOUNT
      destinations:
      - hosts:
        - service-test
        ports:
        - 8000
        methods:
        - GET
    
  2. מייבאים את המדיניות:

    gcloud network-security authorization-policies import authz-policy \
      --source=authz-policy.yaml \
      --location=global
    
  3. כדי לעדכן את מדיניות נקודת הקצה כך שתפנה למדיניות ההרשאה החדשה, מוסיפים את הטקסט הבא לקובץ ep_mtls.yaml:

    authorizationPolicy: projects/PROJECT_ID/locations/global/authorizationPolicies/authz-policy
    

    עכשיו מדיניות נקודת הקצה מציינת שצריך לאכוף גם את mTLS וגם את מדיניות ההרשאה על בקשות נכנסות לפודים שקובצי העזר החיצוניים שלהם ב-Envoy מציגים את התווית app:payments.

  4. מייבאים את המדיניות:

    gcloud network-services endpoint-policies import ep \
        --source=ep_mtls.yaml --location=global
    

אימות ההגדרה

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

# Get the name of the Podrunning Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test.
# This is a valid request and will be allowed.
TEST_CMD="wget -q -O - service-test; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

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

GET /get HTTP/1.1
Host: service-test
content-length: 0
x-envoy-internal: true
accept: */*
x-forwarded-for: redacted
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.35.0
x-forwarded-proto: http
x-request-id: redacted
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_SERVICEACCOUNT;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_SERVICEACCOUNT

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

# Failure case
# Command to execute that tests connectivity to the service service-test.
# This is an invalid request and server will reject because the server
# authorization policy only allows GET requests.
TEST_CMD="wget -q -O - service-test --post-data='' ; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

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

<RBAC: access denied HTTP/1.1 403 Forbidden>

הגדרת אבטחה לשער הכניסה

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

בקטע הזה תפרסו שרת proxy של Envoy כשער כניסה שמסיים חיבורי TLS ומאשר בקשות מלקוחות פנימיים של אשכול.

סיום TLS בשער כניסה (לחצו להגדלה)
סיום TLS בשער כניסה (לחצו כדי להגדיל)

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

  1. פורסים שירות Kubernetes שאפשר להגיע אליו באמצעות כתובת IP פנימית של אשכול.
    1. הפריסה מורכבת משרת proxy עצמאי של Envoy שנחשף כשירות Kubernetes ומתחבר ל-Cloud Service Mesh.
  2. יוצרים מדיניות TLS של שרת כדי לסיים את ה-TLS.
  3. יוצרים מדיניות הרשאה כדי לאשר בקשות נכנסות.

פריסת שירות של שער כניסה ל-GKE

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

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/gateway_sample_xdsv3.yaml | sed -e s/PROJECT_NUMBER_PLACEHOLDER/PROJNUM/g | sed -e s/NETWORK_PLACEHOLDER/default/g | sed -e s/DEMO_CLIENT_KSA_PLACEHOLDER/DEMO_CLIENT_SERVICEACCOUNT/g > gateway_sample.yaml

kubectl apply -f gateway_sample.yaml

הקובץ gateway_sample.yaml הוא המפרט של שער הכניסה. בקטעים הבאים מתוארות כמה תוספות למפרט.

השבתת החדרת ה-sidecar של Cloud Service Mesh

המפרט של gateway_sample.yaml פורס שרת proxy של Envoy בתור הקונטיינר היחיד. בשלבים הקודמים, Envoy הוזרק כקובץ עזר לקונטיינר של אפליקציה. כדי למנוע מצב שבו כמה שרתי Envoy מטפלים בבקשות, אפשר להשבית את החדרת ה-sidecar לשירות Kubernetes באמצעות ההצהרה הבאה:

sidecar.istio.io/inject: "false"

טוענים את אמצעי האחסון הנכון

המפרט gateway_sample.yaml טוען את אמצעי האחסון gke-workload-certificates. האחסון הזה משמש גם לפריסת sidecar, אבל הוא מתווסף באופן אוטומטי על ידי רכיב להחדרת sidecar אוטומטית כשהוא מזהה את ההערה cloud.google.com/enableManagedCerts: "true". אמצעי האחסון gke-workload-certificates מכיל את האישורים והמפתחות של SPIFFE שמנוהלים על ידי GKE, שנחתמו על ידי המכונה של שירות ה-CA שהגדרתם.

הגדרת כתובת ה-IP הפנימית של האשכול

מגדירים את שער הכניסה עם שירות מסוג ClusterInternal. כך נוצר שם מארח של DNS שניתן לפתור באופן פנימי עבור mesh-gateway. כשלקוח שולח בקשה אל mesh-gateway:443, ‏Kubernetes מנתב אותה מיד ליציאה 8080 של פריסת Envoy של שער הכניסה.

הפעלת TLS בשער כניסה

כדי להפעיל TLS בשער כניסה, צריך לפעול לפי ההוראות הבאות.

  1. יוצרים משאב מדיניות TLS של שרת כדי לסיים חיבורי TLS, עם הערכים בקובץ שנקרא server-tls-policy.yaml:

    description: tls server policy
    name: server-tls-policy
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. מייבאים את מדיניות ה-TLS של השרת:

    gcloud network-security server-tls-policies import server-tls-policy \
        --source=server-tls-policy.yaml --location=global
    
  3. יוצרים יעד חדש Gateway ושומרים אותו בקובץ td-gke-gateway.yaml. כך מצרפים את מדיניות ה-TLS של השרת ומגדירים את שער הכניסה של שרת ה-Proxy של Envoy לסיים את תעבורת הנתונים הנכנסת של TLS.

    name: td-gke-gateway
    scope: gateway-proxy
    ports:
    - 8080
    type: OPEN_MESH
    serverTlsPolicy: projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
    
  4. מייבאים את השער:

    gcloud network-services gateways import td-gke-gateway \
      --source=td-gke-gateway.yaml \
      --location=global
    
  5. יוצרים ושומרים HTTPRoute חדש בשם td-gke-route שמפנה לשער ומנתב את כל הבקשות אל td-gke-service.

    name: td-gke-route
    hostnames:
    - mesh-gateway
    gateways:
    - projects/PROJECT_NUMBER/locations/global/gateways/td-gke-gateway
    rules:
    - action:
        destinations:
        - serviceName: "projects/PROJECT_NUMBER/locations/global/backendServices/td-gke-service"
    
  6. מייבאים את HTTPRoute:

    gcloud network-services http-routes import td-gke-route \
      --source=td-gke-route.yaml \
      --location=global
    
    
  7. אפשר לעדכן את מדיניות ההרשאות בקצוות העורפיים כדי לאפשר בקשות כשכל התנאים הבאים מתקיימים:

    • בקשות שנשלחו על ידי DEMO_CLIENT_SERVICEACCOUNT. (הפריסה של שער הכניסה משתמשת בחשבון השירות DEMO_CLIENT_SERVICEACCOUNT).
    • בקשות עם המארח mesh-gateway או service-test
    • יציאה: 8000

    אתם לא צריכים להריץ את הפקודות האלה, אלא אם הגדרתם מדיניות הרשאה לקצוות העורפיים. אם אין מדיניות הרשאה בנקודת הקצה, או שהיא לא מכילה התאמה של המארח או של חשבון המשתמש המקורי במדיניות ההרשאה, הבקשה תאושר בלי השלב הזה. מוסיפים את הערכים האלה אל authz-policy.yaml.

    action: ALLOW
    name: authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_SERVICEACCOUNT
      destinations:
      - hosts:
        - service-test
        - mesh-gateway
        ports:
        - 8000
        methods:
        - GET
    
  8. מייבאים את המדיניות:

    gcloud network-security authorization-policies import authz-policy \
      --source=authz-policy.yaml \
      --location=global
    

אימות הפריסה של שער הכניסה

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

במפרט הבא, ההערה "sidecar.istio.io/inject":"false" מונעת מהרכיב להחדרת sidecar אוטומטית של Cloud Service Mesh להחדיר באופן אוטומטי קובץ עזר חיצוני. אין קונטיינר צדדי שיעזור לקונטיינר debug לנתב את הבקשות. הקונטיינר צריך להתחבר לשער הכניסה לצורך ניתוב.

המפרט כולל את הדגל --no-check-certificate, שמתעלם מאימות האישור של השרת. במאגר debug אין את אישורי האימות של רשות האישורים שנדרשים כדי לאמת אישורים שנחתמו על ידי שירות CA, שמשמשים את שער הכניסה כדי לסיים את TLS.

בסביבת ייצור, מומלץ להוריד את אישור האימות של שירות ה-CA ולהתקין אותו בלקוח. אחרי שמתקינים את אישור האימות, מסירים את האפשרות --no-check-certificate מהפקודה wget.

מריצים את הפקודה הבאה:

kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway; echo"

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

GET / HTTP/1.1
Host: 10.68.7.132
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_SERVICEACCOUNT;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_SERVICEACCOUNT
x-envoy-expected-rq-timeout-ms: 15000
x-envoy-internal: true
x-request-id: 5ae429e7-0e18-4bd9-bb79-4e4149cf8fef
x-forwarded-for: 10.64.0.53
x-forwarded-proto: https
content-length: 0
user-agent: Wget

מריצים את פקודת הבדיקה השלילית הבאה:

# Negative test
# Expect this to fail because gateway expects TLS.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - http://mesh-gateway:443/headers; echo"

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

wget: error getting response: Connection reset by peer

מריצים את פקודת הבדיקה השלילית הבאה:

# Negative test.
# AuthorizationPolicy applied on the endpoints expect a GET request. Otherwise
# the request is denied authorization.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway --post-data=''; echo"

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

HTTP/1.1 403 Forbidden
wget: server returned error: HTTP/1.1 403 Forbidden

מחיקת הפריסה

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

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

gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet

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

gcloud compute backend-services delete td-gke-service --global --quiet
cloud compute network-endpoint-groups delete service-test-neg --zone ZONE --quiet
gcloud compute firewall-rules delete fw-allow-health-checks --quiet
gcloud compute health-checks delete td-gke-health-check --quiet
gcloud network-services endpoint-policies delete ep \
    --location=global --quiet
gcloud network-security authorization-policies delete authz-gateway-policy \
   --location=global --quiet
gcloud network-security authorization-policies delete authz-policy \
    --location=global --quiet
gcloud network-security client-tls-policies delete client-mtls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-tls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-mtls-policy \
    --location=global --quiet

מגבלות

אבטחת השירות של Cloud Service Mesh נתמכת רק ב-GKE. אי אפשר לפרוס אבטחת שירות באמצעות Compute Engine.

פתרון בעיות

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

כשלים בחיבור

אם החיבור נכשל עם שגיאת upstream connect או שגיאת disconnect/reset before headers, בודקים את יומני Envoy, שבהם עשויה להופיע אחת מהודעות היומן הבאות:

gRPC config stream closed: 5, Requested entity was not found

gRPC config stream closed: 2, no credential token is found

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

למידע נוסף, קראו את המאמר הודעות שגיאה ביומני Envoy מצביעות על בעיה בהגדרה.

לא נוצרו פודים

כדי לפתור את הבעיה, קראו את המאמר פתרון בעיות בפריסות אוטומטיות של Pods ב-GKE.

‫Envoy לא מבצע אימות באמצעות Cloud Service Mesh

כש-Envoy (envoy-proxy) מתחבר ל-Cloud Service Mesh כדי לאחזר את הגדרת ה-xDS, הוא משתמש באיחוד זהויות של עומסי עבודה ל-GKE וב-ServiceAccount של Kubernetes של ה-Pod. אם האימות נכשל, Envoy לא נכנס למצב מוכן.

לא ניתן ליצור אשכול עם --workload-identity-certificate-authority flag

אם השגיאה הזו מופיעה, ודאו שאתם משתמשים בגרסה העדכנית של Google Cloud CLI:

gcloud components update

ה-Pods נשארים במצב המתנה

אם ה-Pods נשארים במצב המתנה במהלך תהליך ההגדרה, צריך להגדיל את משאבי המעבד (CPU) והזיכרון של ה-Pods במפרט הפריסה.

אי אפשר ליצור אשכול עם הדגל --enable-mesh-certificates

מוודאים שאתם משתמשים בגרסה העדכנית של ה-CLI של gcloud:

gcloud components update

שימו לב שהדגל --enable-mesh-certificates פועל רק עם gcloud beta.

הפודים לא מתחילים

יכול להיות ש-Pods שמשתמשים באישורי רשת של GKE לא יתחילו לפעול אם הקצאת האישורים נכשלת. זה יכול לקרות במצבים כמו:

  • ה-WorkloadCertificateConfig או ה-TrustConfig מוגדרים באופן שגוי או חסרים.
  • בקשות CSR לא מאושרות.

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

  1. בודקים את הסטטוס של ה-Pod:

    kubectl get pod -n POD_NAMESPACE POD_NAME
    

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

    • ‫POD_NAMESPACE: מרחב השמות של ה-Pod.
    • ‫POD_NAME: שם ה-Pod.
  2. כדי לבדוק אירועים אחרונים ב-Pod:

    kubectl describe pod -n POD_NAMESPACE POD_NAME
    
  3. אם הקצאת האישור נכשלת, יוצג אירוע עם Type=Warning, Reason=FailedMount, From=kubelet ושדה Message שמתחיל ב-MountVolume.SetUp failed for volume "gke-workload-certificates". השדה Message מכיל מידע לפתרון בעיות.

    Events:
      Type     Reason       Age                From       Message
      ----     ------       ----               ----       -------
      Warning  FailedMount  13s (x7 over 46s)  kubelet    MountVolume.SetUp failed for volume "gke-workload-certificates" : rpc error: code = Internal desc = unable to mount volume: store.CreateVolume, err: unable to create volume "csi-4d540ed59ef937fbb41a9bf5380a5a534edb3eedf037fe64be36bab0abf45c9c": caPEM is nil (check active WorkloadCertificateConfig)
    
  4. אם הפודים לא מתחילים לפעול בגלל אובייקטים שהוגדרו באופן שגוי או בגלל בקשות CSR שנדחו, אתם יכולים להיעזר בשלבים הבאים לפתרון הבעיות.

ההגדרה של WorkloadCertificateConfig או TrustConfig שגויה

מוודאים שיצרתם את האובייקטים WorkloadCertificateConfig ו-TrustConfig בצורה נכונה. אפשר לאבחן הגדרות שגויות בכל אחד מהאובייקטים האלה באמצעות kubectl.

  1. אחזור הסטטוס הנוכחי.

    עבור WorkloadCertificateConfig:

    kubectl get WorkloadCertificateConfig default -o yaml
    

    עבור TrustConfig:

    kubectl get TrustConfig default -o yaml
    
  2. בודקים את פלט הסטטוס. אובייקט תקין יכלול תנאי עם type: Ready ו-status: "True".

    status:
      conditions:
      - lastTransitionTime: "2021-03-04T22:24:11Z"
        message: WorkloadCertificateConfig is ready
        observedGeneration: 1
        reason: ConfigReady
        status: "True"
        type: Ready
    

    אם האובייקטים לא תקינים, מופיע הסמל status: "False". השדות reason ו-message מכילים פרטים נוספים לפתרון בעיות.

בקשות CSR לא אושרו

אם משהו משתבש במהלך תהליך האישור של ה-CSR, אפשר לבדוק את פרטי השגיאה בתנאים type: Approved ו-type: Issued של ה-CSR.

  1. מציגים את בקשות ה-CSR הרלוונטיות באמצעות kubectl:

    kubectl get csr \
      --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
    
  2. צריך לבחור CSR שהוא Approved ולא Issued, או שהוא לא Approved.

  3. מציגים את הפרטים של ה-CSR שנבחר באמצעות kubectl:

    kubectl get csr CSR_NAME -o yaml
    

    מחליפים את CSR_NAME בשם של ה-CSR שבחרתם.

ב-CSR תקין יש תנאי עם type: Approved ו-status: "True", ואישור תקין בשדה status.certificate:

status:
  certificate: <base64-encoded data>
  conditions:
  - lastTransitionTime: "2021-03-04T21:58:46Z"
    lastUpdateTime: "2021-03-04T21:58:46Z"
    message: Approved CSR because it is a valid SPIFFE SVID for the correct identity.
    reason: AutoApproved
    status: "True"
    type: Approved

מידע על פתרון בעיות של בקשות CSR לא תקינות מופיע בשדות message ו-reason.

אפליקציות לא יכולות להשתמש בפרטי כניסה שהונפקו ל-mTLS

  1. מוודאים שהתוקף של האישור לא פג:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  2. צריך לוודא שהאפליקציה תומכת בסוג המפתח שבו השתמשתם.

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
    
  3. בודקים שהרשות המנפיקה משתמשת באותה משפחת מפתחות כמו המפתח של האישור.

    1. בודקים את הסטטוס של המכונה של שירות CA (גרסת טרום-השקה (Preview)):

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

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

      • ‫ISSUING_CA_TYPE: סוג ה-CA המנפיק, שיכול להיות subordinates או roots.
      • ‫ISSUING_CA_NAME: השם של הרשות המנפיקה לאישורים.
      • ‫ISSUING_CA_LOCATION: האזור של ה-CA המנפיק.
    2. מוודאים שהערך של keySpec.algorithm בפלט הוא אותו אלגוריתם מפתח שהגדרתם במניפסט ה-YAML של WorkloadCertificateConfig. הפלט אמור להיראות כך:

      config:
        ...
        subjectConfig:
          commonName: td-sub-ca
          subject:
            organization: TestOrgLLC
          subjectAltName: {}
      createTime: '2021-05-04T05:37:58.329293525Z'
      issuingOptions:
        includeCaCertUrl: true
      keySpec:
        algorithm: RSA_PKCS1_2048_SHA256
       ...
      

האישורים נדחים

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

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  3. אם קוד הלקוח לא משתמש ב-Credentials Reloading API של gRPC Go, צריך לוודא שהוא מרענן מדי פעם את פרטי הכניסה ממערכת הקבצים.

  4. מוודאים שעומסי העבודה נמצאים באותו מתחם אמון (trust domain) כמו ה-CA. אישורי רשת ב-GKE תומכים בתקשורת בין עומסי עבודה במתחם אמון (trust domain) אחד.