feat(auth): validate issued credentials without deployment #29

Merged
gitchegumi merged 3 commits from kiyi/validate-issued-credentials into main 2026-09-08 14:11:23 -05:00
Member

Add credential_mode: validate to exercise Forgejo OIDC -> OpenBao -> Kubernetes issuance and the reviewed permission contract without running a deployment command. This allows app onboarding to validate credentials while an existing production application continues running.

Uses the same exchange, identity/lifetime checks, required/forbidden SelfSubjectAccessReviews, masking and session revocation as openbao deployment mode. Validation rejects child commands and reports success only after cleanup succeeds. Logs name each stage and permission-check index plus final elapsed time. Diagnostic modes skip the deployment tool downloads and rescan artifact upload. Existing openbao and kubeconfig deployment paths remain available.

Validation: all 96 tests pass under WSL, including real wrapper control flow with mocked endpoints, all 19 authorization probes, no child execution, cleanup failure, redaction, and workflow routing/owner gate. git diff --check passes. Live issuance remains pending.

The owner has now successfully configured the live OpenBao JWT trust and Kubernetes role after platform#29. After merge and release, adopt validate mode in the existing Actual deploy-bundle.yml caller to preserve its bound workflow identity; run two fresh owner dispatches. This is issuance validation, not proof of two deployments or environment promotion.

Related: Homelab/workflows#19 and Homelab/platform#24.

Add credential_mode: validate to exercise Forgejo OIDC -> OpenBao -> Kubernetes issuance and the reviewed permission contract without running a deployment command. This allows app onboarding to validate credentials while an existing production application continues running. Uses the same exchange, identity/lifetime checks, required/forbidden SelfSubjectAccessReviews, masking and session revocation as openbao deployment mode. Validation rejects child commands and reports success only after cleanup succeeds. Logs name each stage and permission-check index plus final elapsed time. Diagnostic modes skip the deployment tool downloads and rescan artifact upload. Existing openbao and kubeconfig deployment paths remain available. Validation: all 96 tests pass under WSL, including real wrapper control flow with mocked endpoints, all 19 authorization probes, no child execution, cleanup failure, redaction, and workflow routing/owner gate. git diff --check passes. Live issuance remains pending. The owner has now successfully configured the live OpenBao JWT trust and Kubernetes role after platform#29. After merge and release, adopt validate mode in the existing Actual deploy-bundle.yml caller to preserve its bound workflow identity; run two fresh owner dispatches. This is issuance validation, not proof of two deployments or environment promotion. Related: Homelab/workflows#19 and Homelab/platform#24.
feat(auth): validate issued credentials without deployment
All checks were successful
Workflow acceptance / acceptance (pull_request) Successful in 49s
Repository security / security-1 (pull_request) Successful in 1m19s
Repository security / security (pull_request) Successful in 0s
Library checks / tests (pull_request) Successful in 2m1s
5f1f2979ea
portegumi requested changes 2026-09-08 13:50:42 -05:00
Dismissed
portegumi left a comment

Request changes: one startup regression in the diagnostic workflow paths.

[P1] Preserve the owner guard’s Python dependencies when skipping deployment tools — .forgejo/workflows/deploy-bundle.yml:75-77.

Both inspect and validate now skip pipeline/setup.py, but that step also creates the Python environment and installs the hash-locked requirements, not just external deployment/scanning tools. The next mandatory owner-dispatch guard imports delivery.protected; delivery.py:16 imports yaml. PyYAML is not part of the documented runner prerequisites. On a fresh runner with those prerequisites, both diagnostic modes stop with ModuleNotFoundError: No module named 'yaml' before reaching credentials.py. This also regresses the existing inspection path.

Reproduced by creating a fresh python3 -m venv --without-pip, putting its bin directory first in PATH, and executing the exact guard run body from this workflow against the reviewed checkout. Exit 1 at delivery.py:16. The library CI installs the full setup before testing, so its green result does not cover this skipped-setup path.

Keep the lightweight diagnostic path, but either isolate the protected-dispatch guard into a standard-library-only import path, or install its necessary hash-pinned Python runtime dependencies independently of deployment tool downloads. Add a clean-environment workflow-path regression for both inspect and validate that reaches the credential operation with the owner gate still enforced.

Validation: all 96 unit tests pass; scaffold checks pass (YAML/Bash and 16 mocked cases); diff whitespace check passes. Executing the exact validate shell branch with a recording interpreter proved it invokes only credentials.py --validate and propagates failure under the configured Bash error mode. All four exact-head hosted status contexts are green. No real credentials were issued and no deployment was attempted; live issuance remains operational acceptance after the code fix/release/adoption.

Request changes: one startup regression in the diagnostic workflow paths. **[P1] Preserve the owner guard’s Python dependencies when skipping deployment tools** — `.forgejo/workflows/deploy-bundle.yml:75-77`. Both `inspect` and `validate` now skip `pipeline/setup.py`, but that step also creates the Python environment and installs the hash-locked requirements, not just external deployment/scanning tools. The next mandatory owner-dispatch guard imports `delivery.protected`; `delivery.py:16` imports `yaml`. PyYAML is not part of the documented runner prerequisites. On a fresh runner with those prerequisites, both diagnostic modes stop with `ModuleNotFoundError: No module named 'yaml'` before reaching credentials.py. This also regresses the existing inspection path. Reproduced by creating a fresh `python3 -m venv --without-pip`, putting its bin directory first in PATH, and executing the exact guard run body from this workflow against the reviewed checkout. Exit 1 at delivery.py:16. The library CI installs the full setup before testing, so its green result does not cover this skipped-setup path. Keep the lightweight diagnostic path, but either isolate the protected-dispatch guard into a standard-library-only import path, or install its necessary hash-pinned Python runtime dependencies independently of deployment tool downloads. Add a clean-environment workflow-path regression for both inspect and validate that reaches the credential operation with the owner gate still enforced. Validation: all 96 unit tests pass; scaffold checks pass (YAML/Bash and 16 mocked cases); diff whitespace check passes. Executing the exact validate shell branch with a recording interpreter proved it invokes only credentials.py --validate and propagates failure under the configured Bash error mode. All four exact-head hosted status contexts are green. No real credentials were issued and no deployment was attempted; live issuance remains operational acceptance after the code fix/release/adoption.
fix(auth): isolate diagnostic owner guard from deployment dependencies
Some checks failed
Workflow acceptance / acceptance (pull_request) Successful in 58s
Repository security / security-1 (pull_request) Failing after 1m25s
Repository security / security (pull_request) Failing after 0s
Library checks / tests (pull_request) Successful in 1m58s
b206ca013e
Author
Member

Addressed the startup regression. The diagnostic workflow now imports dispatch_guard, which uses only Python standard-library modules. The existing delivery API/guard entrypoints delegate to the same implementation, preserving protected-branch, original owner dispatch and actor enforcement without duplicating authorization logic.

Added a clean-runtime regression using a fresh venv without pip or PyYAML. It executes the exact owner-gate and credential-operation shell bodies for inspect and validate under Bash -e. Authorized mocked Forgejo responses reach the real credential entrypoints and fail at intentionally absent credential configuration; an unprotected branch stops before either operation. No deployment or tool setup is invoked. Existing tests separately exercise all 19 issuance permission probes and cleanup.

All 97 tests pass under WSL; git diff --check passes. Published branch readback matches tested files. Live issuance remains pending after release/adoption.

Addressed the startup regression. The diagnostic workflow now imports dispatch_guard, which uses only Python standard-library modules. The existing delivery API/guard entrypoints delegate to the same implementation, preserving protected-branch, original owner dispatch and actor enforcement without duplicating authorization logic. Added a clean-runtime regression using a fresh venv without pip or PyYAML. It executes the exact owner-gate and credential-operation shell bodies for inspect and validate under Bash -e. Authorized mocked Forgejo responses reach the real credential entrypoints and fail at intentionally absent credential configuration; an unprotected branch stops before either operation. No deployment or tool setup is invoked. Existing tests separately exercise all 19 issuance permission probes and cleanup. All 97 tests pass under WSL; git diff --check passes. Published branch readback matches tested files. Live issuance remains pending after release/adoption.
portegumi requested changes 2026-09-08 14:02:00 -05:00
Dismissed
portegumi left a comment

The original PyYAML startup blocker is resolved. The new dispatch_guard module is standard-library-only, and AST comparison confirms the extracted API and authorization-check bodies preserve the old implementation (apart from the explicit API injection). All 97 unit tests and scaffold checks pass. Reintroducing import yaml makes the clean-runtime regression fail in all four inspect/validate × protected/unprotected cases; restoring the file makes it pass.

Remaining merge blocker: refresh two stale exact security mitigation fingerprints. Exact-head security run 377 (artifact 210) reports passed: false, two blockers and zero scanner errors. Compared with the preceding passing artifact 208, these are the same previously adjudicated operations in pipeline/delivery.py, shifted by extracting the guard. The upload and deploy function ASTs are unchanged; this is fingerprint drift, not evidence of new vulnerabilities.

Update only the corresponding exact mitigations, retaining the reviewed rationale, controls, owner, issue and expiry:

  • HTTPSConnection finding, line 201 -> 169: de0208d1d7ffeaea1dce3aef2c568896d1f97d48894055fa3277ad7ed3ea2e4e -> 4f456ebf10683afb26aba12603a3dbbd134b042691f7f466d24d8eacc28d4681.
  • Health-check urllib finding, line 295 -> 263: a6177ea0d3bab8d5f4ff580a2850e18a7b5ce12f447ae2d4b5152c40b1a18f44 -> 56e16aa7aa353af312d88f53d9852fbd0b37910a1720458328727ea24fbc9a79.

Do not broaden suppressions or refactor the unchanged networking operations. Require a fresh exact-head passing security decision after the mitigation update. No real credential issuance or deployment was performed; live issuance remains separate operational acceptance.

The original PyYAML startup blocker is resolved. The new dispatch_guard module is standard-library-only, and AST comparison confirms the extracted API and authorization-check bodies preserve the old implementation (apart from the explicit API injection). All 97 unit tests and scaffold checks pass. Reintroducing `import yaml` makes the clean-runtime regression fail in all four inspect/validate × protected/unprotected cases; restoring the file makes it pass. **Remaining merge blocker: refresh two stale exact security mitigation fingerprints.** Exact-head security run 377 (artifact 210) reports `passed: false`, two blockers and zero scanner errors. Compared with the preceding passing artifact 208, these are the same previously adjudicated operations in `pipeline/delivery.py`, shifted by extracting the guard. The upload and deploy function ASTs are unchanged; this is fingerprint drift, not evidence of new vulnerabilities. Update only the corresponding exact mitigations, retaining the reviewed rationale, controls, owner, issue and expiry: - HTTPSConnection finding, line 201 -> 169: `de0208d1d7ffeaea1dce3aef2c568896d1f97d48894055fa3277ad7ed3ea2e4e` -> `4f456ebf10683afb26aba12603a3dbbd134b042691f7f466d24d8eacc28d4681`. - Health-check urllib finding, line 295 -> 263: `a6177ea0d3bab8d5f4ff580a2850e18a7b5ce12f447ae2d4b5152c40b1a18f44` -> `56e16aa7aa353af312d88f53d9852fbd0b37910a1720458328727ea24fbc9a79`. Do not broaden suppressions or refactor the unchanged networking operations. Require a fresh exact-head passing security decision after the mitigation update. No real credential issuance or deployment was performed; live issuance remains separate operational acceptance.
fix(scan): refresh mitigation fingerprints after guard extraction
All checks were successful
Workflow acceptance / acceptance (pull_request) Successful in 55s
Repository security / security-1 (pull_request) Successful in 1m27s
Repository security / security (pull_request) Successful in 0s
Library checks / tests (pull_request) Successful in 1m51s
eb6cc85559
Author
Member

Run #159 reported two blocking Semgrep findings and zero scanner errors. Both are existing accepted occurrences in pipeline/delivery.py: the HTTPS release uploader (now line 169) and configured HTTPS health check (now line 263). Extracting the dispatch guard shifted their locations, which changed the location-sensitive fingerprints; the calls and their controls are unchanged.

Commit eb6cc85559 refreshes only those two fingerprints in .pipeline/mitigations.json. Owners, reasons, controls, issue references and the December 1 expiry remain unchanged. Validated that all other mitigation fields and entries are identical, and git diff --check passes. New hosted checks are pending.

Run #159 reported two blocking Semgrep findings and zero scanner errors. Both are existing accepted occurrences in pipeline/delivery.py: the HTTPS release uploader (now line 169) and configured HTTPS health check (now line 263). Extracting the dispatch guard shifted their locations, which changed the location-sensitive fingerprints; the calls and their controls are unchanged. Commit eb6cc85559 refreshes only those two fingerprints in .pipeline/mitigations.json. Owners, reasons, controls, issue references and the December 1 expiry remain unchanged. Validated that all other mitigation fields and entries are identical, and git diff --check passes. New hosted checks are pending.
portegumi approved these changes 2026-09-08 14:11:14 -05:00
portegumi left a comment

Approved at eb6cc85559. This supersedes my earlier REQUEST_CHANGES reviews; both blockers are resolved.

Verified the latest commit changes only the two expected mitigation fingerprints. All other mitigation entries and fields, including owners, reasons, controls, issue references and expiry, are identical. The underlying upload/health-check operations were already verified unchanged during the preceding review.

All 97 local unit tests pass and git diff --check is clean. The standard-library-only owner guard and its mutation-tested clean-runtime inspect/validate regression remain intact. All four exact-head hosted status contexts are now successful.

Independently downloaded the exact-head security artifact 212 from run 380: passed=true, zero blockers, zero scanner errors, five mitigated findings, including both refreshed exact fingerprints.

No remaining code-review blockers. Live issuance still requires the documented fresh owner dispatches after release/adoption; this approval is not evidence of a deployment, promotion or real credential issuance. No deployment or credential issuance was performed during review.

Approved at eb6cc85559a4adc8299b7a16417747b94bfaa8f1. This supersedes my earlier REQUEST_CHANGES reviews; both blockers are resolved. Verified the latest commit changes only the two expected mitigation fingerprints. All other mitigation entries and fields, including owners, reasons, controls, issue references and expiry, are identical. The underlying upload/health-check operations were already verified unchanged during the preceding review. All 97 local unit tests pass and git diff --check is clean. The standard-library-only owner guard and its mutation-tested clean-runtime inspect/validate regression remain intact. All four exact-head hosted status contexts are now successful. Independently downloaded the exact-head security artifact 212 from run 380: passed=true, zero blockers, zero scanner errors, five mitigated findings, including both refreshed exact fingerprints. No remaining code-review blockers. Live issuance still requires the documented fresh owner dispatches after release/adoption; this approval is not evidence of a deployment, promotion or real credential issuance. No deployment or credential issuance was performed during review.
gitchegumi deleted branch kiyi/validate-issued-credentials 2026-09-08 14:11:24 -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!29
No description provided.