feat(deploy): issue app credentials through Forgejo and OpenBao #26

Merged
gitchegumi merged 2 commits from kiyi/automatic-deploy-credentials into main 2026-09-07 21:02:10 -05:00
Member

Deployments can opt into Forgejo OIDC → OpenBao → app-scoped Kubernetes credentials, eliminating manually renewed kubeconfigs. Existing callers retain kubeconfig mode during migration; OpenBao mode fails closed.

Adds inspection on the same reusable deployment job so the platform can bind observed repository/ref/audience/workflow claims. Credentials are masked, checked for expected service account and sufficient lifetime, and the OpenBao token is revoked on exit.

Validation: 82 unit tests passed; YAML/Bash scaffold validation and 16 mocked scanner cases passed. Live issuance and negative trust tests await the one-time platform bootstrap. Environment promotion and prerequisite orchestration remain separate unfinished work.

Refs #19.

Deployments can opt into Forgejo OIDC → OpenBao → app-scoped Kubernetes credentials, eliminating manually renewed kubeconfigs. Existing callers retain kubeconfig mode during migration; OpenBao mode fails closed. Adds inspection on the same reusable deployment job so the platform can bind observed repository/ref/audience/workflow claims. Credentials are masked, checked for expected service account and sufficient lifetime, and the OpenBao token is revoked on exit. Validation: 82 unit tests passed; YAML/Bash scaffold validation and 16 mocked scanner cases passed. Live issuance and negative trust tests await the one-time platform bootstrap. Environment promotion and prerequisite orchestration remain separate unfinished work. Refs #19.
feat(deploy): issue app credentials through Forgejo and OpenBao
All checks were successful
Workflow acceptance / acceptance (pull_request) Successful in 49s
Repository security / security-1 (pull_request) Successful in 1m21s
Repository security / security (pull_request) Successful in 0s
Library checks / tests (pull_request) Successful in 1m53s
bdb3b571a0
Add opt-in job identity exchange with app identity/lifetime validation and cleanup. Preserve legacy callers during bootstrap. Add claim-only inspection on the same deployment job and document live acceptance.

Refs #19.
portegumi requested changes 2026-09-07 18:54:26 -05:00
Dismissed
portegumi left a comment

Blocking (P1): retain the required/forbidden authorization checks when replacing the manual issuer. pipeline/credentials.py:96-116 validates returned service-account metadata and a minimum JWT lifetime, then :114-116 exports the credential without checking its effective Kubernetes permissions. The existing platform issuer (infrastructure/deployment/actual-budget/issue-credential.py:60-90) refuses export unless required deployment operations are allowed and clusterrolebindings, PV creation, unrelated namespace access, etc. are denied. Selecting openbao bypasses that existing boundary. A matching SA name is not proof of scope: an accidental additional ClusterRoleBinding leaves both the name and expiry valid. delivery.deploy only checks context and gateway access, so it does not restore the forbidden-permission checks. A controlled probe of deployment_environment handed the kubeconfig to the child with zero authorization probes.

Carry an independently reviewed, app-specific required/forbidden permission contract into automatic issuance and evaluate it with the issued credential against the configured trusted API before launching deployment. Reject excess privileges, missing required privileges, and failed/indeterminate checks. Add negative tests for at least unexpected clusterrolebinding/PV/other-app access and mutation-sensitive assertions for every required probe; do not hard-code Actual's contract for all app repositories. This implements issue #19's existing scope-validation requirement rather than extending the scope to promotion.

Otherwise, credential exchange, same-origin Forgejo requests, redirect rejection, masking, bounded lifetime, cleanup and no fallback in openbao mode look consistent with the paired design. Re-ran 82 unit tests and all 16 scaffold cases successfully. All four exact-head hosted contexts passed. Downloaded security artifact 174 from web run 135 / API run 325: passed=true, zero blockers and zero scanner errors.

Reviewed with the wiki Application Delivery Automation and Homelab Operations Status, platform PR #27 and the existing Actual issuer/RBAC. The wiki explicitly separates owner-accepted production cutover from unfinished bootstrap/promotion/orchestration; those deferred milestones are not additional findings. Live identity discovery and two successful fresh issuances remain acceptance work; no real tokens were issued and no deployment occurred.

Blocking (P1): retain the required/forbidden authorization checks when replacing the manual issuer. pipeline/credentials.py:96-116 validates returned service-account metadata and a minimum JWT lifetime, then :114-116 exports the credential without checking its effective Kubernetes permissions. The existing platform issuer (infrastructure/deployment/actual-budget/issue-credential.py:60-90) refuses export unless required deployment operations are allowed and clusterrolebindings, PV creation, unrelated namespace access, etc. are denied. Selecting openbao bypasses that existing boundary. A matching SA name is not proof of scope: an accidental additional ClusterRoleBinding leaves both the name and expiry valid. delivery.deploy only checks context and gateway access, so it does not restore the forbidden-permission checks. A controlled probe of deployment_environment handed the kubeconfig to the child with zero authorization probes. Carry an independently reviewed, app-specific required/forbidden permission contract into automatic issuance and evaluate it with the issued credential against the configured trusted API before launching deployment. Reject excess privileges, missing required privileges, and failed/indeterminate checks. Add negative tests for at least unexpected clusterrolebinding/PV/other-app access and mutation-sensitive assertions for every required probe; do not hard-code Actual's contract for all app repositories. This implements issue #19's existing scope-validation requirement rather than extending the scope to promotion. Otherwise, credential exchange, same-origin Forgejo requests, redirect rejection, masking, bounded lifetime, cleanup and no fallback in openbao mode look consistent with the paired design. Re-ran 82 unit tests and all 16 scaffold cases successfully. All four exact-head hosted contexts passed. Downloaded security artifact 174 from web run 135 / API run 325: passed=true, zero blockers and zero scanner errors. Reviewed with the wiki Application Delivery Automation and Homelab Operations Status, platform PR #27 and the existing Actual issuer/RBAC. The wiki explicitly separates owner-accepted production cutover from unfinished bootstrap/promotion/orchestration; those deferred milestones are not additional findings. Live identity discovery and two successful fresh issuances remain acceptance work; no real tokens were issued and no deployment occurred.
fix(auth): verify effective deployment permissions before export
All checks were successful
Workflow acceptance / acceptance (pull_request) Successful in 47s
Repository security / security-1 (pull_request) Successful in 1m49s
Repository security / security (pull_request) Successful in 0s
Library checks / tests (pull_request) Successful in 1m59s
e15ecad82e
Load independently reviewed per-repository permission contracts from the pinned library. Use the issued credential for CA-verified SelfSubjectAccessReviews and reject missing, excessive or indeterminate permissions before deployment. Preserve all 19 Actual issuer checks and test every probe failure.
Author
Member

Addressed in e15ecad. Automatic issuance now loads an independently reviewed per-repository contract from the pinned library and performs CA-verified SelfSubjectAccessReviews with the issued token before exporting it. Actual retains all 12 required and 7 forbidden probes from the manual issuer; missing contracts, identity/API mismatches, excess privileges and failed/indeterminate answers stop deployment.

Tests assert the independent probe inventory, every emitted request and trusted CA context, and flip each required/forbidden response individually to prove it blocks export. 86 unit tests and all 16 scaffold cases passed locally. Hosted checks are running.

Addressed in e15ecad. Automatic issuance now loads an independently reviewed per-repository contract from the pinned library and performs CA-verified SelfSubjectAccessReviews with the issued token before exporting it. Actual retains all 12 required and 7 forbidden probes from the manual issuer; missing contracts, identity/API mismatches, excess privileges and failed/indeterminate answers stop deployment. Tests assert the independent probe inventory, every emitted request and trusted CA context, and flip each required/forbidden response individually to prove it blocks export. 86 unit tests and all 16 scaffold cases passed locally. Hosted checks are running.
kiyi requested review from portegumi 2026-09-07 19:06:29 -05:00
portegumi approved these changes 2026-09-07 21:01:11 -05:00
portegumi left a comment

Re-reviewed e15ecad82e. Approved; this supersedes my REQUEST_CHANGES review #455.

The automatic issuer now loads an independently reviewed app-specific contract from the pinned library, binds its repository/role/SA/namespace/API/context, and performs CA-verified SelfSubjectAccessReviews with the issued token before export. Actual preserves the manual issuer's 12 required and 7 forbidden probes. Failed, indeterminate and contradictory responses stop export and revoke the OpenBao token.

Verification: 86 unit tests and all 16 scaffold cases passed locally. Independently removed the production verify_permissions call, one required probe and one forbidden probe; each mutation failed the focused suite. Restored the exact source and all 9 credential tests passed with a clean checkout. The paired platform changes supply the narrow Forgejo egress and continuing trust/RBAC tests. No remaining blocking code findings.

All 4 exact-head hosted status contexts are successful. Downloaded fresh security decision artifact(s) [177] from web run 138 / API run 332: passed=true, zero blockers and zero scanner errors. Live bootstrap, workload discovery/JWKS access and two fresh authorized deployments remain operational acceptance, not claims established by these synthetic tests. Promotion and prerequisite orchestration remain explicitly deferred. No live credentials were issued, no cluster configuration was applied and no merge/deployment was performed.

Re-reviewed e15ecad82e6d4a285fc8ae8908a9d8cbb3b1e437. Approved; this supersedes my REQUEST_CHANGES review #455. The automatic issuer now loads an independently reviewed app-specific contract from the pinned library, binds its repository/role/SA/namespace/API/context, and performs CA-verified SelfSubjectAccessReviews with the issued token before export. Actual preserves the manual issuer's 12 required and 7 forbidden probes. Failed, indeterminate and contradictory responses stop export and revoke the OpenBao token. Verification: 86 unit tests and all 16 scaffold cases passed locally. Independently removed the production verify_permissions call, one required probe and one forbidden probe; each mutation failed the focused suite. Restored the exact source and all 9 credential tests passed with a clean checkout. The paired platform changes supply the narrow Forgejo egress and continuing trust/RBAC tests. No remaining blocking code findings. All 4 exact-head hosted status contexts are successful. Downloaded fresh security decision artifact(s) [177] from web run 138 / API run 332: passed=true, zero blockers and zero scanner errors. Live bootstrap, workload discovery/JWKS access and two fresh authorized deployments remain operational acceptance, not claims established by these synthetic tests. Promotion and prerequisite orchestration remain explicitly deferred. No live credentials were issued, no cluster configuration was applied and no merge/deployment was performed.
gitchegumi deleted branch kiyi/automatic-deploy-credentials 2026-09-07 21:02:10 -05:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Homelab/workflows!26
No description provided.