Private Service Connect – Sử dụng phần phụ trợ PSC để truy cập vào các API của Google theo khu vực

1. Giới thiệu

Private Service Connect là một tính năng của mạng Google Cloud, cho phép người dùng truy cập vào các dịch vụ của nhà sản xuất. Trong đó có khả năng kết nối với các API của Google thông qua một điểm cuối riêng tư được lưu trữ trong VPC của người dùng(thường là người tiêu dùng).

Ngoài ra, bạn có thể sử dụng các Phụ trợ PSC cùng với các bộ cân bằng tải proxy của Google Cloud để trỏ đến các API của Google theo khu vực cụ thể. Việc sử dụng PSC Backends giúp người tiêu dùng kiểm soát chặt chẽ hơn, chẳng hạn như:

  • Chọn những dịch vụ API của Google có sẵn bằng cách sử dụng Bản đồ URL
  • Khả năng ghi nhận chuyên sâu hơn
  • Tích hợp Cloud Armor
  • URL tùy chỉnh
  • Quản lý lưu lượng truy cập nâng cao

Bạn có thể xem danh sách các dịch vụ hiện có và API theo khu vực của các dịch vụ đó tại đây.

Trong lớp học lập trình này, bạn sẽ tạo một PSC Backend trỏ đến Cloud KMS API theo khu vực và kiểm thử khả năng kết nối với API đó.

Kiến thức bạn sẽ học được

  • Tạo một bộ khoá và khoá Cloud Key Management Service (KMS).
  • Tạo một Bộ cân bằng tải ứng dụng nội bộ có một Phần phụ trợ PSC trỏ đến một API theo khu vực của Cloud KMS
  • Tạo một Bản ghi A và Vùng riêng tư được quản lý Cloud DNS.
  • Truy cập vào Cloud KMS theo khu vực

Bạn cần có

  • Một dự án trên Google Cloud có quyền "Chủ sở hữu" hoặc quyền "Người chỉnh sửa" đầy đủ.

2. Cấu trúc liên kết của lớp học lập trình

1a18ae253213e215.png

Một VPC của người dùng sẽ được tạo với một mạng con trong khu vực europe-west9 để lưu trữ một VM, quy tắc chuyển tiếp Internal Regional Application Load Balancer, PSC Backend và một mạng con chỉ dành cho proxy để sử dụng với trình cân bằng tải. Chúng ta sẽ tạo một Bộ khoá và Khoá trong Hệ thống quản lý khoá (KMS) trên đám mây ở khu vực Châu Âu (phía tây). Sau đó, chúng ta sẽ tạo trình cân bằng tải và PSC Backend để phân giải thành API KMS theo khu vực ở europe-west9.

3. Thiết lập và yêu cầu

Thiết lập môi trường theo tốc độ của riêng bạn

  1. Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không sử dụng. Bạn luôn có thể cập nhật thông tin này.
  • Mã dự án là mã duy nhất trên tất cả các dự án trên Google Cloud và không thể thay đổi (bạn không thể thay đổi mã này sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là PROJECT_ID). Nếu không thích mã nhận dạng được tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Hoặc bạn có thể thử tên người dùng của riêng mình để xem tên đó có được chấp nhận hay không. Bạn không thể thay đổi tên này sau bước này và tên này sẽ tồn tại trong suốt thời gian của dự án.
  • Để bạn nắm được thông tin, có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả 3 giá trị này trong tài liệu.
  1. Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên/API trên đám mây. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Để tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này, bạn có thể xoá các tài nguyên đã tạo hoặc xoá dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.

Khởi động Cloud Shell

Mặc dù có thể vận hành Google Cloud từ xa trên máy tính xách tay, nhưng trong lớp học lập trình này, bạn sẽ sử dụng Google Cloud Shell, một môi trường dòng lệnh chạy trên Cloud.

Trên Bảng điều khiển Google Cloud, hãy nhấp vào biểu tượng Cloud Shell trên thanh công cụ ở trên cùng bên phải:

55efc1aaa7a4d3ad.png

Quá trình này chỉ mất vài phút để cung cấp và kết nối với môi trường. Khi quá trình này kết thúc, bạn sẽ thấy như sau:

7ffe5cbb04455448.png

Máy ảo này được trang bị tất cả các công cụ phát triển mà bạn cần. Nó cung cấp một thư mục chính có dung lượng 5 GB và chạy trên Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện mọi thao tác trong lớp học lập trình này trong trình duyệt. Bạn không cần cài đặt bất cứ thứ gì.

4. Trước khi bắt đầu

Bật API

Trong Cloud Shell, hãy đảm bảo rằng bạn đã thiết lập mã dự án

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

Bật tất cả các dịch vụ cần thiết

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. Tạo mạng VPC, mạng con và quy tắc tường lửa

Tạo mạng VPC

Từ 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

Tạo mạng con

Từ 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

Trong phòng thí nghiệm này, bạn sẽ tạo một trình cân bằng tải nội bộ L7 theo khu vực để trỏ đến các phần phụ trợ API theo khu vực. Bộ cân bằng tải này là bộ cân bằng tải proxy, do đó, bạn cần tạo một "mạng con proxy" dành riêng cho bộ cân bằng tải để thực hiện proxy. Bạn có thể xem thêm thông tin về mạng con chỉ dành cho proxy tại đây.

Từ 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

Tạo quy tắc tường lửa

Trong lớp học này, bạn sẽ sử dụng IAP để kết nối với các phiên bản mà bạn tạo. Nếu không muốn sử dụng IAP, bạn có thể bỏ qua bước này và thay vào đó, hãy thêm địa chỉ IP công khai vào phiên bản này, đồng thời tạo một quy tắc tường lửa cho phép lưu lượng truy cập đến trên cổng TCP 22 từ 0.0.0.0/0.

Để cho phép IAP kết nối với các phiên bản máy ảo, hãy tạo một quy tắc tường lửa có:

  • Áp dụng cho tất cả các phiên bản máy ảo mà bạn muốn có thể truy cập bằng IAP.
  • Cho phép lưu lượng truy cập vào từ dải IP 35.235.240.0/20. Dải này chứa tất cả địa chỉ IP mà IAP sử dụng để chuyển tiếp TCP.

Từ Cloud Shell

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

6. Tạo Cloud NAT

Bạn phải tạo một NAT đám mây để tải các bản phân phối gói Linux xuống.

Tạo Cloud Router

Từ Cloud Shell

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

Tạo Cloud NAT

Từ 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. Tạo bộ khoá và khoá quản lý khoá

Từ Cloud Shell

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

Từ Cloud Shell

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

Trong Cloud Shell, hãy xác nhận rằng bạn đã tạo thành công chuỗi khoá và khoá ở khu vực europe-west.

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

KẾT QUẢ DỰ KIẾN

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

Ghi lại tên đường dẫn đầy đủ được cung cấp cho các khoá vì bạn sẽ sử dụng tên này để kết nối sau.

8. Tạo máy ảo khách và kết nối với KMS API

Tiếp theo, bạn sẽ tạo một máy ảo khách, SSH vào máy ảo đó và kiểm thử độ phân giải của API KMS toàn cầu. Thử nghiệm này thể hiện lựa chọn mặc định cho độ phân giải API toàn cầu của Google.

Từ 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" 

Tiếp theo, bạn cần cập nhật tài khoản dịch vụ Compute mặc định để có quyền truy cập vào khoá KMS mà bạn đã tạo. Tài khoản dịch vụ điện toán mặc định sẽ có dạng <Project_Number> -compute@developer.gserviceaccount.com. Để lấy Số dự án, hãy chạy lệnh sau từ Cloud Shell và sao chép số trên dòng cuối cùng của kết quả trả về.

 gcloud projects describe $PROJECT_ID

Cập nhật tài khoản dịch vụ Compute mặc định để có quyền truy cập vào khoá KMS mà bạn đã tạo.

Từ 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

Tạo một cửa sổ dòng lệnh Cloud Shell khác bằng cách nhấp vào + (ảnh chụp màn hình bên dưới)

a36edc967333315a.png

Trong thẻ 2, hãy tạo đường hầm thông qua IAP để SSH vào client-vm. Xin lưu ý rằng các biến môi trường sẽ không được chuyển và bạn cần thêm mã dự án vào lệnh bên dưới.

Từ 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

Kết nối với KMS API toàn cầu bằng tên khoá KMS mà bạn đã ghi lại trước đó.

Từ thẻ 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'

KẾT QUẢ DỰ KIẾN

*   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

Kiểm tra xem DNS phân giải điểm cuối KMS ở đâu.

Từ tab2, client-vm

dig cloudkms.googleapis.com

KẾT QUẢ DỰ KIẾN

 <<>> 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

Từ tab2, client-vm

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

KẾT QUẢ DỰ KIẾN

<<>> 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

Hành vi mặc định của các API của Google là sử dụng điểm cuối dịch vụ API toàn cầu. Điểm cuối này sẽ phân giải thành một danh sách các IP công khai. Lệnh dig cho cloudkms.googleapis.com cho thấy điều này. (Lưu ý: Địa chỉ IP mà bạn thấy có thể là một địa chỉ IP ngoài khác. Đây là hành vi bình thường của các API Google.)

Bằng cách sử dụng các điểm cuối API của Google theo khu vực với PSC, bạn có thể đáp ứng các yêu cầu theo khu vực đối với lưu lượng truy cập API cũng như thay đổi độ phân giải từ công khai sang riêng tư. Lệnh dig đến cloudkms.europe-west9.rep.googleapis.com cho thấy rằng tại thời điểm này, việc phân giải đến điểm cuối API KSM theo khu vực vẫn là công khai.

Trong các phần sau, chúng ta sẽ di chuyển từ việc sử dụng điểm cuối API KMS toàn cầu sang điểm cuối theo khu vực và thay đổi độ phân giải thành riêng tư bằng cách sử dụng PSC Backends.

9. Tạo NEG PSC và Trình cân bằng tải

Đối với phần tiếp theo, hãy chuyển về thẻ đầu tiên trong Cloud Shell.

Bạn sẽ tạo một Trình cân bằng tải HTTP(S) nội bộ có một nhóm điểm cuối mạng(NEG) trỏ đến điểm cuối KMS theo khu vực ở Châu Âu làm dịch vụ phụ trợ. Quy tắc chuyển tiếp của trình cân bằng tải đóng vai trò là điểm cuối Kết nối dịch vụ riêng tư(PSC).

Tạo Nhóm thiết bị đầu cuối mạng (NEG) có loại Private Service Connect và dịch vụ đích europe-west9-cloudkms.example.com

Từ 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}

Tạo dịch vụ phụ trợ cho trình cân bằng tải.

Từ 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 \

Thêm NEG vào dịch vụ phụ trợ.

Từ Cloud Shell

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

Tạo bản đồ URL cho trình cân bằng tải.

Từ Cloud Shell

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

Tạo Path Matcher cho URL tuỳ chỉnh mà điểm cuối sẽ sử dụng.

Từ Cloud Shell

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

Tạo quy tắc máy chủ lưu trữ cho URL tuỳ chỉnh europe-west9-cloudkms.example.com.

Từ 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

Tạo proxy HTTPS mục tiêu cho trình cân bằng tải. Bạn cần tạo một tài nguyên chứng chỉ SSL theo khu vực. Vui lòng xem các bước tạo chứng chỉ tự ký tại đây. Chúng ta sẽ tạo một chứng chỉ tự ký bằng openssl và dùng chứng chỉ đó để tạo một tài nguyên chứng chỉ theo khu vực trên GCP. Proxy https đích sẽ sử dụng chứng chỉ này.

Từ 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}

Tạo quy tắc chuyển tiếp cho bộ cân bằng tải sẽ đóng vai trò là Điểm cuối Private Service Connect. Địa chỉ IP cho quy tắc chuyển tiếp phải thuộc một mạng con theo khu vực trong VPC nằm cùng khu vực với điểm cuối API mà bạn đang truy cập.

Từ 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. Cấu hình DNS

Trong phần này, bạn sẽ tạo một vùng DNS riêng tư cho example.com và một bản ghi A trỏ đến quy tắc chuyển tiếp mà chúng ta đã tạo ở bước cuối cùng.

Tạo vùng riêng tư DNS được quản lý.

Từ 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}

Tạo bản ghi A cho europe-west9-cloudkms.example.com.

Từ 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. Kết nối với API KMS theo khu vực thông qua PSC

Chuyển về client-vm trong thẻ 2 để chạy tcpdump nhằm xem tất cả thông tin chi tiết về kết nối và kiểm tra các kết nối đến điểm cuối KMS theo khu vực thông qua PSC Backend.

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

Mở thẻ thứ 3 trong Cloud Shell và SSH vào 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)"

KẾT QUẢ DỰ KIẾN cho lệnh 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


Kiểm tra lại cửa sổ 2 và xem thông tin tcpdump. Bạn sẽ thấy rằng bạn có thể truy cập vào điểm cuối theo khu vực của Cloud KMS thông qua điểm cuối PSC mà bạn đã tạo và điểm cuối theo khu vực europe-west9 sẽ phân giải riêng tư thành vùng DNS đám mây được quản lý mà bạn đã tạo. Các dòng liên quan trong đầu ra tcpdump được làm nổi bật ở trên và được tham chiếu ở bên dưới:

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) (Máy chủ siêu dữ liệu GCP phản hồi bằng bản ghi A: 10.0.0.100 – IP của bộ cân bằng tải. Quá trình phân giải DNS đang hoạt động bình thường. europe-west9-cloudkms.example.com phân giải thành 10.0.0.100 (đây là IP của bộ cân bằng tải)

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 (Thao tác này cho thấy quá trình bắt tay TCP cho kết nối HTTPS với IP của bộ cân bằng tải)

Trong thẻ 3, client-vm

dig europe-west9-cloudkms.example.com

KẾT QUẢ DỰ KIẾN

; <<>> 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

Đầu ra của lệnh dig cho thấy URL tuỳ chỉnh mà chúng ta đã tạo cho europe-west9-cloudkms.example.com phân giải chính xác thành 10.0.0.100, đây là địa chỉ IP của bộ cân bằng tải nội bộ. Các yêu cầu đến europe-west9-cloudkms.example.com sẽ được chuyển đến bộ cân bằng tải nội bộ của bạn, sau đó bộ cân bằng tải này sẽ chuyển tiếp các yêu cầu đó đến điểm cuối theo khu vực của KMS thông qua Private Service Connect.

Giờ đây, bạn có thể đóng cả hai thẻ SSH cho client-vm.

12. Các bước dọn dẹp

Xoá các thành phần trong phòng thí nghiệm khỏi một thiết bị đầu cuối 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. Xin chúc mừng!

Chúc mừng bạn đã hoàn thành lớp học lập trình này.