顧客管理の暗号鍵(CMEK)を使用する

このページでは、Firestore の顧客管理の暗号鍵(CMEK)に関連するタスクの実行方法について説明します。CMEK の一般的な用途や使用する理由などの詳細については、Cloud KMS のドキュメントをご覧ください。

CMEK 鍵を準備する

CMEK で保護された Firestore データベースを作成する前に、次の手順を完了する必要があります。

  1. Firestore サービス エージェントを作成(または取得)する
  2. CMEK 鍵を作成する
  3. その鍵の IAM 設定を構成する

CMEK で保護された Firestore データベースを含むプロジェクトごとに、次の手順を完了します。後で新しい CMEK 鍵を作成する場合は、その鍵の IAM 設定を構成する必要があります。

Firestore サービス エージェントを作成する

CMEK 鍵を作成する前に、Firestore サービス エージェントが必要です。このアカウントは、Firestore が鍵へのアクセスに使用する Google マネージド サービス アカウントの一種です。

サービス アカウント作成コマンドを実行して、Firestore がお客様の代わりに CMEK 鍵にアクセスする際に使用するサービス エージェントを作成します。サービス アカウントが存在しない場合、このコマンドはサービス アカウントを作成して表示します。

gcloud beta services identity create \
    --service=firestore.googleapis.com \
    --project FIRESTORE_PROJECT

FIRESTORE_PROJECT は、Firestore データベースに使用するプロジェクトに置き換えます。

このコマンドは、メールアドレスに似た形式のサービス エージェント ID を表示します。後のステップで使用するため、出力メール文字列を記録します。

Service identity created:
service-xxx@gcp-sa-firestore.iam.gserviceaccount.com

鍵を作成する

Cloud KMS で直接作成された鍵または Cloud External Key Manager で利用できる外部管理鍵を使用できます。

Cloud KMS の鍵のロケーションは、使用する Firestore データベースのロケーションと同じにする必要があります。

  • リージョン データベースのロケーションには、ロケーション名には 1 対 1 のマッピングがあるため、キーリング、鍵、データベースに同じロケーション名を使用します。

    たとえば、CMEK で保護されたデータベースを us-west1 に作成する場合は、us-west1 にキーリングと鍵を作成します。

  • マルチリージョン データベース ロケーションには、KMS マルチリージョン ロケーションのロケーション名を使用します。

    • Firestore の nam5 マルチリージョン ロケーションには、Cloud KMS us マルチリージョン ロケーションを使用します。
    • Firestore の eur3 マルチリージョン ロケーションには、Cloud KMS europe マルチリージョン ロケーションを使用します。

鍵を管理する Google Cloud プロジェクトで、以下を完了します。

  1. Cloud KMS API を有効化します。

  2. 次のいずれかのオプションを使用してキーリングと鍵を作成します。

鍵の IAM 設定を構成する

コンソール

Cloud KMS のロールをサービス エージェントに付与するには、次の手順を行います。詳細レベルでの設定が必要な場合は、鍵レベルまたは鍵リングレベルで権限を付与することもできます。

  1. Google Cloud コンソールの [IAM] ページに移動します。

    [IAM] ページに移動

  2. [Add] をクリックします。

  3. Firestore サービス エージェントのメール ID を入力します。

  4. [Cloud KMS 暗号鍵の暗号化 / 復号] ロールを選択します。

  5. [保存] をクリックします。

gcloud

  1. サービス エージェントに cloudkms.cryptoKeyEncrypterDecrypter ロールを付与します。

    gcloud kms keys add-iam-policy-binding KMS_KEY \
        --keyring KMS_KEYRING\
        --location KMS_LOCATION \
        --member serviceAccount:SERVICE_AGENT_EMAIL \
        --role roles/cloudkms.cryptoKeyEncrypterDecrypter \
        --project KMS_PROJECT
    

    次のフィールドを入力します。

    • KMS_KEY: 鍵に割り当てた名前
    • KMS_KEYRING: 鍵が含まれる KMS キーリング
    • KMS_LOCATION: キーリングが含まれるリージョン
    • SERVICE_AGENT_EMAIL: アクセス権を付与するサービス エージェントのメール形式の ID
    • KMS_PROJECT: 鍵が含まれるプロジェクト

    ターミナルに次のようなレスポンスが表示されます。

    Updated IAM policy for key KMS_KEY.
    bindings:
    - members:
      - serviceAccount:
        service-{project-number}@gcp-sa-firestore.iam.gserviceaccount.com
    role: roles/cloudkms.cryptoKeyEncrypterDecrypter
    

CMEK 有効化データベースを作成する

CMEK 鍵の作成と構成が完了したら、CMEK で保護されたデータベースを作成できます。Google のデフォルトの暗号化によって保護されている既存の Firestore データベースは、CMEK を使用するように変換できません。暗号化の種類と鍵は、作成時にのみ選択できます。

gcloud

gcloud alpha firestore databases create --location=FIRESTORE_DATABASE_LOCATION \
      --database=DATABASE_ID \
      --kms-key-name=KMS_KEY_NAME \
      --project=FIRESTORE_PROJECT

次のフィールドを入力します。

  • FIRESTORE_DATABASE_LOCATION: データベースの Firestore のロケーション
  • DATABASE_ID: データベースの ID
  • KMS_KEY_NAME: 鍵に割り当てた名前次の形式で、鍵の完全なリソース名を使用します。

    projects/KMS_PROJECT/locations/KMS_LOCATION/keyRings/KMS_KEYRING_ID/cryptoKeys/KMS_KEY_ID

  • FIRESTORE_PROJECT: Firestore データベースに使用するプロジェクト

REST API

HTTP リクエスト:

POST https://firestore.googleapis.com/v1/projects/{FIRESOTRE_PROJECT}/databases

リクエストの本文で cmek_config.kms_key_name フィールドに CMEK を構成します。

Cloud KMS 鍵の完全なリソース ID に設定します。このデータベースと同じロケーションにある鍵のみが許可されます。

この値は、projects/{KMS_PROJECT}/locations/{KMS_LOCATION}/keyRings/{KMS_KEYRING_ID}/cryptoKeys/{KMS_KEY_ID} の形式で Cloud KMS 鍵のリソース ID にする必要があります。

他のフィールドの詳細については、database create ページをご覧ください。

リクエストの例:

curl -X POST 'https://firestore.googleapis.com/v1/projects/FIRESTORE_PROJECT/databases?databaseId={DATABASE_ID}' \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-type: application/json" \
-d '{
  "type":"FIRESTORE_NATIVE",
  "locationId":"{FIRESTORE_DATABASE_LOCATION}",
  "cmekConfig": {
    "kmsKeyName":"projects/KMS_PROJECT/locations/KMS_LOCATION/keyRings/KMS_KEYRING_ID/cryptoKeys/KMS_KEY_ID"
  }
}'

Terraform

CMEK 有効化データベースを作成するには、google_firestore_database リソースを使用します。詳細と例については、google_firestore_database をご覧ください。

resource "google_firestore_database" "database" {
  project     = "FIRESTORE_PROJECT"
  name        = "DATABASE_ID"
  location_id = "FIRESTORE_DATABASE_LOCATION"
  type        = "DATABASE_TYPE"

  cmek_config {
    kms_key_name = "KMS_KEY_NAME"
  }

}

次のフィールドを入力します。

  • FIRESTORE_PROJECT: Firestore データベースに使用するプロジェクト
  • DATABASE_ID: データベースの ID
  • FIRESTORE_DATABASE_LOCATION: データベースの Firestore のロケーション
  • DATABASE_TYPE: ネイティブ モードの場合は FIRESTORE_NATIVE、Datastore モードの場合は DATASTORE_MODE のいずれか。
  • KMS_KEY_NAME: 鍵に割り当てた名前次の形式で、鍵の完全なリソース名を使用します。

    projects/KMS_PROJECT/locations/KMS_LOCATION/keyRings/KMS_KEYRING_ID/cryptoKeys/KMS_KEY_ID

CMEK で保護されているデータベースにアクセスする

CMEK で保護されたデータベースに送信されるすべての読み取り、書き込み、クエリのオペレーションは、Google のデフォルトの暗号化されたデータベースと同じように機能するべきです。たとえば、リクエストごとに鍵を指定する必要はありません。

使用中の鍵を表示する

gcloud

databases describe gcloud CLI コマンドを使用して、データベースの CMEK の構成を確認できます。

gcloud firestore databases describe --database=DATABASE_ID --project=FIRESTORE_PROJECT

レスポンスの cmekConfig フィールドに、次のような CMEK 情報が表示されます。

cmekConfig:
    activeKeyVersion:
    - projects/PROJECT_ID/locations/us/keyRings/KEYRING_NAME/cryptoKeys/KEY_NAME/cryptoKeyVersions/1
    kmsKeyName: projects/PROJECT_ID/locations/us/keyRings/KEYRING_NAME/cryptoKeys/KEY_NAME
  locationId: nam5
  name: projects/PROJECT_ID/databases/DATABASE_ID

レスポンスには次の情報が含まれます。

  • kmsKeyName: CMEK で保護されたデータベースの暗号化に使用される鍵の完全な鍵リソース名。
  • activeKeyVersion: CMEK で保護されたデータベースで現在使用中のすべての鍵バージョンのリスト。鍵のローテーション中は、アクティブな鍵バージョンが複数存在する可能性があります。

REST API

HTTP リクエスト:

GET https://firestore.googleapis.com/v1/{name=projects/FIRESTORE_PROJECT/databases/DATABASE_ID}

リクエストの本文で cmek_config.kms_key_name フィールドに CMEK を構成します。Cloud KMS 鍵の完全なリソース ID に設定します。このデータベースと同じロケーションにある鍵のみが許可されます。

この値は、projects/{KMS_PROJECT}/locations/{KMS_LOCATION}/keyRings/{KMS_KEYRING_ID}/cryptoKeys/{KMS_KEY_ID} の形式で Cloud KMS 鍵のリソース ID にする必要があります。

他のフィールドの詳細については、database create ページをご覧ください。

リクエストとレスポンスの例:

curl 'https://firestore.googleapis.com/v1/projects/FIRESTORE_PROJECT/databases/{DATABASE_ID}' \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-type: application/json"

—----------------------------------------- Response —--------------------------------------------
{
  "name": "projects/FIRESTORE_PROJECT/databases/{DATABASE_ID}",
  "locationId": "{FIRESTORE_DATABASE_LOCATION}",
  "type": "FIRESTORE_NATIVE",
  "cmekConfig": {
    "kmsKeyName": "projects/{KMS_PROJECT}/locations/{KMS_LOCATION}/keyRings/{KMS_KEYRING_ID}/cryptoKeys/{KMS_KEY_ID}",
    "activeKeyVersion": [
      "projects/{KMS_PROJECT}/locations/{KMS_LOCATION}/keyRings/{KMS_KEYRING_ID}/cryptoKeys/{KMS_KEY_ID}/cryptoKeyVersions/1"
    ]
  },
  ……
}

鍵を無効にする

データベースに関連付けられた鍵を無効にするには、次の手順を完了します。

  1. データベースで使用中の鍵バージョンを表示する
  2. これらの鍵バージョンを無効にする
  3. 変更が有効になるまで待ってから、データにもうアクセスできないかを確認します。通常は数分で変更内容が反映されますが、最長で 3 時間ほどかかることもあります。

データベースで使用される鍵が無効にされている場合、エラー メッセージに追加の詳細を含む FAILED_PRECONDITION 例外を受け取ります。次に例を示します。

{
  "error": {
    "code": 400,
    "message": "The customer-managed encryption key required by the requested resource is not accessible. Error reason:  generic::permission_denied: Permission 'cloudkms.cryptoKeyVersions.useToEncrypt' denied on resource 'projects/FIRESTORE_PROJECT/locations/{KMS_LOCATION}/keyRings/{KMS_KEYRING_ID}/cryptoKeys/{KMS_KEY_ID}' (or it may not exist).",
    "status": "FAILED_PRECONDITION",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.DebugInfo",
        "detail": "The customer-managed encryption key required by the requested resource is not accessible. Error reason:  generic::permission_denied: Permission 'cloudkms.cryptoKeyVersions.useToEncrypt' denied on resource 'projects/FIRESTORE_PROJECT/locations/{KMS_LOCATION}/keyRings/{KMS_KEYRING_ID}/cryptoKeys/{KMS_KEY_ID}' (or it may not exist)"
      }
    ]
  }
}

鍵を有効にする

データベースに関連付けられた鍵を再度有効にするには、次の手順を完了します。

  1. データベースで使用中の鍵バージョンを表示する
  2. それらの鍵バージョンを有効にする
  3. 変更が有効になるまで待ってから、データにもうアクセスできないかを確認します。通常は数分で変更内容が反映されますが、最長で 3 時間ほどかかることもあります。

Cloud KMS 鍵の監査ログを表示する

Cloud KMS データアクセス監査ログを有効にする前に、Cloud Audit Logs について理解しておく必要があります。

Cloud KMS データアクセス監査ログでは、Firestore または CMEK 鍵を使用するように構成されている他のプロダクトが Cloud KMS に暗号化 / 復号呼び出しを行った日時を確認できます。Firestore は、すべてのデータ リクエストに対して暗号化 / 復号呼び出しを実行するのではなく、鍵を定期的に確認するポーラーを維持します。ポーリングの結果は監査ログに表示されます。

監査ログは Google Cloud コンソールで設定と操作ができます。

  1. プロジェクト内の Cloud KMS API でロギングが有効になっていることを確認します。

  2. Google Cloud コンソールで Cloud Logging に移動します。

    Cloud Logging に移動

  3. クエリビルダーに次の行を追加して、ログエントリを Cloud KMS 鍵に限定します。

    resource.type="cloudkms_cryptokey"
    resource.labels.key_ring_id = KMS_KEYRING
    resource.labels.crypto_key_id = KMS_KEY
    resource.labels.location=KMS_LOCATION
    

    次のフィールドを入力します。

    • KMS_KEY: CMEK 鍵の名前
    • KMS_KEYRING: 鍵が含まれる KMS キーリング
    • KMS_LOCATION: 鍵とキーリングのロケーション

    このログには、データベースごとに約 5 分間隔でログエントリが記録されます。ログエントリは次のようになります。

    Info 2021-03-20 08:02:24.869 EDT Cloudkms.googleapis.com Decrypt projects/cloud-kms-project/locations/us-central1/keyRings/firestore-keys/cryptoKeys/my-cmek-key service-123456789123@gcp-sa-firestore.iam.gserviceaccount.com
    audit_log, method: "Decrypt", principal_email: "service-1234567891011@gcp-sa-firestore.iam.gserviceaccount.com"
    
    Info 2021-03-20 08:02:24.913 EDT Cloudkms.googleapis.com Encrypt projects/cloud-kms-project/locations/us-central1/keyRings/firestore-keys/cryptoKeys/my-cmek-key service-123456789123@gcp-sa-firestore.iam.gserviceaccount.com
    audit_log, method: "Encrypt", principal_email: "service-123456789123@gcp-sa-firestore.iam.gserviceaccount.com"
    

監査ログの解釈方法については、監査ログについてをご覧ください。

CMEK の組織のポリシーを構成する

組織内の Firestore データベースの暗号化コンプライアンス要件を指定するには、CMEK 組織のポリシー制約を使用します。

CMEK 保護を要求する

Firestore データベース作成用の CMEK を要求するように constraints/gcp.restrictNonCmekServices を構成します。制約を deny に設定し、firestore.googleapis.com を拒否リストに追加します。次に例を示します。

 gcloud resource-manager org-policies deny gcp.restrictNonCmekServices  is:firestore.googleapis.com --project=FIRESTORE_PROJECT

FIRESTORE_PROJECT は、制限するプロジェクトに置き換えます。

組織のポリシーの構成の詳細については、ポリシーの作成と編集をご覧ください。

ポリシーが有効になった後、影響を受けるプロジェクトで CMEK 以外のデータベースを作成しようとすると、FAILED_PRECONDITION 例外とエラー メッセージを受信します。たとえば、例外は次のようになります。

{
  "error": {
    "code": 400,
    "message": "Constraint 'constraints/gcp.restrictNonCmekServices' violated for 'projects/FIRESTORE_PROJECT' attempting to perform the operation 'google.firestore.admin.v1.FirestoreAdmin.CreateDatabase' with violated value 'firestore.googleapis.com'. See https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints for more information.",
    "status": "FAILED_PRECONDITION",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.PreconditionFailure",
        "violations": [
          {
            "type": "constraints/gcp.restrictNonCmekServices",
            "subject": "orgpolicy:projects/FIRESTORE_PROJECT",
            "description": "Constraint 'constraints/gcp.restrictNonCmekServices' violated for 'projects/FIRESTORE_PROJECT' attempting to perform the operation 'google.firestore.admin.v1.FirestoreAdmin.CreateDatabase' with violated value 'firestore.googleapis.com'. See https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints for more information."
          }
        ]

CMEK の鍵の使用を制限する

CMEK の保護に使用される Cloud KMS 鍵がどれかを制限するには、constraints/gcp.restrictCmekCryptoKeyProjects 制約を構成します。

リスト型制約として許容される値は、リソース階層インジケーター(projects/PROJECT_IDunder:folders/FOLDER_IDunder:organizations/ORGANIZATION_ID など)です。この制約を使用するには、リソース階層インジケーターのリストを構成し、制約を [許可] に設定します。この構成では、CMEK 鍵が、リストされたプロジェクト、フォルダ、組織からのみ選択できるように、サポート対象サービスが制限されます。構成されたサービスで CMEK で保護されたリソースを作成するリクエストは、許可されたリソースのいずれかからの Firestore 鍵がなければ成功しません。

次の例では、指定されたプロジェクト内の CMEK で保護されたデータベースの ALLOWED_KEY_PROJECT_ID の鍵のみを許可します。

gcloud resource-manager org-policies allow gcp.restrictCmekCryptoKeyProjects \
under:projects/ALLOWED_KEY_PROJECT_ID \
--project=FIRESTORE_PROJECT

ポリシーが有効になった後、制約に違反すると、FAILED_PRECONDITION 例外とエラー メッセージを受信します。例外は次のようになります。

{
  "error": {
    "code": 400,
    "message": "Constraint 'constraints/gcp.restrictCmekCryptoKeyProjects' violated for 'projects/FIRESTORE_PROJECT' attempting to perform the operation 'google.firestore.admin.v1.FirestoreAdmin.CreateDatabase' with violated value 'projects/{NOT_ALLOWED_KEY_PROJECT}'. See https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints for more information.",
    "status": "FAILED_PRECONDITION",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.PreconditionFailure",
        "violations": [
          {
            "type": "constraints/gcp.restrictCmekCryptoKeyProjects",
            "subject": "orgpolicy:projects/FIRESTORE_PROJECT",
            "description": "Constraint 'constraints/gcp.restrictCmekCryptoKeyProjects' violated for 'projects/FIRESTORE_PROJECT' attempting to perform the operation 'google.firestore.admin.v1.FirestoreAdmin.CreateDatabase' with violated value 'projects/{NOT_ALLOWED_KEY_PROJECT}'. See https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints for more information."
          }
        ]
      }
    ]
  }
}

次のステップ