Skip to content

sec(iac): federation bundle generator still emits a subject-less AWS trust policy (CLI bundle exploitable) #1640

Description

@cristim

The federation onboarding bundle generator still hands customers a
subject-less AWS trust policy. #1543 closed the hole in the checked-in
CloudFormation template (iac/federation/aws-target/cloudformation/template.yaml,
PR #1602), but the internal/iacfiles generator that produces the
customer-facing bundle was left untouched because internal/ was owned by
concurrent in-flight branches at the time.

The exploit is identical to #1543: a role in the customer's AWS account
carrying ec2:PurchaseReservedInstancesOffering,
savingsplans:CreateSavingsPlan and rds:PurchaseReservedDBInstancesOffering,
assumable by every identity the documented accounts.google.com issuer can
mint. Those are irreversible multi-year spend commitments.

Gaps

1. CLI bundle creates a subject-less role (exploitable, not fail-closed)

internal/iacfiles/templates/aws-wif-cli.sh.tmpl:17 declares
OIDC_SUBJECT_CLAIM="${OIDC_SUBJECT_CLAIM:-}" and documents it as "Optional".
The else branch at :57-70 then builds the trust policy with only the
:aud condition and no :sub:

"Condition": {"StringEquals": {"${OIDC_HOST}:aud": "${OIDC_AUDIENCE}"}}

This path never goes through CloudFormation, so nothing rejects it.
internal/api/handler_federation.go:401,415 makes format=cli a first-class
user-selectable download (cliScriptSpec -> templates/aws-wif-cli.sh.tmpl),
so a customer who picks the CLI bundle gets exactly the role #1543 describes.

This is the exploitable gap. The remaining two are fail-closed but broken
or misleading.

2. CloudFormation deploy script omits the now-required parameter

internal/iacfiles/templates/aws-cfn-deploy.sh.tmpl:34-38 passes
--parameter-overrides for OIDCIssuerURL, OIDCIssuerHost, OIDCAudience
and RoleName only. Now that OIDCSubjectClaim is required with no default,
this script fails with Parameters: [OIDCSubjectClaim] must have values.
Fail-closed, but the CloudFormation onboarding flow is broken until the script
forwards the subject.

buildCFParamsJSON in internal/api/handler_federation.go and
internal/iacfiles/templates/aws-wif-cf-params.json.tmpl have the same
omission.

3. tfvars template contradicts the Terraform module

internal/iacfiles/templates/aws-wif.tfvars.tmpl:14-15 emits:

# Optional: restrict trust to a specific workload subject claim
# oidc_subject_claim = ""

oidc_subject_claim in iac/federation/aws-target/terraform/variables.tf:28-42
is REQUIRED (no default, plus a validation rejecting empty values).
Fail-closed, but the generated file tells the operator the opposite of what
the module enforces.

Fix

  • Thread the subject claim through the generator so every bundle format emits
    it, and make it required rather than optional in each.
  • aws-wif-cli.sh.tmpl: drop the subject-less else branch entirely, mirroring
    what PR sec(iac/aws): require OIDC subject claim in aws-target CloudFormation #1602 did to the CloudFormation template. Fail loudly when
    OIDC_SUBJECT_CLAIM is unset instead of silently producing an open role.
  • aws-cfn-deploy.sh.tmpl, aws-wif-cf-params.json.tmpl, buildCFParamsJSON:
    add OIDCSubjectClaim.
  • aws-wif.tfvars.tmpl: emit oidc_subject_claim uncommented and drop the
    "Optional" label.
  • Apply the same $/* rejection PR sec(iac/aws): require OIDC subject claim in aws-target CloudFormation #1602 added to the template parameters:
    the trust policy is an IAM policy document, so a subject of
    ${accounts.google.com:sub} expands to the token's own sub claim and
    becomes a tautology matching every identity.
  • Regression test: assert the rendered aws-wif-cli.sh.tmpl output contains a
    :sub condition, and that rendering without a subject claim errors rather
    than emitting a policy.

Tracked in known_issues/13_iac_aws_target.md.

Refs #1543

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions