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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
33 changes: 33 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
.DS_Store
**/.DS_Store

# Local developer notes and machine-specific setup — not for version control
/local/

# Local .terraform directories
**/.terraform/*
**/.terraform.lock.hcl
Expand Down Expand Up @@ -36,3 +42,30 @@ override.tf.json

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

# Temporary soong clone for generating ABFS patches
.soong_r4_check/
# Go compiled binaries
**/bin/
tools/horizon/horizon

# -----------------------------------------------------------------------------
# JavaScript / Node (dependencies and local caches — install via npm ci / pnpm)
# -----------------------------------------------------------------------------
**/node_modules/

# Vite default build output (CI/Docker runs npm run build; do not commit)
**/dist/
**/dist-ssr/

# Vite dev cache
**/.vite/

# TypeScript incremental build metadata
*.tsbuildinfo

npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
127 changes: 80 additions & 47 deletions docs/deployment_guide.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docs/gitops.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- [OAuth2 Proxy](#oauth-proxy)
- [Token Injector](#token-injector)
- [Post Jobs](#post-jobs)
- [Config Connector webhook reliability](#config-connector-webhook-reliability)

## GitOps overview

Expand Down Expand Up @@ -317,3 +318,8 @@ A collection of scripts that handle application-specific configurations when sta
- **mtk-connect-post** – Configures MTK Connect after installation, ensuring it is properly set up for use.
- **mtk-connect-post-key** – Generates and configures necessary API keys for MTK Connect.
- **gerrit-post** – Uses the gerrit-admin account to perform the initial setup and configuration of Gerrit.

## Config Connector webhook reliability

Config Connector webhook TLS verification is centralized via CronJob in
`gitops/templates/config-connector.yaml`, while module charts keep ordered sync waves.
59 changes: 59 additions & 0 deletions docs/guides/terraform_sdv_wi_workload_identity_bindings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Terraform `sdv-wi`: Workload Identity bindings on Google service accounts

This guide explains how the **`sdv-wi`** module (`terraform/modules/sdv-wi`) wires **GKE Workload Identity (WI)** and why **IAM bindings must be attached to each Google service account (GSA)**, not to the **project**.

For Argo Workflows–specific KSA/GSA naming and pod behavior, see **[Argo Workflows and Google Cloud Workload Identity](argo_workflows_workload_identity.md)**.

---

## Symptom

Workloads that call Google APIs using WI (for example **External Secrets Operator** reading **Secret Manager** via a `SecretStore` with `gcpsm` + `workloadIdentity`) can fail during token exchange with:

```text
Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).
```

Example: syncing a secret such as `github-app-id-b64` from GSM into the cluster.

---

## Root cause

For GKE Workload Identity, the Kubernetes service account (KSA) must be allowed to **impersonate** the target GSA. Google’s documented binding is:

- **Role:** `roles/iam.workloadIdentityUser`
- **Resource:** the **Google service account** (not the project)
- **Member:** `serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KUBERNETES_SA_NAME]`

Granting `roles/iam.workloadIdentityUser` at **project** scope to that member does **not** replace the per–service-account binding required for impersonation. Clients then fail when obtaining an access token for the GSA.

---

## What the `sdv-wi` module does

1. **`google_service_account.sdv_wi_sa`** — Creates one GSA per entry in `var.wi_service_accounts` (for example `gke-argo-workflows-sa`, `gke-argocd-sa`).

2. **`google_project_iam_member.sdv_wi_sa_iam_2`** — Grants **project-level roles** to each GSA **email** (Secret Manager, storage, etc., as defined in `roles` for each SA). This is unchanged.

3. **`google_service_account_iam_member.sdv_wi_sa_workload_identity_user`** — For each `(GSA, KSA)` pair in `gke_sas`, grants **`roles/iam.workloadIdentityUser`** on **that GSA** to the WI member
`serviceAccount:PROJECT_ID.svc.id.goog[gke_ns/gke_sa]`.

The third block is the **Workload Identity** link between cluster identities and GSAs.

---

## Terraform apply notes

After switching from project-level WI bindings to **GSA-level** `google_service_account_iam_member`:

- **Plan** will show **destroy** of old `google_project_iam_member` resources that previously attempted WI at project scope (if still in state), and **create** of `google_service_account_iam_member` resources.
- **Short risk:** brief window while bindings are replaced; re-run apply if needed.
- No change is required in **gitops** KSA annotations (`iam.gke.io/gcp-service-account`) if they already point at the correct GSA email.

---

## References

- [Authenticate to Google Cloud APIs from GKE workloads](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) (Google Cloud)
- Module: `terraform/modules/sdv-wi/main.tf`
Loading
Loading