Private Service Connect – שימוש בקצוות עורפי של PSC כדי לגשת לממשקי Google API אזוריים

1. מבוא

‫Private Service Connect היא יכולת של רשתות Google Cloud שמאפשרת לצרכנים לגשת לשירותים של ספקי תוכן. האפשרות הזו כוללת את היכולת להתחבר לממשקי Google API דרך נקודת קצה פרטית שמארחת ב-VPC של המשתמש(בדרך כלל צרכן).

בנוסף, אפשר להשתמש ב-PSC Backends בשילוב עם מאזני עומסים של פרוקסי ב-Google Cloud כדי להפנות אל Google APIs ספציפיים לאזור. שימוש ב-PSC Backends מספק אמצעי בקרה מפורטים יותר בצד הלקוח, כמו:

  • בחירה של שירותי Google API שזמינים באמצעות מיפוי כתובות URL
  • ניראות מעמיקה יותר
  • שילוב עם Cloud Armor
  • כתובות URL מותאמות אישית
  • ניהול מתקדם של תעבורת נתונים

כאן אפשר למצוא את רשימת השירותים הזמינים ואת ממשקי ה-API האזוריים שלהם.

ב-codelab הזה, תיצרו קצה עורפי של PSC שמפנה אל Cloud KMS API האזורי ותבדקו את הקישוריות אל ה-API הזה.

מה תלמדו

  • יוצרים אוסף מפתחות ומפתח של Cloud Key Management Service ‏ (KMS).
  • יצירת מאזן עומסים פנימי של אפליקציות עם קצה עורפי מסוג PSC שמפנה אל Cloud KMS regional API
  • יצירה של תחום פרטי מנוהל ורשומת A ב-Cloud DNS.
  • גישה ל-Cloud KMS האזורי

מה תצטרכו

  • פרויקט ב-Google Cloud עם הרשאות 'בעלים' או הרשאות 'עריכה' מלאות.

2. Codelab Topology

1a18ae253213e215.png

ייווצר VPC של צרכן עם רשת משנה אחת באזור europe-west9 לאירוח VM, כלל ההעברה של מאזן העומסים האזורי הפנימי של אפליקציות, הקצה העורפי של PSC ורשת משנה אחת של שרת proxy לשימוש עם מאזן העומסים. ניצור אוסף מפתחות ומפתח ב-Cloud Key Management System ‏ (KMS) באזור europe-west. לאחר מכן ניצור את מאזן העומסים ואת הקצה העורפי של PSC כדי לפתור את בעיית ה-API האזורי של KMS באזור europe-west9.

3. הגדרה ודרישות

הגדרת סביבה בקצב אישי

  1. נכנסים ל-מסוף Google Cloud ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. אם עדיין אין לכם חשבון Gmail או Google Workspace, אתם צריכים ליצור חשבון.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • שם הפרויקט הוא השם המוצג של הפרויקט הזה למשתתפים. זו מחרוזת תווים שלא נמצאת בשימוש ב-Google APIs. תמיד אפשר לעדכן את המיקום.
  • מזהה הפרויקט הוא ייחודי לכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו אחרי שהוא מוגדר. מסוף Cloud יוצר באופן אוטומטי מחרוזת ייחודית, ובדרך כלל לא צריך לדעת מה היא. ברוב ה-Codelabs, תצטרכו להפנות למזהה הפרויקט (בדרך כלל מסומן כ-PROJECT_ID). אם אתם לא אוהבים את המזהה שנוצר, אתם יכולים ליצור מזהה אקראי אחר. אפשר גם לנסות שם משתמש משלכם ולבדוק אם הוא זמין. אי אפשר לשנות את ההגדרה הזו אחרי השלב הזה, והיא תישאר לאורך הפרויקט.
  • לידיעתכם, יש ערך שלישי, מספר פרויקט, שחלק מממשקי ה-API משתמשים בו. במאמרי העזרה מפורט מידע נוסף על שלושת הערכים האלה.
  1. בשלב הבא, תצטרכו להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבי Cloud או בממשקי API של Cloud. השלמת ה-codelab הזה לא תעלה לכם הרבה, אם בכלל. כדי להשבית את המשאבים ולמנוע חיובים נוספים אחרי שתסיימו את המדריך הזה, תוכלו למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים לתוכנית תקופת ניסיון בחינם בשווי 300$.

מפעילים את Cloud Shell

אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-codelab הזה תשתמשו ב-Google Cloud Shell, סביבת שורת פקודה שפועלת בענן.

ב-מסוף Google Cloud, לוחצים על סמל Cloud Shell בסרגל הכלים שבפינה הימנית העליונה:

55efc1aaa7a4d3ad.png

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

7ffe5cbb04455448.png

המכונה הווירטואלית הזו כוללת את כל הכלים שדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את כל העבודה ב-codelab הזה בדפדפן. לא צריך להתקין שום דבר.

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

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

ב-Cloud Shell, מוודאים שמזהה הפרויקט מוגדר

gcloud config list project
gcloud config set project <project-id>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=europe-west9
export ZONE=europe-west9-a
echo $PROJECT_ID
echo $REGION
echo $ZONE

הפעלת כל השירותים הנדרשים

gcloud services enable compute.googleapis.com
gcloud services enable servicedirectory.googleapis.com
gcloud services enable dns.googleapis.com
gcloud services enable cloudkms.googleapis.com

5. יצירת רשת VPC, רשתות משנה וכללי חומת אש

יצירת רשת VPC

מ-Cloud Shell

# Set environment variables

export VPC_NAME="consumer-vpc"
export SUBNET_NAME="consumer-subnet-1"

# Create VPC network

gcloud compute networks create ${VPC_NAME} \
    --subnet-mode=custom \
    --bgp-routing-mode=regional

יצירת רשתות משנה

מ-Cloud Shell

gcloud compute networks subnets create ${SUBNET_NAME} \
    --network=${VPC_NAME} \
    --region=${REGION} \
    --range=10.0.0.0/24 \
    --enable-private-ip-google-access

בשיעור ה-Lab הזה תיצרו מאזן עומסים פנימי אזורי ברמה 7 כדי להפנות לשרתי בק-אנד אזוריים של API. מאזן העומסים הזה הוא מאזן עומסים של שרת proxy, ולכן צריך ליצור 'רשת משנה של שרת proxy' שמוקדשת למאזן העומסים כדי לבצע את ה-proxy. מידע נוסף על רשת משנה של שרת proxy בלבד זמין כאן.

מ-Cloud Shell

gcloud compute networks subnets create eu-west9-proxy-subnet \
--network=${VPC_NAME} \
--region=${REGION} \
--range=10.100.100.0/24 \
--purpose=REGIONAL_MANAGED_PROXY \
--role=ACTIVE

יצירת כללים לחומת האש

ב-Lab הזה תשתמשו ב-IAP כדי להתחבר למופעים שתיצרו. אם אתם לא רוצים להשתמש ב-IAP, אתם יכולים לדלג על השלב הזה, ובמקום זאת להוסיף כתובות IP ציבוריות למכונה וליצור כלל חומת אש שמאפשר כניסה ביציאת TCP מספר 22 מ-0.0.0.0/0.

כדי לאפשר ל-IAP להתחבר למכונות הווירטואליות, צריך ליצור כלל חומת אש ש:

  • רלוונטי לכל מכונות ה-VM שרוצים לגשת אליהן באמצעות IAP.
  • מאפשר תנועה נכנסת מטווח כתובות ה-IP‏ 35.235.240.0/20. הטווח הזה מכיל את כל כתובות ה-IP שמשמשות את IAP להעברת TCP.

מ-Cloud Shell

gcloud compute firewall-rules create allow-ssh-iap \
    --network=${VPC_NAME} \
--allow tcp:22 \
--source-ranges=35.235.240.0/20

6. יצירת Cloud NAT

צריך ליצור Cloud NAT כדי להוריד הפצות של חבילות Linux.

יצירת Cloud Router

מ-Cloud Shell

gcloud compute routers create crnat \
    --network=${VPC_NAME} \
    --region=${REGION}

יצירת Cloud NAT

מ-Cloud Shell

gcloud compute routers nats create europe-nat \
    --router=crnat \
    --auto-allocate-nat-external-ips \
    --nat-all-subnet-ip-ranges \
    --enable-logging \
    --region=${REGION}

7. יצירה של אוסף מפתחות ומפתח לניהול מפתחות

מ-Cloud Shell

gcloud kms keyrings create europe-kr \
    --location ${REGION}

מ-Cloud Shell

gcloud kms keys create europe-key \
    --location ${REGION} \
    --keyring europe-kr \
    --purpose encryption

ב-Cloud Shell, מוודאים שצרור המפתחות והמפתח נוצרו בהצלחה באזור europe-west.

gcloud kms keys list \
    --location ${REGION} \
    --keyring europe-kr

התוצאה הצפויה

NAME: projects/<project-id>/locations/europe-west9/keyRings/europe-kr/cryptoKeys/europe-key
PURPOSE: ENCRYPT_DECRYPT
ALGORITHM: GOOGLE_SYMMETRIC_ENCRYPTION
PROTECTION_LEVEL: SOFTWARE
LABELS: 
PRIMARY_ID: 1
PRIMARY_STATE: ENABLED

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

8. יצירת מכונה וירטואלית של לקוח וחיבור ל-KMS API

בשלב הבא יוצרים מכונה וירטואלית של לקוח, מתחברים למכונה הווירטואלית באמצעות SSH ובודקים את הרזולוציה של ה-API הגלובלי של KMS. הבדיקה הזו מייצגת את אפשרות ברירת המחדל לפתרון בעיות ב-Google APIs גלובליים.

מ-Cloud Shell

#Create the startup script

touch startup.sh

#Open the startup.sh file using a text editor of your choice (e.g., nano, vim, gedit, etc.)

nano startup.sh 

#Paste the following script content into the startup.sh file

#! /bin/bash 
sudo apt-get update 
sudo apt-get install dnsutils -y 
sudo apt-get install tcpdump -y

#Save the changes you made to the startup.sh file
#Use the chmod command to make the script executable

chmod +x startup.sh

#Create the VM instance

gcloud compute instances create client-vm \
    --network="${VPC_NAME}" \
    --subnet="${SUBNET_NAME}" \
    --zone="europe-west9-a" \
    --machine-type="e2-medium" \
    --no-address \
    --scopes="https://www.googleapis.com/auth/cloud-platform" \
    --image-family="debian-12" \
    --image-project="debian-cloud" \
    --metadata-from-file="startup-script=./startup.sh" 

בשלב הבא, תצטרכו לעדכן את חשבון השירות שמוגדר כברירת המחדל של Compute כדי לקבל גישה למפתח ה-KMS שיצרתם. חשבון השירות שמוגדר כברירת מחדל ל-Compute יהיה בפורמט <Project_Number> -compute@developer.gserviceaccount.com. כדי לקבל את מספר הפרויקט, מריצים את הפקודה הבאה מ-Cloud Shell ומעתיקים את המספר בשורה האחרונה של התוצאות שמוחזרות.

 gcloud projects describe $PROJECT_ID

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

מ-Cloud Shell

gcloud kms keys add-iam-policy-binding europe-key \
    --location $REGION \
    --keyring europe-kr \
    --member serviceAccount:<project_number>-compute@developer.gserviceaccount.com \
    --role roles/cloudkms.admin

לוחצים על + (צילום מסך בהמשך) כדי ליצור טרמינל נוסף של Cloud Shell.

a36edc967333315a.png

בכרטיסייה 2, יוצרים מנהרה דרך IAP כדי להתחבר ב-SSH למכונה client-vm. שימו לב שמשתני הסביבה לא יועברו, ותצטרכו להוסיף את מזהה הפרויקט לפקודה שבהמשך.

מ-Cloud Shell

# Set the environment variable

export PROJECT_ID=$(gcloud config get-value project)

# ssh into the client-vm

gcloud beta compute ssh --zone europe-west9-a "client-vm" \
--tunnel-through-iap \
--project $PROJECT_ID

מתחברים ל-KMS API הגלובלי באמצעות השם של מפתח ה-KMS שרשמתם קודם.

בכרטיסייה 2, client-vm

# Store the access token in a variable

TOKEN=$(gcloud auth print-access-token)

# Run the full command with maximum verbosity
curl -v \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
'https://cloudkms.googleapis.com/v1/projects/<project-id>/locations/europe-west9/keyRings/europe-kr/cryptoKeys/europe-key'

התוצאה הצפויה

*   Trying 216.58.214.74:443...
* Connected to cloudkms.googleapis.com (216.58.214.74) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=upload.video.google.com
*  start date: Aug 26 07:12:45 2024 GMT
*  expire date: Nov 18 07:12:44 2024 GMT
*  subjectAltName: host "cloudkms.googleapis.com" matched cert's "*.googleapis.com"
*  issuer: C=US; O=Google Trust Services; CN=WR2
*  SSL certificate verify ok.
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /v1/projects/<project-id>/locations/europe-west9/keyRings/europe-kr/cryptoKeys/europe-key]
* h2h3 [:scheme: https]
* h2h3 [:authority: cloudkms.googleapis.com]
* h2h3 [user-agent: curl/7.88.1]
* h2h3 [accept: */*]
* h2h3 [authorization: Bearer dsnkjfdnvjfd
* h2h3 [content-type: application/json]
* Using Stream ID: 1 (easy handle 0x55ed8bb7ece0)
> GET /v1/projects/<project-id>/locations/europe-west9/keyRings/europe-kr/cryptoKeys/europe-key HTTP/2
> Host: cloudkms.googleapis.com
> user-agent: curl/7.88.1
> accept: */*
> authorization: Bearer dsnkjfdnvjfd
> content-type: application/json
>
< HTTP/2 200
< content-type: application/json; charset=UTF-8
< vary: X-Origin
< vary: Referer
< vary: Origin,Accept-Encoding
< date: Tue, 24 Sep 2024 18:25:42 GMT
< server: ESF
< cache-control: private
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< x-content-type-options: nosniff
< accept-ranges: none
<
{
  "name": "projects/<project-id>/locations/europe-west9/keyRings/europe-kr/cryptoKeys/europe-key",
  "primary": {
    "name": "projects/<project-id>/locations/europe-west9/keyRings/europe-kr/cryptoKeys/europe-key/cryptoKeyVersions/1",
    "state": "ENABLED",
    "createTime": "2024-09-24T17:56:01.905156045Z",
    "protectionLevel": "SOFTWARE",
    "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION",
    "generateTime": "2024-09-24T17:56:01.905156045Z"
  },
  "purpose": "ENCRYPT_DECRYPT",
  "createTime": "2024-09-24T17:56:01.905156045Z",
  "versionTemplate": {
    "protectionLevel": "SOFTWARE",
    "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION"
  },
  "destroyScheduledDuration": "2592000s"
}
* Connection #0 to host cloudkms.googleapis.com left intact

בודקים איפה DNS פותר את נקודת הקצה של KMS.

מ-tab2, client-vm

dig cloudkms.googleapis.com

התוצאה הצפויה

 <<>> DiG 9.18.28-1~deb12u2-Debian <<>> cloudkms.googleapis.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62617
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;cloudkms.googleapis.com.       IN      A

;; ANSWER SECTION:
cloudkms.googleapis.com. 300    IN      A       142.250.74.234
cloudkms.googleapis.com. 300    IN      A       142.250.75.234
cloudkms.googleapis.com. 300    IN      A       216.58.214.170
cloudkms.googleapis.com. 300    IN      A       172.217.20.170
cloudkms.googleapis.com. 300    IN      A       172.217.20.202
cloudkms.googleapis.com. 300    IN      A       216.58.215.42
cloudkms.googleapis.com. 300    IN      A       216.58.213.74
cloudkms.googleapis.com. 300    IN      A       142.250.179.74
cloudkms.googleapis.com. 300    IN      A       142.250.179.106
cloudkms.googleapis.com. 300    IN      A       142.250.178.138
cloudkms.googleapis.com. 300    IN      A       142.250.201.170
cloudkms.googleapis.com. 300    IN      A       172.217.18.202
cloudkms.googleapis.com. 300    IN      A       216.58.214.74

;; Query time: 4 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Wed Oct 23 19:58:58 UTC 2024
;; MSG SIZE  rcvd: 260

מ-tab2, client-vm

dig cloudkms.europe-west9.rep.googleapis.com

התוצאה הצפויה

<<>> DiG 9.18.28-1~deb12u2-Debian <<>> cloudkms.europe-west9.rep.googleapis.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2736
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;cloudkms.europe-west9.rep.googleapis.com. IN A

;; ANSWER SECTION:
cloudkms.europe-west9.rep.googleapis.com. 3043 IN A 34.1.65.232

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Wed Oct 23 20:00:04 UTC 2024
;; MSG SIZE  rcvd: 85

התנהגות ברירת המחדל של Google APIs היא שימוש בנקודת הקצה של שירות ה-API הגלובלי. נקודת הקצה הזו תומר לרשימה של כתובות IP ציבוריות. הפלט של הפקודה dig עבור cloudkms.googleapis.com מראה את זה. (הערה: יכול להיות שכתובת ה-IP שמוצגת לכם היא כתובת IP חיצונית אחרת. זוהי התנהגות רגילה של Google APIs.)

באמצעות נקודות קצה אזוריות של Google API עם PSC, אתם יכולים לעמוד בדרישות אזוריות לתעבורת API וגם לשנות את ההגדרה מציבורית לפרטית. הפלט של הפקודה dig ל-cloudkms.europe-west9.rep.googleapis.com מראה שבשלב הזה, הרזולוציה של נקודת הקצה האזורית של KSM API עדיין ציבורית.

בקטעים הבאים נסביר איך עוברים משימוש בנקודת קצה ל-API הגלובלית של KMS לנקודת הקצה האזורית, ואיך משנים את ההגדרה לפרטית באמצעות PSC Backends.

9. יצירת PSC NEG ומאזן עומסים

כדי לעבור לקטע הבא, חוזרים לכרטיסייה הראשונה ב-Cloud Shell.

תצרו מאזן עומסים פנימי מסוג HTTP(S) עם קבוצה של נקודות קצה ברשת(NEG) שמפנה לנקודת הקצה האזורית של KMS באירופה כשירות עורפי. כלל ההעברה של מאזן העומסים פועל כנקודת קצה (endpoint) של Private Service Connect ‏(PSC).

יוצרים את קבוצת נקודות הקצה ברשת (NEG) עם סוג Private Service Connect ושירות יעד europe-west9-cloudkms.example.com

מ-Cloud Shell

#Set the necessary variables

NEG_NAME="l7psc-kms-neg"
PSC_TARGET="cloudkms.europe-west9.rep.googleapis.com"

#Create the Private Service Connect NEG

gcloud compute network-endpoint-groups create ${NEG_NAME} \
    --project=${PROJECT_ID} \
    --region=${REGION} \
    --network-endpoint-type=PRIVATE_SERVICE_CONNECT \
    --psc-target-service=${PSC_TARGET}

# Verify the NEG creation

gcloud compute network-endpoint-groups describe ${NEG_NAME} \
    --project=${PROJECT_ID} \
    --region=${REGION}

יוצרים את שירות הקצה העורפי למאזן העומסים.

מ-Cloud Shell

# 1. Set the necessary variables

BACKEND_SERVICE_NAME="l7-psc-kms"

# 2. Create the backend service

gcloud compute backend-services create $BACKEND_SERVICE_NAME \
  --load-balancing-scheme=INTERNAL_MANAGED \
  --protocol=HTTPS \
  --region=$REGION \

מוסיפים את ה-NEG לשירות הקצה העורפי.

מ-Cloud Shell

gcloud compute backend-services add-backend $BACKEND_SERVICE_NAME \
  --network-endpoint-group=${NEG_NAME} \
  --region=$REGION

יוצרים את מפת URL למאזן העומסים.

מ-Cloud Shell

gcloud compute url-maps create l7-psc-url-map \
  --default-service=l7-psc-kms \
  --region=$REGION

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

מ-Cloud Shell

gcloud compute url-maps add-path-matcher l7-psc-url-map \
 --path-matcher-name=example \
 --default-service=l7-psc-kms \
 --region=$REGION

יוצרים את כלל המארח עבור כתובת ה-URL המותאמת אישית europe-west9-cloudkms.example.com.

מ-Cloud Shell

gcloud compute url-maps add-host-rule l7-psc-url-map \
--hosts=europe-west9-cloudkms.example.com \
--path-matcher-name=example \
--region=$REGION

יוצרים את שרת ה-HTTPS Proxy של היעד עבור מאזן העומסים. כדי לעשות זאת, צריך ליצור משאב אישור SSL אזורי. כאן מוסבר איך ליצור אישור עם חתימה עצמית. אנחנו ניצור אישור עם חתימה עצמית באמצעות openssl ונשתמש בו כדי ליצור משאב אישור אזורי ב-GCP. שרת ה-proxy של יעד ה-HTTPS ישתמש באישור הזה.

מ-Cloud Shell

# Set environment variables

export CERT_NAME="my-ssl-cert"

# Generate a private key

openssl genrsa -out private.key 2048

#  Create a configuration file for the CSR

cat > csr_config.cnf << EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[dn]
CN = example.com
O = My Organization
C = US

[req_ext]
subjectAltName = @alt_names

[alt_names]
DNS.1 = example.com
DNS.2 = *.example.com
EOF

# Create a CSR using the configuration

openssl req -new -key private.key -out server.csr -config csr_config.cnf

# Create a self-signed certificate using the CSR

openssl x509 -req -days 365 -in server.csr -signkey private.key -out server.crt \
    -extfile csr_config.cnf -extensions req_ext

# Verify the certificate

openssl x509 -in server.crt -text -noout

#Create a regional SSL certificate resource 

gcloud compute ssl-certificates create ${CERT_NAME} \
    --region=${REGION} \
    --certificate=server.crt \
    --private-key=private.key

#Create the target HTTPS proxy for the load balancer 

gcloud compute target-https-proxies create psc-http-proxy \
    --region=${REGION} \
    --url-map=l7-psc-url-map \
    --ssl-certificates=${CERT_NAME}

יוצרים את כלל ההעברה למאזן העומסים שיפעל כנקודת קצה של Private Service Connect. כתובת ה-IP של כלל ההעברה צריכה להיות שייכת לרשת משנה אזורית ב-VPC שנמצאת באותו אזור של נקודת קצה ל-API שאליה ניגשים.

מ-Cloud Shell

# Set environment variables

export PROXY_NAME="psc-http-proxy"

# Create the forwarding rule

gcloud compute forwarding-rules create kms-lb-rule \
    --project=${PROJECT_ID} \
    --region=${REGION} \
    --load-balancing-scheme=INTERNAL_MANAGED \
    --network=${VPC_NAME} \
    --subnet=${SUBNET_NAME} \
    --target-https-proxy=${PROXY_NAME} \
    --target-https-proxy-region=${REGION} \
    --address=10.0.0.100 \
    --ports=443

10. הגדרת DNS

בקטע הזה יוצרים תחום DNS פרטי לדומיין example.com, ורשומת A שמפנה לכלל ההעברה שיצרנו בשלב הקודם.

יוצרים תחום פרטי מנוהל ב-DNS.

מ-Cloud Shell

# Set environment variables

export LB_RULE_NAME="kms-lb-rule"
export DNS_ZONE_NAME="example-com-private-zone"

# Create the private DNS zone

gcloud dns managed-zones create ${DNS_ZONE_NAME} \
    --dns-name="example.com." \
    --description="Private DNS zone for example.com" \
    --visibility=private \
    --networks=${VPC_NAME}

יוצרים רשומת A עבור europe-west9-cloudkms.example.com.

מ-Cloud Shell

gcloud dns record-sets transaction start \
   --zone=${DNS_ZONE_NAME}

gcloud dns record-sets transaction add 10.0.0.100 \
   --name=europe-west9-cloudkms.example.com \
   --ttl=300 \
   --type=A \
   --zone=${DNS_ZONE_NAME}

gcloud dns record-sets transaction execute \
   --zone=${DNS_ZONE_NAME}

11. חיבור ל-Regional KMS API דרך PSC

חוזרים אל client-vm בכרטיסייה 2 כדי להריץ את tcpdump, לראות את כל פרטי החיבור ולבדוק את החיבורים לנקודת הקצה האזורית של KMS דרך העורף של PSC.

sudo tcpdump -i any net 10.0.0.100 or port 53 -n

פותחים כרטיסייה שלישית ב-Cloud Shell ומבצעים SSH אל client-vm.

# Set environment variables

export PROJECT_ID=$(gcloud config get-value project)
export KMS_HOSTNAME="europe-west9-cloudkms.example.com"
export KEY_RING="europe-kr"
export KEY_NAME="europe-key"
export REGION="europe-west9"

# Command to access the specific key

curl -k "https://${KMS_HOSTNAME}/v1/projects/${PROJECT_ID}/locations/${REGION}/keyRings/${KEY_RING}/cryptoKeys/${KEY_NAME}" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)"

התוצאה הצפויה של פקודת curl + TCPDUMP

{
  "name": "projects/<project-id>/locations/europe-west9/keyRings/europe-kr/cryptoKeys/europe-key",
  "primary": {
    "name": "projects/<project-id>/locations/europe-west9/keyRings/europe-kr/cryptoKeys/europe-key/cryptoKeyVersions/1",
    "state": "ENABLED",
    "createTime": "2024-10-10T18:50:24.357027036Z",
    "protectionLevel": "SOFTWARE",
    "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION",
    "generateTime": "2024-10-10T18:50:24.357027036Z"
  },
  "purpose": "ENCRYPT_DECRYPT",
  "createTime": "2024-10-10T18:50:24.357027036Z",
  "versionTemplate": {
    "protectionLevel": "SOFTWARE",
    "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION"
  },
  "destroyScheduledDuration": "2592000s"
}


Tcpdump output

listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
18:13:51.220209 lo    In  IP 127.0.0.1.48873 > 127.0.0.53.53: 2086+ [1au] A? europe-west9-cloudkms.example.com. (62)
18:13:51.220230 lo    In  IP 127.0.0.1.48873 > 127.0.0.53.53: 24619+ [1au] AAAA? europe-west9-cloudkms.example.com. (62)
18:13:51.220669 ens4  Out IP 10.0.0.2.52121 > 169.254.169.254.53: 8885+ [1au] A? europe-west9-cloudkms.example.com. (62)
18:13:51.220784 ens4  Out IP 10.0.0.2.53041 > 169.254.169.254.53: 57748+ [1au] AAAA? europe-west9-cloudkms.example.com. (62)
18:13:51.229638 ens4  In  IP 169.254.169.254.53 > 10.0.0.2.52121: 8885 1/0/1 A 10.0.0.100 (78)
18:13:51.229945 lo    In  IP 127.0.0.53.53 > 127.0.0.1.48873: 2086 1/0/1 A 10.0.0.100 (78)
18:13:51.230068 ens4  In  IP 169.254.169.254.53 > 10.0.0.2.53041: 57748 0/1/1 (155)
18:13:51.230203 lo    In  IP 127.0.0.53.53 > 127.0.0.1.48873: 24619 0/1/1 (155)
18:13:51.230390 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [S], seq 1606150798, win 65320, options [mss 1420,sackOK,TS val 4135800856 ecr 0,nop,wscale 7], length 0
18:13:51.232565 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [S.], seq 1041507402, ack 1606150799, win 65535, options [mss 1420,sackOK,TS val 2276748382 ecr 4135800856,nop,wscale 8], length 0
18:13:51.232583 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [.], ack 1, win 511, options [nop,nop,TS val 4135800859 ecr 2276748382], length 0
18:13:51.235494 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [P.], seq 1:518, ack 1, win 511, options [nop,nop,TS val 4135800862 ecr 2276748382], length 517
18:13:51.236571 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [.], ack 518, win 267, options [nop,nop,TS val 2276748387 ecr 4135800862], length 0
18:13:51.239119 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [P.], seq 1:1356, ack 518, win 267, options [nop,nop,TS val 2276748389 ecr 4135800862], length 1355
18:13:51.239140 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [.], ack 1356, win 501, options [nop,nop,TS val 4135800865 ecr 2276748389], length 0
18:13:51.240978 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [P.], seq 518:598, ack 1356, win 501, options [nop,nop,TS val 4135800867 ecr 2276748389], length 80
18:13:51.241266 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [P.], seq 598:684, ack 1356, win 501, options [nop,nop,TS val 4135800867 ecr 2276748389], length 86
18:13:51.241366 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [P.], seq 684:1646, ack 1356, win 501, options [nop,nop,TS val 4135800867 ecr 2276748389], length 962
18:13:51.242370 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [.], ack 684, win 267, options [nop,nop,TS val 2276748392 ecr 4135800867], length 0
18:13:51.242619 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [P.], seq 1356:1433, ack 1646, win 278, options [nop,nop,TS val 2276748393 ecr 4135800867], length 77
18:13:51.242730 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [P.], seq 1646:1677, ack 1433, win 501, options [nop,nop,TS val 4135800869 ecr 2276748393], length 31
18:13:51.248724 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [.], ack 1677, win 278, options [nop,nop,TS val 2276748399 ecr 4135800869], length 0
18:13:51.296676 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [P.], seq 1433:2357, ack 1677, win 278, options [nop,nop,TS val 2276748447 ecr 4135800869], length 924
18:13:51.297223 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [F.], seq 1677, ack 2357, win 501, options [nop,nop,TS val 4135800923 ecr 2276748447], length 0
18:13:51.298304 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [P.], seq 2357:2381, ack 1678, win 278, options [nop,nop,TS val 2276748448 ecr 4135800923], length 24
18:13:51.298305 ens4  In  IP 10.0.0.100.443 > 10.0.0.2.59474: Flags [F.], seq 2381, ack 1678, win 278, options [nop,nop,TS val 2276748448 ecr 4135800923], length 0
18:13:51.298336 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [R], seq 1606152476, win 0, length 0
18:13:51.298343 ens4  Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [R], seq 1606152476, win 0, length 0


חוזרים לחלון של כרטיסייה 2 ובודקים את המידע של tcpdump. תוכלו לראות שהייתה לכם גישה לנקודת הקצה האזורית של Cloud KMS דרך נקודת הקצה של PSC שיצרתם, ושהנקודה האזורית europe-west9 מתורגמת באופן פרטי לתחום ה-DNS המנוהל של Cloud DNS שיצרתם. השורות הרלוונטיות בפלט של tcpdump מודגשות למעלה ומופיעות בהמשך:

18:13:51.229638 ens4 In IP 169.254.169.254.53 > 10.0.0.2.52121: 8885 1/0/1 A 10.0.0.100 (78) (שרת המטא-נתונים של GCP מגיב עם רשומת ה-A: ‏ 10.0.0.100 – כתובת ה-IP של איזון העומסים. פענוח ה-DNS פועל בצורה תקינה. הכתובת europe-west9-cloudkms.example.com מנותבת לכתובת 10.0.0.100, שהיא כתובת ה-IP של מאזן העומסים)

18:13:51.230390 ens4 Out IP 10.0.0.2.59474 > 10.0.0.100.443: Flags [S], seq 1606150798, win 65320, options [mss 1420,sackOK,TS val 4135800856 ecr 0,nop,wscale 7], length 0 (מוצג כאן לחיצת היד של TCP לחיבור HTTPS לכתובת ה-IP של מאזן העומסים)

בכרטיסייה 3, client-vm

dig europe-west9-cloudkms.example.com

התוצאה הצפויה

; <<>> DiG 9.18.28-1~deb12u2-Debian <<>> europe-west9-cloudkms.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7008
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;europe-west9-cloudkms.example.com. IN  A

;; ANSWER SECTION:
europe-west9-cloudkms.example.com. 300 IN A     10.0.0.100

;; Query time: 12 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Fri Oct 11 20:03:00 UTC 2024
;; MSG SIZE  rcvd: 78

הפלט של פקודת ה-dig מראה שכתובת ה-URL המותאמת אישית שיצרנו עבור europe-west9-cloudkms.example.com מפורשת בצורה נכונה ל-10.0.0.100, שהיא כתובת ה-IP של מאזן העומסים הפנימי. בקשות אל europe-west9-cloudkms.example.com יופנו אל מאזן העומסים הפנימי שלכם, שמעביר אותן אל נקודת הקצה האזורית של KMS דרך Private Service Connect.

עכשיו אפשר לסגור את שתי הכרטיסיות של SSH למכונה הווירטואלית של הלקוח.

12. שלבי הניקוי

מחיקת רכיבי מעבדה ממסוף Cloud Shell יחיד

# Set environment variables

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")
export REGION=europe-west9
export ZONE=europe-west9-a
export VPC_NAME="consumer-vpc"
export SUBNET_NAME="consumer-subnet-1"
export NEG_NAME="l7psc-kms-neg"
export BACKEND_SERVICE_NAME="l7-psc-kms"
export CERT_NAME="my-ssl-cert"
export PROXY_NAME="psc-http-proxy"
export LB_RULE_NAME="kms-lb-rule"
export DNS_ZONE_NAME="example-com-private-zone"

#  Delete DNS records and zone

gcloud dns record-sets delete europe-west9-cloudkms.example.com. \
    --zone=${DNS_ZONE_NAME} --type=A --quiet
gcloud dns managed-zones delete ${DNS_ZONE_NAME} --quiet

#  Delete Load Balancer components

gcloud compute forwarding-rules delete ${LB_RULE_NAME} --region=${REGION} --quiet
gcloud compute target-https-proxies delete ${PROXY_NAME} --region=${REGION} --quiet
gcloud compute url-maps delete l7-psc-url-map --region=${REGION} --quiet
gcloud compute backend-services delete ${BACKEND_SERVICE_NAME} --region=${REGION} --quiet
gcloud compute network-endpoint-groups delete ${NEG_NAME} --region=${REGION} --quiet

# Delete SSL certificate

gcloud compute ssl-certificates delete ${CERT_NAME} --region=${REGION} --quiet

#  Delete VM instance

gcloud compute instances delete client-vm --zone=${ZONE} --quiet

#  Delete firewall rules

gcloud compute firewall-rules delete allow-ssh-iap --quiet

# Delete Cloud NAT and router

gcloud compute routers nats delete europe-nat --router=crnat --region=${REGION} --quiet
gcloud compute routers delete crnat --region=${REGION} --quiet

#  Delete subnets and VPC

gcloud compute networks subnets delete ${SUBNET_NAME} --region=${REGION} --quiet
gcloud compute networks subnets delete eu-west9-proxy-subnet --region=${REGION} --quiet
gcloud compute networks delete ${VPC_NAME} --quiet

# Schedule KMS key for deletion and provide instructions for keyring deletion

gcloud kms keys remove-iam-policy-binding europe-key \
    --location ${REGION} \
    --keyring europe-kr \
    --member serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com \
    --role roles/cloudkms.admin

gcloud kms keys versions destroy 1 --location=${REGION} --keyring=europe-kr --key=europe-key

#  Disable services (optional, only if you want to completely disable these APIs)

gcloud services disable compute.googleapis.com --force
gcloud services disable servicedirectory.googleapis.com --force
gcloud services disable dns.googleapis.com --force
gcloud services disable cloudkms.googleapis.com --force

#  Clean up local files

rm -f private.key server.csr server.crt csr_config.cnf startup.sh

13. מעולה!

כל הכבוד, סיימתם את ה-Codelab.