↓メインコンテンツへスキップ
  1. Blogs/

TerraformでCloud KMSのKeyRingとCryptoKeyを作成してみた

2 分
Terraform GoogleCloud
0222-nnn
著者
0222-nnn
猫が好き
目次
Terraform-GoogleCloud - この記事は連載の一部です
パート 15: この記事

概要
#

Cloud KMSは暗号鍵を生成・管理するサービスです。今回はTerraformでKeyRingとENCRYPT_DECRYPT用CryptoKeyを作成します。

重要なのは、KeyRingなどが通常のResourceと同じようには完全削除できない点です。専用の検証Projectで試します。

Terraformの基本操作は前提としています。暗号鍵の管理が初めての方向けです。

Key自体を使った実際の暗号化・復号処理、外部KeyのImportは扱いません。

検証すること
#

  • Cloud KMSのKeyRingとCryptoKeyを作成できること
  • Rotation PeriodとPurposeをTerraformで設定できること
  • Google Cloud CLIでKeyとVersionを確認できること

前提環境
#

  • Google Cloud CLIとApplication Default Credentials(ADC)
  • Terraform 1.5以降
  • Cloud KMSを操作できる検証用Google Cloud Project
  • 検証時のバージョン:Terraform 1.14.3、google 7.43.0

今回の構成
#

Cloud KMSはVPCに属しません。Projectの下にLocationごとのKeyRingがあり、その中にCryptoKeyが入る階層構造です。利用側はAPIエンドポイント経由でアクセスします。

flowchart TB
    Caller["利用側
gcloud / アプリケーション"] subgraph GCP["Google Cloud"] subgraph Project["Project"] subgraph KMS["Cloud KMS"] subgraph Ring["KeyRing"] Key["CryptoKey: tf-example-key
ENCRYPT_DECRYPT
GOOGLE_SYMMETRIC_ENCRYPTION"] Ver["Key Version 1(ENABLED)"] Key --- Ver end end end end Caller -->|"encrypt / decrypt API"| Key

KeyRingはLocationに紐づき、あとから移動できません。またKeyRingとCryptoKeyは削除できないため、Location選びは最初に決める必要があります。

暗号化と復号では、鍵そのものは外に出ません。データをCloud KMSへ送り、処理結果を受け取ります。

sequenceDiagram
    actor User as 手元の端末
    participant KMS as Cloud KMS
    participant Key as CryptoKey (鍵は外に出ない)

    User->>KMS: encrypt (平文 16 bytes)
    KMS->>Key: 鍵バージョン1で暗号化
    KMS-->>User: 暗号文 97 bytes

    User->>KMS: decrypt (暗号文)
    Note over KMS,Key: 暗号文から鍵バージョンを判別
    KMS-->>User: 平文

使用するTerraformコード
#

KeyRing
#

locals {
  key_ring_name = "${var.key_ring_name_prefix}-${var.project_id}"
}

resource "google_kms_key_ring" "example" {
  project  = var.project_id
  name     = local.key_ring_name
  location = var.location
}

KeyRingはKeyをまとめるContainerです。名前の衝突を避けるためProject IDを付加し、デフォルトLocationはglobalです。

CryptoKey
#

resource "google_kms_crypto_key" "example" {
  name     = var.crypto_key_name
  key_ring = google_kms_key_ring.example.id
  purpose  = "ENCRYPT_DECRYPT"
}

ENCRYPT_DECRYPTは対称暗号化・復号用です。実運用ではRotation Period、次回Rotation日時、IAM、Protection Levelなども設計します。

設定と実行
#

cd Basic-Examples/14-cloud-kms
cp terraform.tfvars.example terraform.tfvars
terraform init
terraform fmt -check
terraform validate
terraform plan
terraform apply
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

crypto_key_name = "tf-example-key"
key_ring_name = "tf-example-keyring-YOUR_PROJECT_ID"
location = "asia-northeast1"

同じProjectで2回目を実行すると、KeyRingが残っているため失敗します。

Error: Error creating KeyRing: googleapi: Error 409: KeyRing already exists.
  "reason": "RESOURCE_ALREADY_EXISTS"

後述のとおりKeyRingは削除できません。terraform.tfvarsでkey_ring_name_prefixを変えて再実行します。

GCP側で確認する
#

gcloud kms keyrings describe \
  "$(terraform output -raw key_ring_name)" \
  --location="$(terraform output -raw location)" \
  --project="$(terraform output -raw project_id)"

gcloud kms keys describe \
  "$(terraform output -raw crypto_key_name)" \
  --keyring="$(terraform output -raw key_ring_name)" \
  --location="$(terraform output -raw location)" \
  --project="$(terraform output -raw project_id)"
name: projects/YOUR_PROJECT_ID/locations/asia-northeast1/keyRings/tf-example-keyring-YOUR_PROJECT_ID/cryptoKeys/tf-example-key
purpose: ENCRYPT_DECRYPT
versionTemplate:
  algorithm: GOOGLE_SYMMETRIC_ENCRYPTION
  protectionLevel: SOFTWARE

実際に暗号化と復号を試すと、鍵が使える状態かを確認できます。

echo "hello terraform" > sample.txt

gcloud kms encrypt \
  --key="$(terraform output -raw crypto_key_name)" \
  --keyring="$(terraform output -raw key_ring_name)" \
  --location="$(terraform output -raw location)" \
  --project="$(terraform output -raw project_id)" \
  --plaintext-file=sample.txt \
  --ciphertext-file=sample.enc

gcloud kms decrypt \
  --key="$(terraform output -raw crypto_key_name)" \
  --keyring="$(terraform output -raw key_ring_name)" \
  --location="$(terraform output -raw location)" \
  --project="$(terraform output -raw project_id)" \
  --ciphertext-file=sample.enc \
  --plaintext-file=-
hello terraform

元のテキストが戻れば成功です。16バイトの平文が97バイトの暗号文になりました。Cloud KMSの暗号文には鍵のバージョン情報などが含まれるため、平文より大きくなります。

destroy時の重要な注意
#

terraform destroy

Cloud KMSのKeyRingはGoogle Cloudから削除できません。Terraform destroyでStateから外れても、Project側には名前が残ります。CryptoKeyも鍵Materialの即時完全消去とは異なるLifecycleを持ちます。

そのため、このサンプルはdestroyで完全に元の状態へ戻りません。同じProjectで再実行すると名前が衝突する場合は、key_ring_name_prefixを変更します。

検証用Projectを分け、残存Resourceと料金を理解してから実行します。Key Versionの保持や暗号処理には料金が発生します。

まとめ
#

  • KeyRingとCryptoKeyの階層をTerraformで定義できる
  • 対称暗号用にENCRYPT_DECRYPTを指定できる
  • KMSはdestroyしても完全削除されないResourceがある
  • Rotation、IAM、削除防止を本番要件として追加検討する

参考資料
#

次回
#

次はCloud MonitoringのAlert PolicyとEmail Notification Channelを作成します。

Terraform-GoogleCloud - この記事は連載の一部です
パート 15: この記事

関連記事

Terraform StateをCloud Storage Remote Backendへ移行してみた
2 分
Terraform GoogleCloud CloudStorage
TerraformからGoogle Cloudへ接続してProject情報を取得してみた
3 分
Terraform GoogleCloud
TerraformでArtifact RegistryのDocker Repositoryを作成してみた
2 分
Terraform GoogleCloud Docker
TerraformでArtifact RegistryのコンテナをCloud Runへデプロイしてみた
2 分
Terraform GoogleCloud CloudRun ArtifactRegistry
TerraformでBigQuery DatasetとTableを作成してみた
2 分
Terraform GoogleCloud
TerraformでCloud MonitoringのAlert Policyを作成してみた
2 分
Terraform GoogleCloud