Mã hoá Cloud Functions bằng Khoá mã hoá do khách hàng quản lý (CMEK)

1. Giới thiệu

Tổng quan

Cloud Functions là một giải pháp điện toán gọn nhẹ dành cho nhà phát triển để tạo các hàm độc lập, có mục đích duy nhất, phản hồi các sự kiện trên đám mây mà không cần quản lý máy chủ hoặc môi trường thời gian chạy.

Bạn có thể sử dụng khoá mã hoá do khách hàng quản lý (CMEK) của Cloud Key Management Service để bảo vệ Cloud Functions và dữ liệu liên quan ở trạng thái tĩnh. Việc triển khai một hàm bằng CMEK sẽ bảo vệ dữ liệu được liên kết với hàm đó bằng cách sử dụng một khoá mã hoá mà bạn có toàn quyền kiểm soát. Loại mã hoá này cho phép bạn đáp ứng các yêu cầu tuân thủ ở một số ngành nhất định, chẳng hạn như dịch vụ tài chính. Vì khoá này thuộc quyền sở hữu của bạn và không do Google kiểm soát, nên không ai (kể cả bạn) có thể truy cập vào dữ liệu được bảo vệ bằng các khoá mã hoá này khi các khoá đó bị vô hiệu hoá hoặc bị huỷ.

Đối với Cloud Functions, CMEK sẽ mã hoá những nội dung sau:

  • Mã nguồn hàm được tải lên để triển khai và được Google lưu trữ trong Cloud Storage, dùng trong quá trình xây dựng.
  • Kết quả của quá trình xây dựng hàm, bao gồm cả hình ảnh vùng chứa được xây dựng từ mã nguồn hàm của bạn, mỗi thực thể của hàm được triển khai.
  • Dữ liệu ở trạng thái tĩnh cho các kênh truyền tải sự kiện nội bộ (chỉ thế hệ thứ 1).

Bạn có thể tìm thêm thông tin về dữ liệu được mã hoá trong tài liệu về CMEK của Cloud Function.

Sản phẩm bạn sẽ tạo ra

Lớp học lập trình này trình bày cách triển khai một Cloud Function (thế hệ thứ 1 hoặc thế hệ thứ 2) được mã hoá bằng CMEK. Lớp học lập trình này sử dụng một Cloud Function công khai (tức là một hàm không yêu cầu xác thực) cho mục đích minh hoạ. Bạn có thể gọi một hàm đã xác thực và bật CMEK giống như bất kỳ Cloud Function nào khác yêu cầu xác thực.

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

  • Cách tạo khoá CMEK trên một bộ khoá đối xứng hiện có
  • Cách tạo kho lưu trữ Artifact Registry
  • Cách định cấu hình CMEK trên một Cloud Function cho cả thế hệ thứ nhất và thế hệ thứ 2

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

Điều kiện tiên quyết

  • Bạn đã đăng nhập vào Cloud Console
  • Bạn đã triển khai một Cloud Function được kích hoạt bằng HTTP (để xác minh rằng bạn có các vai trò và API phù hợp đã được bật)

Kích hoạt Cloud Shell

  1. Trên Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Nếu đây là lần đầu tiên bạn khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian mô tả về Cloud Shell. Nếu bạn thấy màn hình trung gian, hãy nhấp vào Tiếp tục.

9c92662c6a846a5c.png

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài phút.

9f0e51b578fecce5.png

Máy ảo này được tải sẵn tất cả các công cụ phát triển cần thiết. Máy ảo này cung cấp một thư mục chính 5 GB liên tục và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và khả năng xác thực. Bạn có thể thực hiện hầu hết, nếu không phải là tất cả, công việc trong lớp học lập trình này bằng một trình duyệt.

Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án được đặt thành mã dự án của bạn.

  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list

Kết quả lệnh

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project

Kết quả lệnh

[core]
project = <PROJECT_ID>

Nếu không, bạn có thể đặt bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Kết quả lệnh

Updated property [core/project].

3. Tạo một bộ khoá và khoá mới cho Cloud Functions

Đảm bảo rằng Cloud KMS API đã được bật bằng cách chạy lệnh sau:

gcloud services enable cloudkms.googleapis.com

Trước tiên, hãy tạo các biến môi trường để chứa tên bộ khoá, tên khoá, khu vực và các biến khác được dùng trong lớp học lập trình này.

KEYRING_NAME="keyring-functions"
REGION="us-central1"
KEY_NAME="key-encrypted-function"
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER="$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')"
USER_EMAIL="$(gcloud config list account --format "value(core.account)")"

Tiếp theo, hãy tạo một bộ khoá là tài nguyên gốc cho các khoá và phiên bản khoá Cloud KMS.

gcloud kms keyrings create $KEYRING_NAME --location $REGION

Cuối cùng, giờ đây, bạn có thể tạo một khoá đối xứng trong bộ khoá mới của mình trong Cloud KMS.

gcloud kms keys create $KEY_NAME --keyring $KEYRING_NAME --location $REGION --purpose "encryption"

4. Tạo kho lưu trữ Artifact Registry ở định dạng Docker có bật CMEK

Trong phần này, bạn sẽ tạo một kho lưu trữ ở định dạng Docker trong Artifact Registry có bật CMEK. Khoá này sẽ là khoá được dùng để triển khai Cloud Function.

Trước tiên, bạn cần có tài khoản dịch vụ cho Artifact Registry. Bạn có thể tạo tài khoản này bằng cách chạy lệnh sau:

gcloud beta services identity create --service=artifactregistry.googleapis.com --project=$PROJECT_ID

Sử dụng lệnh sau để cấp vai trò IAM Trình mã hoá/Trình giải mã CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter) cho tài khoản dịch vụ Artifact Registry để có quyền đối với khoá:

gcloud kms keys add-iam-policy-binding \
  $KEY_NAME --location $REGION --keyring=$KEYRING_NAME \
  --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter

Và cấp vai trò cho nguyên tắc sẽ tạo kho lưu trữ trong Artifact Registry, chẳng hạn như tài khoản đang hoạt động hiện tại của bạn. Bạn có thể xác minh tài khoản đang hoạt động hiện tại bằng cách chạy gcloud auth list.

gcloud kms keys add-iam-policy-binding \
       $KEY_NAME --location $REGION --keyring=$KEYRING_NAME \
       --member user:$USER_EMAIL \
       --role roles/cloudkms.cryptoKeyEncrypterDecrypter

Giờ đây, bạn có thể tạo một kho lưu trữ ở định dạng Docker có bật CMEK.

Lưu ý: rằng vùng phải là cùng một vùng với khoá CMEK.

REPO_NAME=my-cmek-encrypted-repo 

KEY_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/keyRings/"$KEYRING_NAME"/cryptoKeys/"$KEY_NAME" 

gcloud artifacts repositories create $REPO_NAME \
    --repository-format=docker \
    --location=$REGION \
    --kms-key=$KEY_FULLPATH \
    --async

Bạn có thể xem kho lưu trữ Artifact Registry mới bằng cách chạy lệnh sau:

gcloud artifacts repositories describe $REPO_NAME --location=$REGION

5. Cấp quyền truy cập cho Tài khoản dịch vụ vào khoá (thế hệ thứ 2)

Phần này trình bày cách tạo tài khoản dịch vụ cho các hàm thế hệ thứ 2. Nếu bạn đang tạo một hàm thế hệ thứ 1, vui lòng chuyển sang phần tiếp theo.

Bạn phải cấp quyền truy cập cho một số tác nhân dịch vụ vào khoá bằng cách cấp vai trò IAM Trình mã hoá/Trình giải mã CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Các tác nhân dịch vụ này được dùng để lấy quyền truy cập vào mã nguồn được lưu trữ trong Cloud Storage, lưu trữ hình ảnh hàm trong một kho lưu trữ được bảo vệ bằng CMEK trong Artifact Registry và để triển khai một Cloud Function được mã hoá bằng CMEK.

Các bước dành cho Cloud Functions thế hệ thứ 2

  1. Cấp quyền truy cập cho tác nhân dịch vụ Cloud Run vào khoá:
CLOUDRUN_SA=service-$PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$CLOUDRUN_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Cấp quyền truy cập cho tác nhân dịch vụ Eventarc vào khoá:
EVENTARC_SA=service-$PROJECT_NUMBER@gcp-sa-eventarc.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$EVENTARC_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Cấp quyền truy cập cho tác nhân dịch vụ Artifact Registry vào khoá:
AR_SA=service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$AR_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Cấp quyền truy cập cho các tác nhân dịch vụ Cloud Storage vào khoá:
STORAGE_SA=service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$STORAGE_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

Trong phần tiếp theo, bạn sẽ thấy cách tạo và triển khai một hàm được mã hoá bằng CMEK.

6. Cấp quyền truy cập cho Tài khoản dịch vụ vào khoá (thế hệ thứ 1)

Phần này trình bày cách tạo tài khoản dịch vụ cho các hàm thế hệ thứ 1. Nếu bạn đã tạo tài khoản dịch vụ cho một hàm thế hệ thứ 2, vui lòng chuyển sang phần tiếp theo.

Bạn phải cấp quyền truy cập cho một số tác nhân dịch vụ vào khoá bằng cách cấp vai trò IAM Trình mã hoá/Trình giải mã CryptoKey (roles/cloudkms.cryptoKeyEncrypterDecrypter). Các tác nhân dịch vụ này được dùng để lấy quyền truy cập vào mã nguồn được lưu trữ trong Cloud Storage, lưu trữ hình ảnh hàm trong một kho lưu trữ được bảo vệ bằng CMEK trong Artifact Registry và để triển khai một Cloud Function được mã hoá bằng CMEK.

Các bước dành cho Cloud Functions thế hệ thứ 1

  1. Cấp quyền truy cập cho tác nhân dịch vụ Cloud Functions vào khoá:
FUNCTION_SA=service-$PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$FUNCTION_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Cấp quyền truy cập cho tác nhân dịch vụ Artifact Registry vào khoá:
AR_SA=service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$AR_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Cấp quyền truy cập cho các tác nhân dịch vụ Cloud Storage vào khoá:
STORAGE_SA=service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$STORAGE_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

Trong phần tiếp theo, bạn sẽ thấy cách tạo và triển khai một hàm được mã hoá bằng CMEK.

7. Tạo một Cloud Function được mã hoá bằng CMEK (thế hệ thứ 2)

Phần này trình bày cách tạo các hàm thế hệ thứ 2. Bạn có thể chuyển sang phần tiếp theo để xem hướng dẫn về thế hệ thứ 1.

Giờ đây, bạn đã định cấu hình một kho lưu trữ Artifact Registry có bật CMEK và đã cấp quyền truy cập cho Cloud Functions vào khoá của mình, bạn có thể triển khai một hàm được mã hoá bằng khoá CMEK.

Các bước dành cho Cloud Functions thế hệ thứ 2:

Tạo mã nguồn cho hàm

Mặc dù lớp học lập trình này sử dụng Node.js, nhưng bạn có thể sử dụng bất kỳ thời gian chạy nào được hỗ trợ.

Trước tiên, hãy tạo một thư mục và chuyển đến thư mục đó.

mkdir ~/cmek-function-2ndgen && cd $_

Sau đó, hãy tạo tệp package.json.

touch package.json

echo '{
  "dependencies": {
    "@google-cloud/functions-framework": "^2.1.0"
  }
}
' > package.json

Tiếp theo, hãy tạo tệp nguồn index.js.

touch index.js

echo 'const functions = require("@google-cloud/functions-framework");

functions.http("helloWorld", (req, res) => {
 res.send(`Hello ${req.query.name || req.body.name || "World"}!`);
});' > index.js

Triển khai Cloud Function thế hệ thứ 2 bằng tính năng mã hoá CMEK

Lưu ý: Ví dụ dưới đây cho biết cách triển khai một hàm bằng các nguồn từ thư mục hiện tại. Đảm bảo bạn đang ở cùng thư mục với mã nguồn cho hàm của mình.

FUNCTION_NAME=protect-me-cmek-2ndgen
ENTRY_POINT=helloWorld

REPO_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/repositories/$REPO_NAME

gcloud beta functions deploy $FUNCTION_NAME  \
--gen2 \
--region $REGION \
--kms-key $KEY_FULLPATH \
--docker-repository $REPO_FULLPATH \
--source . \
--trigger-http \
--allow-unauthenticated \
--runtime nodejs16 \
--entry-point $ENTRY_POINT

Bạn có thể xem khoá CMEK từ kết quả đầu ra bằng cách chạy lệnh sau

gcloud functions describe $FUNCTION_NAME –region $REGION | grep kmsKeyName

Kiểm thử hàm thế hệ thứ 2

Bạn có thể kiểm thử hàm bằng cách sử dụng lệnh curl:

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --region $REGION --format='get(serviceConfig.uri)')"

curl $FUNCTION_URL

kết quả là:

Hello World!

Miễn là khoá mã hoá được bật, hàm sẽ trả về trạng thái thành công cho phương thức gọi. Tuy nhiên, sau khi khoá mã hoá bị vô hiệu hoá, phương thức gọi sẽ nhận được lỗi.

Trong phần tiếp theo, bạn sẽ thấy điều gì xảy ra khi bạn gọi Hàm sau khi khoá đã bị vô hiệu hoá.

8. Tạo một Cloud Function được mã hoá bằng CMEK (thế hệ thứ 1)

Phần này trình bày cách tạo các hàm thế hệ thứ 1. Nếu bạn đã tạo một hàm thế hệ thứ 2, vui lòng chuyển sang phần tiếp theo.

Giờ đây, bạn đã định cấu hình một kho lưu trữ Artifact Registry có bật CMEK và đã cấp quyền truy cập cho Cloud Functions vào khoá của mình, bạn có thể triển khai một hàm được mã hoá bằng khoá CMEK.

Các bước dành cho Cloud Functions thế hệ thứ 1:

Tạo mã nguồn cho hàm thế hệ thứ 1

Mặc dù lớp học lập trình này sử dụng Node.js, nhưng bạn có thể sử dụng bất kỳ thời gian chạy nào được hỗ trợ.

Trước tiên, hãy tạo một thư mục và chuyển đến thư mục đó.

mkdir ~/cmek-function-1stgen && cd $_

Tiếp theo, hãy tạo tệp package.json.

touch package.json

echo '{
    "name": "function-cmek-codelab",
    "version": "0.0.1"
}' > package.json

Sau đó, hãy tạo tệp nguồn index.js.

touch index.js

echo "exports.helloWorld = (req, res) => {
    let message = req.query.message || req.body.message || 'Hello World!';
    res.status(200).send(message);
};" > index.js

Triển khai Cloud Function thế hệ thứ 1 bằng tính năng mã hoá CMEK

Lưu ý: Ví dụ dưới đây cho biết cách triển khai một hàm bằng các nguồn từ thư mục hiện tại. Đảm bảo bạn đang ở cùng thư mục với mã nguồn cho hàm của mình.

FUNCTION_NAME=protect-me-cmek-1stgen
ENTRY_POINT=helloWorld

REPO_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/repositories/$REPO_NAME

gcloud functions deploy $FUNCTION_NAME  \
--region $REGION \
--kms-key $KEY_FULLPATH \
--docker-repository $REPO_FULLPATH \
--source . \
--trigger-http \
--allow-unauthenticated \
--runtime nodejs16 \
--entry-point $ENTRY_POINT

Bạn có thể xem khoá CMEK từ kết quả đầu ra bằng cách chạy lệnh sau

gcloud functions describe $FUNCTION_NAME –region $REGION | grep kmsKeyName

Kiểm thử hàm thế hệ thứ 1

Bạn có thể kiểm thử hàm bằng cách sử dụng lệnh curl:

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --region $REGION --format='get(httpsTrigger.url)')"

curl $FUNCTION_URL

kết quả là:

Hello World!

Miễn là khoá mã hoá được bật, hàm sẽ trả về trạng thái thành công cho phương thức gọi. Tuy nhiên, sau khi khoá mã hoá bị vô hiệu hoá, phương thức gọi sẽ nhận được lỗi.

Trong phần tiếp theo, bạn sẽ thấy điều gì xảy ra khi bạn gọi Hàm sau khi khoá đã bị vô hiệu hoá.

9. Gọi một Cloud Function được mã hoá bằng CMEK mà khoá mã hoá đã bị vô hiệu hoá

Trong phần cuối cùng này, bạn sẽ làm mất hiệu lực khoá và gọi lại Hàm để xem lỗi kết quả.

Vô hiệu hoá khoá mã hoá

Bạn có thể chạy lệnh này để vô hiệu hoá khoá. Vì lớp học lập trình này chỉ tạo một phiên bản của khoá, nên bạn sẽ vô hiệu hoá phiên bản 1.

gcloud kms keys versions disable 1 \
    --key=$KEY_NAME \
    --keyring=$KEYRING_NAME \
    --location=$REGION

và bạn sẽ thấy thông tin kết quả:

algorithm: GOOGLE_SYMMETRIC_ENCRYPTION
createTime: '2023-04-11T03:30:49.111832653Z'
generateTime: '2023-04-11T03:30:49.111832653Z'
name: projects/dogfood-gcf-saraford/locations/us-central1/keyRings/myKeyRing/cryptoKeys/encrypted-function/cryptoKeyVersions/1
protectionLevel: SOFTWARE
state: DISABLED

Gọi Hàm bằng một khoá đã bị vô hiệu hoá

Bây giờ, hãy curl lại hàm.

curl $FUNCTION_URL

và lần này bạn sẽ không nhận được phản hồi Hello World.

Trong nhật ký cho Cloud Function, bạn sẽ thấy

User's CMEK key has been disabled. CMEK key: projects/<PROJECT-NAME>/locations/us-central1/keyRings/myKeyRing/cryptoKeys/encrypted-function

Cố gắng xem tài nguyên khi khoá CMEK bị vô hiệu hoá

Trong phần này, bạn sẽ thấy các tài nguyên sau đây trở nên không dùng được khi khoá CMEK bị vô hiệu hoá:

  • Mã nguồn hàm
  • Hình ảnh vùng chứa được xây dựng từ mã nguồn của bạn

Ví dụ: việc truy cập vào thẻ Nguồn cho Cloud Function sẽ cho thấy lỗi trong khi tìm nạp tệp lưu trữ. Bạn sẽ nhận được lỗi tương tự nếu cố gắng xem tệp .zip chứa mã nguồn trực tiếp trong Cloud Storage.

ac3307bb05d30e19.png

Ngoài ra, bạn sẽ không có quyền truy cập để sử dụng hình ảnh vùng chứa cho hàm từ Artifact Registry. Ví dụ: nếu cố gắng triển khai hình ảnh vùng chứa đó lên Cloud Run, bạn sẽ nhận được lỗi cho biết không tìm thấy hình ảnh.

Vui lòng tham khảo tài liệu về CMEK Functions để biết danh sách đầy đủ các tài nguyên được mã hoá.

10. Xin chúc mừng

Xin chúc mừng, bạn đã hoàn tất lớp học lập trình!

Nội dung đã đề cập

  • Cách tạo khoá CMEK trên một bộ khoá đối xứng hiện có
  • Cách tạo kho lưu trữ Artifact Registry
  • Cách định cấu hình CMEK trên một Cloud Function

Để biết thêm thông tin

Bạn có thể tìm thêm thông tin về Cloud Functions và CMEK trong các đường liên kết sau: