You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Parent:#1400 · Labels:enhancement, area/infra (auto, infra/**) · Size: M · Depends on: none
Goal. Light infra: the source-keyed GCS bucket and a dedicated least-privilege write identity via the existing WIF federation — and explicitly no GKE host cluster (GitHub Pages is the host).
Scope.
New Terraform under infra/evidence-dashboard/ (sibling of infra/uat-gcp-account/, reusing its backend.tf/providers.tf/variables.tf conventions and the eidosx project default).
Bucket (data) with hardening: public-access-prevention, uniform bucket-level access, object versioning, soft-delete, access logging. The bucket stays locked/non-public — the public surface is GitHub Pages, not the bucket. (Optionally a staging bucket; no four-bucket worker model is needed since there are no workers.)
Dedicated write-only publish SA. A NEW SA (e.g. evidence-publish@eidosx) bound to onlyroles/storage.objectCreator on the data bucket, impersonated through the existinggithub-actions-pool provider (uat-gcp.yaml:53). Do not reuse or scope down the shared github-actions@eidosx SA — it holds project-wide objectAdmin/objectViewer and more (infra/uat-gcp-account/iam.tf:19-23); the publish SA's compromise must not reach any of that. No new federation beyond the reused pool; no static keys.
Read SA (objectViewer) for the build CI that pulls all CTRFs to generate the site (GP4/GP5) — or have the build job impersonate a read-only SA; least-privilege either way.
Per-SA WIF subject/attribute condition. Bind the publish SA's roles/iam.workloadIdentityUser member to a condition admitting only the GP2 ingest workflow/job (decide push-event vs workflow_run up front — it changes the OIDC sub/event_name claim). The github-actions-pool provider is owned by infra/demo-api-server; do not tighten/loosen the shared provider — scope per-SA, or stand up a separate provider under infra/evidence-dashboard/ if a provider-level condition is unavoidable. Confirm no demo-api-server regression.
Explicitly no GKE host cluster — document in the Terraform README that the public surface is GitHub Pages and the only standing cost is negligible GCS storage (a deliberate divergence from Epic: TG — Deploy & operate the AICR TestGrid instance #1263 TG1).
Out of scope. The ingest job (GP2); the generator (GP4); Pages publish (GP5). Any worker/API/UI compute.
Tests.terraform validate + terraform plan (dry-run, no apply); tflint/checkov if wired for infra/. Assert: data bucket has public-access-prevention + uniform bucket-level access; the publish SA is a new SA whose only binding is objectCreator (a policy test rejecting any objectViewer/objectAdmin/compute binding and asserting it is not github-actions@eidosx); the per-SA subject condition admits only the GP2 context; no static-key resources; no GKE cluster resource is declared.
Acceptance.infra/evidence-dashboard/ plans cleanly against eidosx; the data bucket is hardened and locked (non-public); a dedicated write-only objectCreator publish SA + a read-only SA are bound least-privilege via the existing github-actions-pool federation with a per-SA subject condition scoped to the GP2 ingest workflow (no shared-provider regression); no host cluster is provisioned.
Child of #1400 · staged from docs/design/013-interim-evidence-dashboard.md (GP3).
Parent: #1400 · Labels:
enhancement,area/infra(auto,infra/**) · Size: M · Depends on: noneGoal. Light infra: the source-keyed GCS bucket and a dedicated least-privilege write identity via the existing WIF federation — and explicitly no GKE host cluster (GitHub Pages is the host).
Scope.
infra/evidence-dashboard/(sibling ofinfra/uat-gcp-account/, reusing itsbackend.tf/providers.tf/variables.tfconventions and theeidosxproject default).evidence-publish@eidosx) bound to onlyroles/storage.objectCreatoron the data bucket, impersonated through the existinggithub-actions-poolprovider (uat-gcp.yaml:53). Do not reuse or scope down the sharedgithub-actions@eidosxSA — it holds project-wideobjectAdmin/objectViewerand more (infra/uat-gcp-account/iam.tf:19-23); the publish SA's compromise must not reach any of that. No new federation beyond the reused pool; no static keys.objectViewer) for the build CI that pulls all CTRFs to generate the site (GP4/GP5) — or have the build job impersonate a read-only SA; least-privilege either way.roles/iam.workloadIdentityUsermember to a condition admitting only the GP2 ingest workflow/job (decide push-event vsworkflow_runup front — it changes the OIDCsub/event_nameclaim). Thegithub-actions-poolprovider is owned byinfra/demo-api-server; do not tighten/loosen the shared provider — scope per-SA, or stand up a separate provider underinfra/evidence-dashboard/if a provider-level condition is unavoidable. Confirm no demo-api-server regression.Out of scope. The ingest job (GP2); the generator (GP4); Pages publish (GP5). Any worker/API/UI compute.
Key files. New
infra/evidence-dashboard/*.tf(+ README); referenceinfra/uat-gcp-account/variables.tf:15-18(eidosxdefault),infra/uat-gcp-account/iam.tf:17-23(shared-SA caveat),backend.tf; WIF provider/SAuat-gcp.yaml:53-54..github/labeler.yml:51-53(infra/**→area/infra, no change needed).Tests.
terraform validate+terraform plan(dry-run, no apply);tflint/checkovif wired forinfra/. Assert: data bucket has public-access-prevention + uniform bucket-level access; the publish SA is a new SA whose only binding isobjectCreator(a policy test rejecting anyobjectViewer/objectAdmin/compute binding and asserting it is notgithub-actions@eidosx); the per-SA subject condition admits only the GP2 context; no static-key resources; no GKE cluster resource is declared.Acceptance.
infra/evidence-dashboard/plans cleanly againsteidosx; the data bucket is hardened and locked (non-public); a dedicated write-onlyobjectCreatorpublish SA + a read-only SA are bound least-privilege via the existinggithub-actions-poolfederation with a per-SA subject condition scoped to the GP2 ingest workflow (no shared-provider regression); no host cluster is provisioned.Child of #1400 · staged from
docs/design/013-interim-evidence-dashboard.md(GP3).