Skip to content

Add WIF credential input to integration and export resources#417

Merged
jaym merged 3 commits intomainfrom
jdm/integrations-wif
Apr 21, 2026
Merged

Add WIF credential input to integration and export resources#417
jaym merged 3 commits intomainfrom
jdm/integrations-wif

Conversation

@jaym
Copy link
Copy Markdown
Contributor

@jaym jaym commented Apr 17, 2026

Summary

Follow-up to #416 (which exposed the computed wif_subject attribute). Makes WIF (Workload Identity Federation) configurable end-to-end for the four resources where the server supports it, so customers can run without long-lived service account JSON / IAM access keys.

  • mondoo_integration_gcp, mondoo_export_gcs_bucket: static credentials.private_key is now optional; new credentials.wif { audience, service_account_email } block as an alternative. ConflictsWith + AtLeastOneOf enforce exactly one auth method.
  • mondoo_integration_aws: new credentials.wif { audience, role_arn } alongside the existing role and key options; all three pair-wise conflict.
  • mondoo_export_bigquery: service_account_key is now optional with RequiresReplace() dropped; new credentials.wif { audience, service_account_email } block gated by ExactlyOneOf so users can flip between static creds and WIF without recreating the export.
  • Read and ImportState round-trip the new WIF fields from the server response.
  • Docs regenerated via go generate ./....

Examples

mondoo_integration_gcp

WIF (no static credentials):

resource "mondoo_integration_gcp" "prod" {
  name       = "gcp-prod"
  project_id = "my-gcp-project"
  credentials = {
    wif = {
      audience              = "https://iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/mondoo-pool/providers/mondoo-provider"
      service_account_email = "mondoo-tf@my-gcp-project.iam.gserviceaccount.com"
    }
  }
}

output "gcp_wif_subject" {
  value = mondoo_integration_gcp.prod.wif_subject
}

Static service account (unchanged behavior):

resource "mondoo_integration_gcp" "prod" {
  name       = "gcp-prod"
  project_id = "my-gcp-project"
  credentials = {
    private_key = file("mondoo-sa.json")
  }
}

mondoo_integration_aws

WIF:

resource "mondoo_integration_aws" "prod" {
  name = "aws-prod"
  credentials = {
    wif = {
      audience = "mondoo"
      role_arn = "arn:aws:iam::123456789012:role/MondooAccess"
    }
  }
}

Existing role and key options are unchanged.

mondoo_export_gcs_bucket

WIF:

resource "mondoo_export_gcs_bucket" "exports" {
  name        = "gcs-exports"
  scope_mrn   = "//captain.api.mondoo.app/spaces/my-space"
  bucket_name = "my-mondoo-exports"
  credentials = {
    wif = {
      audience              = "https://iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/mondoo-pool/providers/mondoo-provider"
      service_account_email = "mondoo-exports@my-gcp-project.iam.gserviceaccount.com"
    }
  }
}

mondoo_export_bigquery

WIF (note: credentials is a new top-level block added specifically to host wif; the static service_account_key stays at top level for backward compatibility):

resource "mondoo_export_bigquery" "exports" {
  name       = "bq-exports"
  scope_mrn  = "//captain.api.mondoo.app/spaces/my-space"
  dataset_id = "my-gcp-project.mondoo_exports"
  credentials = {
    wif = {
      audience              = "https://iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/mondoo-pool/providers/mondoo-provider"
      service_account_email = "mondoo-bq@my-gcp-project.iam.gserviceaccount.com"
    }
  }
}

Static service account (unchanged aside from being optional and no longer triggering replace):

resource "mondoo_export_bigquery" "exports" {
  name                = "bq-exports"
  scope_mrn           = "//captain.api.mondoo.app/spaces/my-space"
  dataset_id          = "my-gcp-project.mondoo_exports"
  service_account_key = file("mondoo-bq-sa.json")
}

Test plan

  • go build ./... and go vet ./... pass (verified locally).
  • go generate ./... regenerates docs with only the expected diff.
  • Acceptance tests pass in CI (require MONDOO_CONFIG_*, not runnable locally).
  • Apply a WIF-only config for each of the four resources against a real Mondoo space; confirm wif_subject populates.
  • Update a mondoo_export_bigquery resource from service_account_key to credentials.wif and confirm in-place update (no replace), validating the RequiresReplace removal.
  • Verify validation errors:
    • Setting both service_account_key and credentials.wif on mondoo_export_bigqueryExactlyOneOf error.
    • Setting credentials = {} on the other three resources → AtLeastOneOf error.
    • Setting two of role/key/wif on mondoo_integration_aws → ConflictsWith error.

Notes

  • No mondoo-go bump is needed — the input / output fields are already present in the pinned version.
  • The deprecated mondoo_gcs_bucket_export resource is intentionally left untouched.

🤖 Generated with Claude Code

Commit bd71f95 exposed the server-computed `wif_subject` as a read-only
attribute. This commit makes WIF usable end-to-end by allowing customers
to configure WIF credentials in Terraform instead of static service
account JSON / IAM access keys.

- mondoo_integration_gcp, mondoo_export_gcs_bucket: `credentials.private_key`
  is now optional; adds `credentials.wif { audience, service_account_email }`
  as an alternative. ConflictsWith + AtLeastOneOf enforce exactly one
  auth method.
- mondoo_integration_aws: adds `credentials.wif { audience, role_arn }`
  alongside the existing `role` and `key` options.
- mondoo_export_bigquery: `service_account_key` is now optional with
  RequiresReplace dropped; adds `credentials.wif { audience, service_account_email }`
  gated by ExactlyOneOf so users can flip between static creds and WIF
  without recreating the export.

Read and ImportState round-trip the new WIF fields (wifAudience /
wifServiceAccountEmail for GCP-family, wifAudience / wifRoleArn for AWS)
from the server response.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jaym jaym marked this pull request as ready for review April 17, 2026 14:19
Service account impersonation is an optional step for GCP workload
identity federation - customers can also grant the identity pool's
principal direct access to the resource. Only send the field to the
server when it is set, and map an empty server response back to null
in state so an unset value does not churn in subsequent plans.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@mondoo-code-review mondoo-code-review Bot left a comment

Choose a reason for hiding this comment

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

Adds workload identity federation (WIF) credential support to AWS, GCP, BigQuery, and GCS integrations as an alternative to static keys.

Comment thread internal/provider/export_bigquery.go Outdated
Comment thread internal/provider/export_gcs_bucket.go Outdated
Comment thread internal/provider/integration_aws_resource.go
vjeffrey
vjeffrey previously approved these changes Apr 17, 2026
- Replace the per-attribute ConflictsWith + AtLeastOneOf pairing with a
  single ExactlyOneOf ConfigValidator on the GCP integration, GCS bucket
  export, and AWS integration. BigQuery already used ExactlyOneOf; drop
  the redundant string-level ConflictsWith on its service_account_key.
- Require both WifAudience and WifRoleArn to be non-empty before
  importing a wif credential block on the AWS integration so a partial
  server response cannot write a state that fails validation on the
  next plan.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@mondoo-code-review mondoo-code-review Bot left a comment

Choose a reason for hiding this comment

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

WIF credential validation simplified and import logic hardened as requested.

@jaym jaym merged commit b8f66ee into main Apr 21, 2026
13 checks passed
@jaym jaym deleted the jdm/integrations-wif branch April 21, 2026 13:18
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants