Skip to content

feat(blueprints): wire CMEK for Spanner, scope firewall targets for bastion - #380

Open
LeonxLJX wants to merge 5 commits into
google:mainfrom
LeonxLJX:fix/374-blueprints-iam-cmek-firewall
Open

LeonxLJX wants to merge 5 commits into
google:mainfrom
LeonxLJX:fix/374-blueprints-iam-cmek-firewall

Conversation

@LeonxLJX

Copy link
Copy Markdown

Fixes #374.

Summary

This PR enhances workload blueprints with CMEK wiring, resource-scoped firewall rules, and bastion VM hardening.

Changes Made

fedramp-high/cloud-spanner

  • variables.tf: Added optional kms_key_name variable (default: null) accepting a fully qualified KMS crypto key self link.
  • main.tf: Wired kms_key_name = var.kms_key_name into the spanner-instance-se module. When a key is provided, Spanner data at rest is encrypted with CMEK instead of GKEK.
  • main.tf: Added google_project_service_identity.spanner and google_kms_crypto_key_iam_member.spanner_sa_kms_access resources (guarded with count) that grant the Spanner API service identity roles/cloudkms.cryptoKeyEncrypterDecrypter on the CMEK key when configured.

il5/bastion-pattern

  • main.tf: Scoped the ingress firewall rule with target_tags = ["bastion"] instead of applying it to all instances in the network.
  • main.tf: Added tags = ["bastion"] to the bastion VM so the firewall rule matches only the intended target.

Security Impact

  • CMEK for Spanner: Allows operators to bring their own encryption key for Cloud Spanner data-at-rest, meeting FedRAMP IL5/IL6 data sovereignty requirements.
  • Least-privilege firewall: Restricts the bastion web-access firewall rule to VMs tagged bastion, preventing accidental application to other workload VMs on the shared VPC.
  • Audit logging: Both affected blueprints already retain log_config { metadata = "INCLUDE_ALL_METADATA" } on their firewall rules.

…rules

- fedramp-high/cloud-spanner: add kms_key_name variable, wire to spanner module, grant Spanner SA KMS encryption/decryption access
- il5/bastion-pattern: scope ingress firewall to target_tags=['bastion'], add matching VM tag
- il5/postgresql: firewall already has logging (no additional changes needed - Cloud SQL uses PSA)
@google-cla

google-cla Bot commented Oct 28, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@github-actions github-actions Bot added Framework - IL5 DoD Impact Level 5 (IL5) compliance regime and controls Framework - FedRAMP High FedRAMP High compliance regime and controls Scope - Blueprint Related to solution blueprints in the blueprints directory labels Oct 28, 2026
@LeonxLJX

Copy link
Copy Markdown
Author

刚 force push 了 erraform fmt 修复 Repository Lint(for_each map key 对齐)。CI 会重新跑。

@LeonxLJX

Copy link
Copy Markdown
Author

Hi, I just signed the Google Contributor License Agreement (CLA). Could someone please re-run the \cla/google\ check? Thanks!

@aghassemlouei aghassemlouei added Enhancement New feature or request Level of Effort - Low Quick, well-defined tasks with no unknowns; takes a few hours up to one day to complete Priority - Medium Standard features and non-blocking bugs; important for the current milestone but not urgent Security Something is insecure or can be secured labels Oct 29, 2026

@aghassemlouei aghassemlouei left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for wiring bastion-pattern firewall scoping and cloud-spanner CMEK toward #374. Running terraform validate and terraform plan surfaced three issues documented inline:

  1. blueprints/fedramp-high/cloud-spanner/main.tf fails terraform validate with Unsupported argument: An argument named "kms_key_name" is not expected here because modules/spanner-instance-se configures kms_key_name per database inside var.databases, not at the module root.
  2. blueprints/fedramp-high/cloud-spanner/main.tf omits depends_on edges from google_project_service.spanner_api to google_project_service_identity.spanner and from google_kms_crypto_key_iam_member.spanner_sa_kms_access to module.cloud-spanner, causing fresh CMEK deployments to race the KMS IAM grant.
  3. Only 2 of the blueprints tracked in #374 are covered here while items in cloud-composer-environment, blueprints/il5/postgresql, and resource-scoped IAM remain open; please switch Fixes #374. to Part of #374. and populate the .github/pull_request_template.md sections.

source = "../../../modules/spanner-instance-se"
project_id = var.main_project_id
edition = var.edition
kms_key_name = var.kms_key_name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modules/spanner-instance-se does not declare a top-level kms_key_name variable, so terraform validate fails here with Error: Unsupported argument: An argument named "kms_key_name" is not expected here. In modules/spanner-instance-se/variables.tf at line 43 and main.tf at line 100, kms_key_name is an attribute on each entry of the databases map via databases = { (var.database_name) = { kms_key_name = var.kms_key_name, ... } }. Wire kms_key_name = var.kms_key_name inside databases[(var.database_name)], update the variable description in variables.tf since CMEK encrypts the Spanner database rather than the instance, and regenerate README.md with tools/tfdoc.py.

Comment on lines 59 to 75
depends_on = [google_project_service.spanner_api]
}

# Grant Spanner service identity access to CMEK key when provided
resource "google_project_service_identity" "spanner" {
provider = google-beta
project = var.main_project_id
service = "spanner.googleapis.com"
count = var.kms_key_name != null ? 1 : 0
}

resource "google_kms_crypto_key_iam_member" "spanner_sa_kms_access" {
count = var.kms_key_name != null ? 1 : 0
crypto_key_id = var.kms_key_name
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
member = google_project_service_identity.spanner[0].member
} No newline at end of file

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a fresh project with var.kms_key_name != null, google_project_service_identity.spanner needs depends_on = [google_project_service.spanner_api] and module.cloud-spanner needs depends_on = [google_project_service.spanner_api, google_kms_crypto_key_iam_member.spanner_sa_kms_access] so Spanner database creation waits until the Spanner service agent holds roles/cloudkms.cryptoKeyEncrypterDecrypter on var.kms_key_name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement New feature or request Framework - FedRAMP High FedRAMP High compliance regime and controls Framework - IL5 DoD Impact Level 5 (IL5) compliance regime and controls Level of Effort - Low Quick, well-defined tasks with no unknowns; takes a few hours up to one day to complete Priority - Medium Standard features and non-blocking bugs; important for the current milestone but not urgent Scope - Blueprint Related to solution blueprints in the blueprints directory Security Something is insecure or can be secured

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhancement] blueprints/il5, fedramp-high: scope project-wide IAM bindings to resources, wire CMEK, and restrict firewall targets

2 participants