1. はじめに
概要
Cloud Functions は軽量なコンピューティング ソリューションであり、デベロッパーはサーバーやランタイム環境を管理することなく、Cloud イベントに応答する単一目的のスタンドアロン関数を作成できます。
Cloud Key Management Service の顧客管理の暗号鍵(CMEK)は、Cloud Functions と関連する保存データを保護するために使用できます。CMEK を使用して関数をデプロイすると、完全に制御できる暗号鍵を使用して、関連するデータが保護されます。このタイプの暗号化を行うことで、金融サービスなどの特定の業界のコンプライアンス要件を満たすことができます。鍵はユーザーが所有し、Google が管理していないため、鍵が無効または破棄されると、これらの暗号鍵で保護されたデータに誰も(ユーザー自身も)アクセスできなくなります。
Cloud Functions の場合、CMEK は次のものを暗号化します。
- デプロイ用にアップロードされた関数のソースコード。Google により Cloud Storage に保存され、ビルドプロセスで使用されます。
- 関数のソースコードからビルドされたコンテナ イメージや、デプロイされた関数の各インスタンスなど、関数ビルドプロセスの結果。
- 内部イベント トランスポート チャネルの保存データ(第 1 世代のみ)。
暗号化されるデータの詳細については、Cloud Functions CMEK のドキュメントをご覧ください。
作成するアプリの概要
この Codelab では、CMEK を使用して暗号化された Cloud Functions の関数(第 1 世代または第 2 世代)をデプロイする方法について説明します。この Codelab では、デモ用に公開 Cloud Functions(認証を必要としない関数)を使用します。認証を必要とする他の Cloud Functions と同様に、認証済みの CMEK 対応関数を呼び出すことができます。
学習内容
- 既存の対称鍵リングに CMEK 鍵を作成する方法
- Artifact Registry リポジトリを作成する方法
- 第 1 世代と第 2 世代の両方で Cloud Functions に CMEK を構成する方法
2. 設定と要件
前提条件
- Cloud コンソールにログインしていること
- HTTP トリガー Cloud Functions を以前にデプロイしていること(適切なロールと API が有効になっていることを確認するため)
Cloud Shell をアクティブにする
- Cloud Console で、[Cloud Shell をアクティブにする ]
をクリックします。

Cloud Shell を初めて起動した場合は、その内容を説明する画面が表示されます。中間画面が表示された場合は、[続行] をクリックします。

すぐにプロビジョニングが実行され、Cloud Shell に接続されます。

この仮想マシンには、必要な開発ツールがすべて用意されています。仮想マシンは Google Cloud で稼働し、永続的なホーム ディレクトリが 5 GB 用意されているため、ネットワークのパフォーマンスと認証が大幅に向上しています。 この Codelab で行う作業のほとんどはブラウザから実行できます。
Cloud Shell に接続すると、認証が完了し、プロジェクトに各自のプロジェクト ID が設定されていることがわかります。
- 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`
- 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
まず、この Codelab で使用するキーリング名、鍵名、リージョンなどの変数を含む環境変数を作成します。
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 対応の Docker 形式の Artifact Registry リポジトリを作成する
このセクションでは、CMEK 対応の Docker 形式のリポジトリを Artifact Registry に作成します。この鍵は、Cloud Functions のデプロイに使用する鍵と同じです。
まず、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
また、Artifact Registry にリポジトリを作成するプリンシパル(現在の有効なアカウントなど)にロールを付与します。現在の有効なアカウントを確認するには、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
これで、CMEK 対応の Docker 形式のリポジトリを作成できます。
注: リージョンは 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 Functions をデプロイするために使用されます。
第 2 世代の関数の手順
- 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
- 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
- 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
- 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 Functions をデプロイするために使用されます。
第 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
- 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
- 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 世代の関数の手順:
関数のソースコードを作成する
この Codelab では Node.js を使用しますが、サポートされている任意のランタイムを使用できます。
まず、ディレクトリを作成してそのディレクトリに移動します。
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 Functions をデプロイする
注: 次の例は、現在のディレクトリのソースを使用して関数をデプロイする方法を示しています。関数のソースコードと同じディレクトリにいることを確認してください。
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 世代の関数をテストする
関数を curl でテストできます。
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 世代の関数のソースコードを作成する
この Codelab では Node.js を使用しますが、サポートされている任意のランタイムを使用できます。
まず、ディレクトリを作成してそのディレクトリに移動します。
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 Functions をデプロイする
注: 次の例は、現在のディレクトリのソースを使用して関数をデプロイする方法を示しています。関数のソースコードと同じディレクトリにいることを確認してください。
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 で暗号化された関数を呼び出す
この最後のセクションでは、鍵を無効にして関数を再度呼び出し、結果のエラーを確認します。
暗号鍵を無効にする
このコマンドを実行すると、鍵を無効にできます。この Codelab では鍵のバージョンを 1 つだけ作成するため、バージョン 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 Functions の [ソース] タブにアクセスすると、アーカイブの取得中にエラーが表示されます。Cloud Storage でソースコードを含む .zip ファイルを直接表示しようとすると、同様のエラーが表示されます。

また、Artifact Registry から関数のコンテナ イメージを使用することもできません。たとえば、そのコンテナ イメージを Cloud Run にデプロイしようとすると、イメージが見つからないというエラーが表示されます。
暗号化されたリソースの一覧については、CMEK Functions のドキュメントを ご覧ください。
10. 完了
お疲れさまでした。これでこの Codelab は終了です。
学習した内容
- 既存の対称鍵リングに CMEK 鍵を作成する方法
- Artifact Registry リポジトリを作成する方法
- Cloud Functions に CMEK を構成する方法
詳細
Cloud Functions と CMEK の詳細については、次のリンクをご覧ください。