Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions terraform/environments/gcp/ci-cd-permissions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,33 @@ Workload Identity Federation endpoint for a short-lived SA access token, and set

### Attribute condition

The WIF provider is configured with `attribute_condition = "assertion.repository == 'LeanerCloud/CUDly'"`.
Only workflows from that exact repository can impersonate the service account. To change the allowed
repo, update `github_repo` in `terraform.tfvars` and re-apply.
The WIF provider enforces **two** conditions simultaneously:

```text
assertion.repository == '<github_repo>' && assertion.ref == '<deploy_ref>'
```

Only workflows running from the exact repository **and** the exact ref (branch) configured in
`terraform.tfvars` can obtain a GCP token. Any other branch, PR, fork, tag, or
`workflow_dispatch` from a different ref is rejected with:

> `unauthorized_client: The given credential is rejected by the attribute condition.`

**Keeping `deploy_ref` in sync with the active deploy branch is critical.** When the base
deploy branch changes (e.g. a long-running feature branch is merged into `main`), the operator
must update `deploy_ref` in `terraform.tfvars` and re-apply this module before the next deploy.

The default value of `deploy_ref` is `refs/heads/main`. A plain `terraform apply` with no
override in `terraform.tfvars` restores the correct condition for deploys from `main`.

To verify the currently-applied condition without applying:

```bash
gcloud iam workload-identity-pools providers describe github-actions \
--workload-identity-pool=github-actions \
--location=global \
--project=<PROJECT_ID> \
--format="value(attributeCondition)"
```

To change the allowed repo, update `github_repo` in `terraform.tfvars` and re-apply.
5 changes: 5 additions & 0 deletions terraform/environments/gcp/ci-cd-permissions/github_oidc.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ resource "google_iam_workload_identity_pool_provider" "github" {

# Restrict to the specific repo AND only allow the designated deploy branch.
# PRs, tags, forks, and workflow_dispatch from other refs are blocked.
#
# deploy_ref defaults to refs/heads/main. Override in terraform.tfvars only
# when temporarily deploying from a feature branch; flip back to main once
# that branch merges. Forgetting to flip locks out main-branch deploys with
# "unauthorized_client: The given credential is rejected by the attribute condition."
attribute_condition = "assertion.repository == '${var.github_repo}' && assertion.ref == '${var.deploy_ref}'"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,18 @@ github_repo = "LeanerCloud/CUDly"
# Only exact-match pushes to this branch can obtain a GCP token.
# PRs, tags, forks, and workflow_dispatch from other refs are blocked.
#
# DEFAULT: refs/heads/main
# The default in variables.tf is refs/heads/main, which is correct for normal
# operation. Override here ONLY when temporarily deploying from a feature branch.
#
# IMPORTANT: When the active deploy branch changes (e.g. a long-running feature
# branch merges into main), update this value and re-apply the module. Forgetting
# to flip back to refs/heads/main will lock out all future main-branch deploys
# with: "The given credential is rejected by the attribute condition."
#
# To verify the currently-applied condition in GCP (read-only):
# gcloud iam workload-identity-pools providers describe github-actions \
# --workload-identity-pool=github-actions --location=global \
# --project=<PROJECT_ID> --format="value(attributeCondition)"
#
deploy_ref = "refs/heads/main"
Loading