From 0d32993e3bba54dd9305fa21fb6bf65ffbfa20c6 Mon Sep 17 00:00:00 2001 From: wowsofine Date: Sun, 7 Jun 2026 14:07:55 +0800 Subject: [PATCH] Improve GCP workload identity federation evidence --- skills/cloud/gcp-review/SKILL.md | 22 ++++- .../cloud/gcp-review/benchmark-checklist.md | 93 +++++++++++++++++++ 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/skills/cloud/gcp-review/SKILL.md b/skills/cloud/gcp-review/SKILL.md index 8c61f49e..24814444 100644 --- a/skills/cloud/gcp-review/SKILL.md +++ b/skills/cloud/gcp-review/SKILL.md @@ -52,6 +52,7 @@ The CIS Google Cloud Platform Foundation Benchmark v2.0.0 is a consensus-driven - Access to GCP infrastructure-as-code files (Terraform `.tf`, Deployment Manager `.yaml`/`.jinja`) - gcloud CLI output or configuration exports (if reviewing a live environment) - IAM policy bindings and org policy definitions +- Workload Identity Federation pools, providers, external principal bindings, and CI/OIDC trust policy definitions - VPC and firewall rule definitions - Cloud Audit Logs configuration @@ -100,7 +101,7 @@ Produce the final report using the structure defined in the Output Format sectio | Severity | Definition | Examples | |----------|-----------|----------| | **Critical** | Immediate risk of data breach or unauthorized access | Public GCS buckets, firewall rules allowing 0.0.0.0/0 on SSH/RDP, Cloud SQL with public IP and no SSL, user-managed SA keys with admin roles | -| **High** | Significant security gap that materially weakens posture | Default service accounts with broad scopes, missing Cloud Audit Logs, no VPC flow logs, instances with public IPs | +| **High** | Significant security gap that materially weakens posture | Default service accounts with broad scopes, missing Cloud Audit Logs, no VPC flow logs, instances with public IPs, broad Workload Identity Federation principal sets | | **Medium** | Control gap that should be addressed in normal cycle | Missing log metric filters, DNSSEC not enabled, Shielded VM not enabled, uniform bucket access not set | | **Low** | Hardening recommendation or defense-in-depth measure | OS Login not enabled, serial port access not explicitly disabled, BigQuery tables without CMEK | | **Informational** | Best practice observation, no direct security impact | Default network still exists (non-production), naming conventions, documentation gaps | @@ -138,6 +139,16 @@ Produce the final report using the structure defined in the Output Format sectio | 6 | Cloud SQL | X | Y | Z | nn% | | 7 | BigQuery | X | Y | Z | nn% | +### Identity Federation Evidence + +| Control Area | Status | Evidence Reviewed | Risk Notes | +|---|---|---|---| +| WIF provider issuer and audience | Pass / Fail / Not Evaluable | `` | `` | +| Attribute mapping and condition | Pass / Fail / Not Evaluable | `` | `` | +| Service account impersonation binding scope | Pass / Fail / Not Evaluable | `` | `` | +| External principal TokenCreator grants | Pass / Fail / Not Evaluable | `` | `` | +| CI workload claim binding | Pass / Fail / Not Evaluable | `` | `` | + ### Detailed Findings #### [CIS X.Y] @@ -190,10 +201,11 @@ Produce the final report using the structure defined in the Output Format sectio 1. **Missing org-level policy checks.** Many CIS controls (e.g., 3.1 default network, 5.1 public access) can be enforced via org policies. Check both resource-level configuration and org policy constraints. 2. **Confusing GCP-managed vs. user-managed service account keys.** CIS 1.4 only flags user-managed keys (created via `google_service_account_key`). Keys automatically managed by GCP services are acceptable. -3. **VPC flow logs must be per-subnet.** CIS 3.8 requires flow logs on every subnet, not just the VPC. Each `google_compute_subnetwork` must have a `log_config` block. -4. **Cloud SQL authorized_networks vs. private IP.** CIS 6.5 flags `0.0.0.0/0` in authorized networks, but CIS 6.6 goes further and recommends disabling public IP entirely in favor of private networking. -5. **BigQuery dataset-level vs. table-level CMEK.** CIS 7.2 checks table-level encryption, while CIS 7.3 checks the dataset default. Both should be evaluated independently. -6. **Default compute service account identification.** The default SA follows the pattern `PROJECT_NUMBER-compute@developer.gserviceaccount.com`. Grep for this pattern, not just the string "default." +3. **Treating Workload Identity Federation as automatically safe.** WIF removes long-lived keys, but broad `principalSet` members, missing `attribute_condition`, or project-level impersonation roles can create a keyless privilege escalation path. +4. **VPC flow logs must be per-subnet.** CIS 3.8 requires flow logs on every subnet, not just the VPC. Each `google_compute_subnetwork` must have a `log_config` block. +5. **Cloud SQL authorized_networks vs. private IP.** CIS 6.5 flags `0.0.0.0/0` in authorized networks, but CIS 6.6 goes further and recommends disabling public IP entirely in favor of private networking. +6. **BigQuery dataset-level vs. table-level CMEK.** CIS 7.2 checks table-level encryption, while CIS 7.3 checks the dataset default. Both should be evaluated independently. +7. **Default compute service account identification.** The default SA follows the pattern `PROJECT_NUMBER-compute@developer.gserviceaccount.com`. Grep for this pattern, not just the string "default." --- diff --git a/skills/cloud/gcp-review/benchmark-checklist.md b/skills/cloud/gcp-review/benchmark-checklist.md index 204ab38f..12f8c811 100644 --- a/skills/cloud/gcp-review/benchmark-checklist.md +++ b/skills/cloud/gcp-review/benchmark-checklist.md @@ -76,6 +76,99 @@ These roles should be granted at the service account level, not project level. Check for key rotation mechanisms or expiration policies on service account keys. +### Supplemental IAM Check -- Workload Identity Federation and External OIDC Boundaries + +Workload Identity Federation (WIF) is preferred over long-lived service account keys, but an overly broad federation policy can let external workloads impersonate service accounts without a key. Treat WIF as an identity boundary that needs explicit provider, attribute, and service-account binding evidence. + +**Grep patterns:** + +``` +# Workload Identity Federation provider resources +google_iam_workload_identity_pool_provider +workload_identity_pool_provider +attribute_mapping +attribute_condition + +# External principals and broad principal sets +principalSet://iam.googleapis.com/.*/attribute.repository/\* +principalSet://iam.googleapis.com/.*/attribute.owner/\* +principal://iam.googleapis.com/ +roles/iam.workloadIdentityUser +roles/iam.serviceAccountTokenCreator + +# GitHub Actions / CI OIDC providers +issuer_uri = "https://token.actions.githubusercontent.com" +attribute.repository +attribute.ref +attribute.workflow +attribute.actor +``` + +**Risk patterns:** + +```hcl +# BAD: GitHub Actions OIDC provider without repository/ref restriction +resource "google_iam_workload_identity_pool_provider" "github" { + oidc { + issuer_uri = "https://token.actions.githubusercontent.com" + } + attribute_mapping = { + "google.subject" = "assertion.sub" + "attribute.repository" = "assertion.repository" + } + # Missing attribute_condition binding the trusted org/repo/ref/workflow +} + +# BAD: Any repository in the provider pool can impersonate the service account +resource "google_service_account_iam_member" "wif" { + service_account_id = google_service_account.deploy.name + role = "roles/iam.workloadIdentityUser" + member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.pool.name}/attribute.repository/*" +} +``` + +**Evidence to collect:** + +- [ ] Provider issuer is the expected external IdP and uses OIDC/SAML settings appropriate for that IdP. +- [ ] `attribute_mapping` includes stable attributes required for policy decisions, such as `attribute.repository`, `attribute.ref`, `attribute.workflow`, or cloud-specific tenant/application IDs. +- [ ] `attribute_condition` restricts the trusted organization, repository, branch/tag, workflow, audience, or equivalent IdP claims. +- [ ] `roles/iam.workloadIdentityUser` bindings are granted on the target service account, not broadly at project level. +- [ ] `principalSet` members avoid wildcard repository, owner, namespace, or subject patterns unless a documented exception exists. +- [ ] External principals are not also granted `roles/iam.serviceAccountTokenCreator` without a compensating approval and audit trail. +- [ ] Audit logs or CI configuration tie the federated identity to the expected workload, branch, and deployment environment. + +**Remediation:** + +```hcl +resource "google_iam_workload_identity_pool_provider" "github" { + workload_identity_pool_id = google_iam_workload_identity_pool.ci.workload_identity_pool_id + workload_identity_pool_provider_id = "github-actions" + + oidc { + issuer_uri = "https://token.actions.githubusercontent.com" + } + + attribute_mapping = { + "google.subject" = "assertion.sub" + "attribute.repository" = "assertion.repository" + "attribute.ref" = "assertion.ref" + "attribute.workflow" = "assertion.workflow" + } + + attribute_condition = <<-CEL + assertion.repository == "trusted-org/trusted-repo" && + assertion.ref == "refs/heads/main" && + assertion.workflow == "deploy.yml" + CEL +} + +resource "google_service_account_iam_member" "github_deploy" { + service_account_id = google_service_account.deploy.name + role = "roles/iam.workloadIdentityUser" + member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.ci.name}/attribute.repository/trusted-org/trusted-repo" +} +``` + ### CIS 1.8 -- Ensure that Separation of Duties is Enforced While Assigning Service Account Related Roles to Users Verify that no user has both `iam.serviceAccountUser` and `iam.serviceAccountAdmin` simultaneously.