使用客戶自行管理的加密金鑰 (CMEK) 加密 Cloud Functions

1. 簡介

總覽

Cloud Functions 是簡易運算解決方案,可讓開發人員建立獨立的單一用途函式來回應雲端事件,而不需要管理伺服器或執行階段環境。

您可以使用 Cloud Key Management Service 客戶管理的加密金鑰 (CMEK) 保護 Cloud Functions 和相關靜態資料。使用 CMEK 部署函式時,系統會使用您完全控管的加密金鑰,保護與函式相關聯的資料。這種加密方式可讓您滿足金融服務等特定產業的法規遵循要求。由於金鑰由您擁有,並非由 Google 控管,因此在金鑰停用或刪除後,任何人 (包括您) 都無法存取這些加密金鑰所保護的資料。

在 Cloud Functions 中,CMEK 會加密下列項目:

  • 上傳並部署在 Cloud Storage 中的函式原始碼,供 Google 用於建構程序。
  • 函式建構程序的結果,包括從函式原始碼建構的容器映像檔,以及每個已部署函式的例項。
  • 內部事件傳輸管道的靜止資料 (僅限第 1 代)。

如要進一步瞭解哪些資料會遭到加密,請參閱 Cloud Function CMEK 說明文件

建構項目

本程式碼研究室說明如何部署使用 CMEK 加密的 Cloud Functions (第 1 或第 2 代)。本程式碼研究室會使用公開 Cloud 函式 (即不需要驗證的函式) 進行示範。您可以像呼叫需要驗證的其他 Cloud Function 一樣,呼叫已驗證的 CMEK 支援函式。

課程內容

  • 如何在現有的對稱金鑰環上建立 CMEK 金鑰
  • 如何建立 Artifact Registry 存放區
  • 如何在第 1 代和第 2 代 Cloud Functions 上設定 CMEK

2. 設定和需求

必要條件

  • 您已登入 Cloud Console
  • 您先前已部署 HTTP 觸發的 Cloud Function (以便驗證您已啟用適當的角色和 API)

啟用 Cloud Shell

  1. 在 Cloud 控制台中,按一下「啟用 Cloud Shell」 圖示 853e55310c205094.png

55efc1aaa7a4d3ad.png

如果這是您首次啟動 Cloud Shell,系統會顯示中介畫面,說明 Cloud Shell 的功能。如果您看到中介畫面,請按一下「繼續」

9c92662c6a846a5c.png

佈建並連線至 Cloud Shell 的作業只需幾分鐘的時間。

9f0e51b578fecce5.png

這個虛擬機器會載入所有必要的開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,可大幅提升網路效能和驗證功能。您可以在瀏覽器中完成本程式碼研究室的大部分工作,甚至是全部工作。

連線至 Cloud Shell 後,您應會發現自己通過驗證,且專案已設為您的專案 ID。

  1. 在 Cloud Shell 中執行下列指令,確認您已通過驗證:
gcloud auth list

指令輸出

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. 在 Cloud Shell 中執行下列指令,確認 gcloud 指令知道您的專案:
gcloud config list project

指令輸出

[core]
project = <PROJECT_ID>

如果尚未設定,請使用下列指令進行設定:

gcloud config set project <PROJECT_ID>

指令輸出

Updated property [core/project].

3. 為 Cloud Functions 建立新的金鑰環和金鑰

執行下列指令,確認 Cloud KMS API 已啟用:

gcloud services enable cloudkms.googleapis.com

首先,建立環境變數,用於儲存金鑰環名稱、金鑰名稱、區域和本程式碼研究室中使用的其他變數。

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

接著,建立 金鑰環,這是 Cloud KMS 金鑰和金鑰版本的根資源。

gcloud kms keyrings create $KEYRING_NAME --location $REGION

最後,您現在可以在 Cloud KMS 的新金鑰環中建立對稱金鑰

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

4. 建立啟用 CMEK 且支援 CMEK 的 Artifact Registry 存放區

在本節中,您將在 已啟用 CMEK 的 Artifact Registry 中建立 Docker 格式的存放區。這組金鑰與用於部署 Cloud 函式的金鑰相同。

首先,您必須擁有 Artifact Registry 的服務帳戶。您可以執行下列指令來建立這個檔案:

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

執行下列指令,將 CryptoKey Encrypter/Decrypter IAM 角色 (roles/cloudkms.cryptoKeyEncrypterDecrypter) 授予 Artifact Registry 服務帳戶,以取得金鑰的存取權:

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

並將角色授予在原件登錄中建立存放區的使用者,例如您目前的有效帳戶。您可以執行 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

現在,您可以建立 Docker 格式的存放區,並啟用 CMEK 功能。

注意:區域必須與 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

您可以執行下列指令,查看新的 Artifact Registry 存放區:

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

5. 授予服務帳戶存取金鑰 (第 2 代) 的權限

本節將說明如何為第 2 代函式建立服務帳戶。如果您要建立第 1 代函式,請繼續閱讀下一節。

您必須授予多個服務代理權限,以便存取金鑰,方法是授予 CryptoKey Encrypter/Decrypter IAM 角色 (roles/cloudkms.cryptoKeyEncrypterDecrypter)。這些服務代理可用於取得存放於 Cloud Storage 的原始碼存取權、在 Artifact Registry 中以 CMEK 保護的存放區儲存函式圖像,以及部署以 CMEK 加密的 Cloud Function。

第 2 代函式的步驟

  1. 將金鑰存取權授予 Cloud Run 服務代理:
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. 授予 Eventarc 服務代理金鑰存取權:
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. 授予 Artifact Registry 服務代理的權限,以便存取金鑰:
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. 授予 Cloud Storage 服務代理存取金鑰的權限:
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

在下一節中,您將瞭解如何建立及部署 CMEK 加密函式。

6. 將金鑰的存取權授予服務帳戶 (第 1 代)

本節將說明如何為第 1 代函式建立服務帳戶。如果您先前已為第 2 代函式建立服務帳戶,請繼續閱讀下一節。

您必須授予多個服務代理權限,以便存取金鑰,方法是授予 CryptoKey Encrypter/Decrypter IAM 角色 (roles/cloudkms.cryptoKeyEncrypterDecrypter)。這些服務代理可用於取得存放於 Cloud Storage 的原始碼存取權、在 Artifact Registry 中以 CMEK 保護的存放區儲存函式圖像,以及部署以 CMEK 加密的 Cloud Function。

第 1 代函式的步驟

  1. 授予 Cloud Functions 服務代理程式金鑰存取權:
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. 授予 Artifact Registry 服務代理權限,以便存取金鑰:
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. 授予 Cloud Storage 服務代理存取金鑰的權限:
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

在下一節中,您將瞭解如何建立及部署 CMEK 加密函式。

7. 建立 CMEK 加密函式 (第 2 代)

本節說明如何建立第 2 代函式。如需第 1 代說明,請繼續參閱下一節。

您已設定啟用 CMEK 的 Artifact Registry 存放區,並授予 Cloud Functions 存取金鑰的權限,現在可以部署使用 CMEK 金鑰加密的函式。

第 2 代函式須採取的步驟:

建立函式原始碼

雖然本程式碼研究室使用的是 Node.js,但您可以使用任何支援的執行階段

首先,請建立目錄並使用 cd 指令前往該目錄。

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

接著建立 package.json 檔案。

touch package.json

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

接下來,請建立 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

使用 CMEK 加密功能部署第 2 代 Cloud Function

注意:以下範例說明如何使用目前目錄中的來源部署函式。請確認您位於函式原始碼所在的目錄。

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

執行這項指令,即可在結果輸出內容中看到 CMEK 金鑰

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

測試第 2 代函式

您可以透過捲曲函式來測試函式:

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

curl $FUNCTION_URL

結果如下:

Hello World!

只要加密金鑰為啟用狀態,該函式就會將成功傳回給呼叫端。不過,一旦加密金鑰停用,呼叫端就會收到錯誤。

在下一節中,您將瞭解在金鑰停用後叫用函式時會發生的情況。

8. 建立 CMEK 加密的函式 (第 1 代)

本節說明如何建立第 1 代函式。如果您先前已建立第 2 代函式,請繼續閱讀下一節。

您已設定啟用 CMEK 的 Artifact Registry 存放區,並授予 Cloud Functions 存取金鑰的權限,現在可以部署使用 CMEK 金鑰加密的函式。

第 1 代函式的步驟:

建立第 1 代函式的原始碼

雖然本程式碼研究室使用的是 Node.js,但您可以使用任何支援的執行階段

首先,請建立目錄並使用 cd 指令前往該目錄。

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

接下來,請建立 package.json 檔案。

touch package.json

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

接著,請建立 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

使用 CMEK 加密功能部署第 1 代 Cloud 函式

注意:以下範例說明如何使用目前目錄中的來源部署函式。確認您位於函式原始碼所在的目錄。

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

執行這項指令,即可在結果輸出內容中看到 CMEK 金鑰

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

測試第 1 代函式

您可以使用 curl 來測試函式:

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

curl $FUNCTION_URL

結果如下:

Hello World!

只要加密金鑰為啟用狀態,該函式就會將成功傳回給呼叫端。不過,一旦加密金鑰停用,呼叫端就會收到錯誤。

在下一節中,您將瞭解在金鑰停用後叫用函式時會發生什麼情況。

9. 在加密金鑰已停用的情況下,呼叫 CMEK 加密函式

在這個最後一節中,您將讓金鑰失效,並再次叫用函式,查看產生的錯誤。

停用加密金鑰

您可以執行這項指令來停用金鑰。由於這個程式碼研究室只建立一個金鑰版本,因此您將停用版本 1。

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

您應該會看到以下結果資訊:

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

使用已停用的金鑰叫用函式

現在再次 curl 函式。

curl $FUNCTION_URL

這次您也不會收到 Hello World 回應。

在 Cloud Functions 的記錄中,您會看到

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

在 CMEK 金鑰停用時嘗試查看資源

在這個部分,您會看到在停用 CMEK 金鑰後,下列資源將無法使用:

  • 函式原始碼
  • 從原始碼建構容器映像檔

例如,造訪 Cloud 函式的「來源」分頁時,擷取封存檔時會顯示錯誤。如果您嘗試直接在 Cloud Storage 中查看含有原始碼的 .zip 檔案,也會收到類似的錯誤訊息。

ac3307bb05d30e19.png

此外,您也無法使用 Artifact Registry 中的函式容器映像檔。舉例來說,如果您嘗試將該容器映像檔部署至 Cloud Run,系統會顯示找不到映像檔的錯誤訊息。

如需加密資源的完整清單,請參閱 CMEK 函式說明文件

10. 恭喜

恭喜,您已完成程式碼研究室!

涵蓋內容

  • 如何在現有的對稱金鑰環中建立 CMEK 金鑰
  • 如何建立 Artifact Registry 存放區
  • 如何在 Cloud 函式中設定 CMEK

瞭解詳情

如要進一步瞭解 Cloud Functions 和 CMEK,請參閱以下連結: