יצירת פריסה עם הצפנת TLS ב-Kubernetes

ב-Spanner Omni משתמשים ב-TLS 1.3 כדי להצפין את הנתונים שעוברים בין הלקוח לשרת, ובין שרתי Spanner Omni. ‫Spanner Omni מספק mTLS לאבטחה משופרת, שבה שני הצדדים מאמתים את האותנטיות אחד של השני לפני שהם מחליפים נתונים. אם אתם משתמשים בהצפנה, השרתים שלכם צריכים לתקשר באמצעות mTLS. אתם יכולים לבחור אם הלקוח והשרת ישתמשו גם ב-mTLS.

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

ודאו שאתם עומדים בדרישות הבאות:

  • יוצרים אשכול Kubernetes. ההגדרה תומכת ב-Google Kubernetes Engine (GKE) וב-Amazon Elastic Kubernetes Service (Amazon EKS). יכול להיות שתצטרכו להתאים אישית את ההגדרות כדי שהן יפעלו בסביבות אחרות.

  • מוודאים שלאשכול Kubernetes יש גישה לארטיפקט של Artifact Registry שמארח את הקונטיינר של Spanner Omni.

  • מתקינים ומגדירים את כלי שורת הפקודה kubectl ואת Helm.

  • אם הגדרתם את סביבת Kubernetes במכונות של פלטפורמת הווירטואליזציה vSphere, השביתו את הווירטואליזציה של מונה חותמות הזמן (TSC) על ידי הוספת monitor_control.virtual_rdtsc = FALSE לקובץ התצורה .vmx של המכונה הווירטואלית. כך אפשר לוודא ש-TrueTime פועל בצורה תקינה.

  • מוודאים שהסביבה עומדת בדרישות המערכת של Spanner Omni.

שלב 1: יוצרים את האישורים

צריך ליצור שלוש קבוצות של אישורים:

  • אישורי API: עוזרים להגן על שרת ה-API של Spanner Omni.

  • אישורי שרת: עוזרים להגן על התקשורת בין שרתים.

  • אישורי לקוח: משתמשי קצה או אפליקציות משתמשים בהם כדי לאמת את הזהות שלהם וליצור אמון עם שרתי Spanner Omni.

רשות אישורים (CA) מנפיקה את האישורים האלה. ב-Spanner Omni יש כלים ליצירת רשות אישורים בחתימה עצמית וכל שלושת סוגי האישורים.

מבצעים את השלבים הבאים באחד מהמחשבים. השלבים מבוססים על ההנחה שמרחב השמות הוא spanner-ns. צריך לשנות את זה למרחב השמות שבו אתם מתכוונים להשתמש בפריסה.

אתם יכולים ליצור את האישורים האלה בתחנת העבודה שלכם באמצעות ה-CLI של Spanner Omni.

1. יצירת רשויות אישורים

צריך ליצור שתי רשויות אישורים (CA) נפרדות כדי לבודד את התקשורת הפנימית בין השרתים מהתקשורת החיצונית של הלקוח ושל ה-API:

  • ‫Internal server CA (ca.crt): מנפיק אישורי שרת (server.crt) שמשמשים רק לתקשורת mTLS פנימית בין שרתי Spanner Omni.
  • ‫API ו-CA של לקוח (ca-api.crt): מנפיק את אישור שרת ה-API‏ (api.crt) ואת אישורי הלקוח mTLS (client.crt). לחלופין, אתם יכולים להשתמש ב-CA מהימן חיצוני או ב-CA של הארגון שלכם בשביל אישורי ה-API ואישורי הלקוח.
  1. יוצרים את ה-CA של השרת הפנימי לתקשורת בין שרתים:

    ./google/spanner/bin/spanner certificates create-ca --ca-certificate-directory=certs
    

    הפקודה הזו יוצרת את אישור ה-CA של השרת הפנימי (certs/ca.crt) וכותבת את המפתח הפרטי שלו ב-$HOME/.spanner/private-keys/ca.key.

  2. יוצרים רשות אישורים נפרדת לאישורי ה-API ואישורי הלקוח, ומעתיקים את אישור ה-CA שלה אל certs/ca-api.crt:

    ./google/spanner/bin/spanner certificates create-ca \
        --ca-certificate-directory=api-certs \
        --ca-private-key-directory=$HOME/.spanner/api-private-keys
    cp api-certs/ca.crt certs/ca-api.crt
    

    הפקודות האלה יוצרות את אישור ה-CA של הלקוח וה-API (api-certs/ca.crt, מועתק אל certs/ca-api.crt) וכותבות את המפתח הפרטי שלו אל $HOME/.spanner/api-private-keys/ca.key.

לגבות ולאבטח את $HOME/.spanner/private-keys וגם את $HOME/.spanner/api-private-keys. משתמשים שיש להם גישה למפתחות הפרטיים האלה יכולים לחתום על אישורים שרירותיים שהפריסה סומכת עליהם.

2. יצירת אישורי שרת

צריך ליצור שני סוגים של אישורי שרת:

  • אישור API: משתמשים באישור הזה כדי להצפין את התקשורת ממערכות שיוצרות אינטראקציה עם הפריסה.

  • אישור שרת Spanner: שרתי Spanner Omni משתמשים באישור הזה כדי להצפין את התקשורת ביניהם.

ההגדרה הזו מאפשרת לנהל את האישורים האלה בצורה גמישה. לדוגמה, אפשר להשתמש ברוטציית אישורים.

יצירת אישור השרת של Spanner

יוצרים את אישור השרת:

# Comma-separate names of the Spanner servers; wildcards are supported.
SERVER_NAMES=*.pod.NAMESPACE
./google/spanner/bin/spanner certificates create-server --hostnames=${SERVER_NAMES} --ca-certificate-directory certs --output-directory certs

הפקודה הזו יוצרת את server.crt ואת server.key בספרייה certs.

יצירת אישור ה-API

יוצרים את אישור ה-API באמצעות ה-CA של ה-API:

OMNI_ENDPOINT=spanner.NAMESPACE.svc
./google/spanner/bin/spanner certificates create-server \
    --filename-prefix=api \
    --hostnames=${OMNI_ENDPOINT} \
    --ca-certificate-directory=api-certs \
    --ca-private-key-directory=$HOME/.spanner/api-private-keys \
    --output-directory=certs

הפקודה הזו יוצרת את api.crt ואת api.key בספרייה certs. במקרה הצורך, השתמשו ברשות אישורים חיצונית מהימנה לאישורי ה-API.

3. יצירת אישורי לקוח

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

חותמים על אישורי לקוח באמצעות ה-API ורשות האישורים של הלקוח (api-certs/ca.crt, שתואמת ל-certs/ca-api.crt) וכוללים שם משתמש להרשאה. אל תחתמו על אישורי לקוח באמצעות ה-CA של השרת הפנימי (certs/ca.crt). בדוגמה הזו, השתמשו במשתמש admin, שהוא משתמש ברירת המחדל לכל מסד נתונים חדש. מידע נוסף זמין במאמר אימות והרשאה ב-Spanner Omni.

יוצרים את אישור הלקוח:

USERNAME=admin
./google/spanner/bin/spanner certificates create-client $USERNAME \
    --output-directory=clientcerts \
    --ca-certificate-directory=api-certs \
    --ca-private-key-directory=$HOME/.spanner/api-private-keys

הפקודה הזו יוצרת את client.crt ואת client.key בספרייה clientcerts. שולחים את הקבצים האלה לכל מכונה שמתחברת לפריסה.

אם אתם מתכננים להשתמש באישורי לקוח עם ספריית הלקוח של Java, אתם צריכים ליצור את מפתח האישור בפורמט PKCS#8. משתמשים בפקודה הבאה:

USERNAME=admin
./google/spanner/bin/spanner certificates create-client $USERNAME \
    --output-directory=clientcerts \
    --ca-certificate-directory=api-certs \
    --ca-private-key-directory=$HOME/.spanner/api-private-keys \
    --generate-pkcs8-key

4. יצירת קבוצת המפתחות של ה-wrapper

כדי להצפין מפתחות פנימיים, כמו מפתחות להצפנה ולחתימה של טוקנים, Spanner Omni משתמש בערכת מפתחות עוטפת של מפתח להצפנת מפתחות הצפנה (KEK) שמותקנת ב-/spanner/kms/wrapper_key בכל פוד של שרת.

כדי ליצור קובץ חדש של קבוצת מפתחות wrapper באמצעות spanner keys create-keyset, מריצים את הפקודה הבאה:

./google/spanner/bin/spanner keys create-keyset --output-file=kms/wrapper_key

כברירת מחדל, spanner keys create-keyset יוצר מפתח AES256_GCM. כדי ליצור סוג אחר של מפתח, משתמשים בדגל --key-template עם אחד מהערכים הבאים של סוג המפתח: AES256_GCM,‏ AES128_GCM,‏ AES256_GCM_RAW,‏ CHACHA20_POLY1305 או XCHACHA20_POLY1305.

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

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

  1. יוצרים את מרחב השמות:

    kubectl create namespace NAMESPACE
    
  2. מעבירים את אישורי ה-TLS לסוד:

    kubectl create secret generic tls-certs \
      --from-file=ca.crt="certs/ca.crt" \
      --from-file=ca-api.crt="certs/ca-api.crt" \
      --from-file=server.crt="certs/server.crt" \
      --from-file=server.key="certs/server.key" \
      --from-file=api.crt="certs/api.crt" \
      --from-file=api.key="certs/api.key" \
      -n NAMESPACE
    
  3. דוחפים את קבוצת מפתחות העטיפה לסוד (wrapper-key), שמוטמע ב-/spanner/kms בכל pod של שרת:

    kubectl create secret generic wrapper-key \
      --from-file=wrapper_key="kms/wrapper_key" \
      -n NAMESPACE
    
  4. יוצרים קובץ סיסמה שמכיל את הסיסמה של משתמש ברירת המחדל של admin, עם הרשאות מוגבלות (ניתן לקריאה רק על ידי הבעלים, הרשאות 600):

    printf '%s' 'PASSWORD' > admin_password.txt
    chmod 600 admin_password.txt
    

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

    • באורך של בין 8 ל-32 תווים.
    • לפחות אות גדולה אחת.
    • לפחות אות קטנה אחת.
    • לפחות מספר אחד.
    • לפחות תו מיוחד אחד.
  5. יוצרים סוד לסיסמת האדמין:

    kubectl create secret generic spanner-admin-password \
      --from-file=password=admin_password.txt \
      -n NAMESPACE
    

שלב 3: יצירת הפריסה עם הצפנת TLS

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

1. הכנת ההגדרות של Helm

במאמר יצירת הגדרה של תרשים Helm מוסבר איך ליצור את הגדרת הפריסה לסביבה שלכם.

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

# Enables TLS
global:
  insecureMode: false

# Enables client certificate authentication (mTLS)
deployment:
  enableClientCertificateAuthentication: true
  # Name of the secret containing the administrator password
  adminPasswordSecret: spanner-admin-password

2. יצירת הפריסה

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

kubectl create ns monitoring

helm upgrade --install spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni \
  --version VERSION \
  --set global.platform=gke \
  --set global.insecureMode=false \
  --set deployment.enableClientCertificateAuthentication=true \
  --set deployment.adminPasswordSecret=spanner-admin-password \
  --namespace NAMESPACE \
  --set monitoring.enabled=true

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

kubectl logs -n NAMESPACE -l app.kubernetes.io/component=bootstrap -f

הפלט מציין את ההתקדמות. בסיום, תופיע ההודעה "Deployment created successfully".

3. בדיקת הסטטוס של ה-pods

מריצים את הפקודה הבאה כדי לאמת את סטטוס ה-Pod:

kubectl get pods --watch --namespace NAMESPACE

כל הפודים נמצאים במצב READY.

4. עדכון האישור והפריסה עם פרטי מאזן העומסים

השלב הזה נדרש אם רוצים שלקוחות יתחברו מחוץ לאשכול Kubernetes.

# Get the service details
kubectl get service spanner -n NAMESPACE

# The EXTERNAL-IP:PORT is the API or deployment endpoint for your deployment.
# Update the API certificate with these details.
OMNI_ENDPOINT=EXTERNAL_IP,spanner.NAMESPACE.svc
./google/spanner/bin/spanner certificates update \
    --certificate-file=certs/api.crt \
    --certificate-key-file=certs/api.key \
    --hostnames=${OMNI_ENDPOINT} \
    --ca-certificate-directory=api-certs \
    --ca-private-key-directory=$HOME/.spanner/api-private-keys

# Update the secrets in Kubernetes
kubectl patch secret tls-certs -n NAMESPACE -p "{\"data\":{\"api.crt\":\"$(base64 -w 0 certs/api.crt)\"}}"

שלב 4: אינטראקציה עם Spanner Omni

אתם יכולים לקיים אינטראקציה עם פריסת Spanner Omni מכל VM באמצעות ה-CLI של Spanner Omni.

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

  • --client-certificate-directory=CLIENT_CERTIFICATE_DIRECTORY

  • --ca-certificate-file=API_CA_CERT_FILE_PATH

1. התחברות ל-Spanner Omni (אופציונלי)

מתחברים ל-Spanner Omni (השלב הזה אופציונלי אם משתמשים באישורי לקוח):

./google/spanner/bin/spanner auth login admin \
    --ca-certificate-file=certs/ca-api.crt \
    --deployment-endpoint=DEPLOYMENT_ENDPOINT

כשמופיעה בקשה, מזינים את הסיסמה שהוגדרה ב-admin_password.txt.

Successfully logged in as "admin"

2. יצירת מסד נתונים

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

./google/spanner/bin/spanner --deployment-endpoint=DEPLOYMENT_ENDPOINT databases create DATABASE_NAME --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts

3. פתיחת SQL Shell

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

./google/spanner/bin/spanner sql --database=DATABASE_NAME --deployment-endpoint=DEPLOYMENT_ENDPOINT --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts

4. יצירת טבלה והוספת נתונים

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

spanner> CREATE TABLE names (nameId INT64 NOT NULL, name String(100)) PRIMARY KEY (nameId);
Query OK, 0 rows affected (4.62 sec)

spanner> INSERT names (nameId, name) VALUES (1, "Jack");
Query OK, 1 rows affected (0.18 sec)

5. אימות הפריסה

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

./google/spanner/bin/spanner databases list --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts --deployment-endpoint=DEPLOYMENT_ENDPOINT

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

שם STATE VERSION_RETENTION_PERIOD EARLIEST_VERSION_TIME ENABLE_DROP_PROTECTION
DATABASE_NAME מוכן שעה 2025-02-07T12:25:30Z FALSE

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

./google/spanner/bin/spanner sql --database=DATABASE_NAME --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts --deployment-endpoint=DEPLOYMENT_ENDPOINT

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

SHOW TABLES;
SELECT * FROM names;

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

שלב 5: מעקב אחרי הפריסה

אם התקנתם את Spanner Omni באמצעות monitoring.enabled=true, ‏Prometheus אוסף מדדים. אתם יכולים להשתמש ב-Grafana כדי להציג את המדדים האלה באופן חזותי.

1. קבלת פרטי השירות

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

# Prometheus service details. Default port is 9090.
kubectl get service prometheus-service -n monitoring

# Grafana service details. Default port is 3000.
kubectl get service grafana -n monitoring

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