Back to Checks
gcp

BigQuery table is encrypted with a Customer-Managed Key (CMK)

bigquery_table_cmk_encryption
Service: bigquerySeverity: high
OfficialBuilt-inVerified
Categories:encryption
Resource Type:bigquery.googleapis.com/Table

BigQuery tables use customer-managed encryption keys (CMEK) for at-rest encryption. The evaluation identifies tables lacking a configured Cloud KMS key, indicating use of default Google-managed encryption instead.

Risk

Without CMEK, encryption keys are not under your control, reducing key custody and auditability. You can't enforce region-bound keys, custom rotation, or revoke access by disabling a key, weakening confidentiality and compliance. A compromised account may retain data access without an external KMS gate.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler gcp --checks bigquery_table_cmk_encryption

Recommendation

Protect BigQuery tables with Cloud KMS CMEK to retain key ownership and control.

  • Set dataset/project default keys
  • Match key location to dataset region
  • Enforce least-privilege on KMS and monitor usage
  • Rotate keys and define revocation procedures
  • Apply org policies to require CMEK and restrict permissible key projects

Remediation

CLI

bq cp -f --destination_kms_key projects/<KMS_PROJECT_ID>/locations/<LOCATION>/keyRings/<KEY_RING>/cryptoKeys/<KEY> <DATASET_ID>.<TABLE_ID> <DATASET_ID>.<TABLE_ID>

Terraform

resource "google_bigquery_table" "<example_resource_name>" {
  dataset_id = "<DATASET_ID>"
  table_id   = "<TABLE_ID>"

  schema = jsonencode([
    { name = "id", type = "INT64", mode = "NULLABLE" }
  ])

  # Critical: enforce CMEK on the table using the specified KMS key
  encryption_configuration {
    kms_key_name = "projects/<KMS_PROJECT_ID>/locations/<LOCATION>/keyRings/<KEY_RING>/cryptoKeys/<KEY>"  # Enables CMK encryption
  }
}

Other

1In Google Cloud Console, go to BigQuery and open the Query editor
2Run:
3```sql
4ALTER TABLE <DATASET_ID>.<TABLE_ID>
5SET OPTIONS (kms_key_name = 'projects/<KMS_PROJECT_ID>/locations/<LOCATION>/keyRings/<KEY_RING>/cryptoKeys/<KEY>');
6```
7Click Run
8Open the table Details and verify Customer-managed key shows the specified key

Check Code

from prowler.lib.check.models import Check, Check_Report_GCP
from prowler.providers.gcp.services.bigquery.bigquery_client import bigquery_client


class bigquery_table_cmk_encryption(Check):
    def execute(self) -> Check_Report_GCP:
        findings = []
        for table in bigquery_client.tables:
            report = Check_Report_GCP(metadata=self.metadata(), resource=table)
            report.status = "PASS"
            report.status_extended = (
                f"Table {table.name} is encrypted with Customer-Managed Keys (CMKs)."
            )
            if not table.cmk_encryption:
                report.status = "FAIL"
                report.status_extended = f"Table {table.name} is not encrypted with Customer-Managed Keys (CMKs)."
            findings.append(report)

        return findings