116 lines
5.3 KiB
Markdown
116 lines
5.3 KiB
Markdown
|
|
# Core Hub Forgejo source-read lane (CCR-2026-0031)
|
||
|
|
|
||
|
|
Status: **proposed**, drafted 2026-10-03 under CUST-WP-0075 for
|
||
|
|
`RAPPCOREHUB-WP-0003-T04`. Nothing here is approved, applied or provisioned.
|
||
|
|
No Forgejo, OpenBao or cluster object was created and no owner message other
|
||
|
|
than the CUST-WP-0075 reply was sent.
|
||
|
|
|
||
|
|
## Why
|
||
|
|
|
||
|
|
The repo-manager publisher in namespace `core-hub` reads the 123-entry
|
||
|
|
repository registry (all `coulomb/*`) anonymously. Nine private sources return
|
||
|
|
HTTP 404. T04 forbids the Forgejo admin PAT, personal keys or PATs, and the
|
||
|
|
`policy-nexus-source` token from CCR-2026-0014. This lane gives the publisher
|
||
|
|
its own read-only identity.
|
||
|
|
|
||
|
|
## Shape
|
||
|
|
|
||
|
|
| Item | Value |
|
||
|
|
| --- | --- |
|
||
|
|
| Forgejo user | `core-hub-source` (restricted, non-admin, private; random unrecorded password) |
|
||
|
|
| Forgejo team | `coulomb/core-hub-source-readers`: permission read, all repositories, `repo.code` read, every other unit none, cannot create repos |
|
||
|
|
| PAT | `core-hub-source-read-<UTC timestamp>`, scope exactly `read:repository` |
|
||
|
|
| OpenBao | `platform/workloads/core-hub/forgejo-source-read` fields `FORGEJO_SOURCE_TOKEN`, `API_USER`, `API_BASE_URL`, `TOKEN_SCOPES`, `GENERATED_AT` |
|
||
|
|
| Policy | `workload-kv-read-core-hub-forgejo-source` (`openbao/policies/…hcl`, read on data + metadata of that one path) |
|
||
|
|
| Auth | Kubernetes role `external-secrets-core-hub-forgejo-source`, bound to SA `external-secrets/external-secrets`, TTL 15m |
|
||
|
|
| Delivery | ESO store + ExternalSecret below → Secret `core-hub/repo-manager-forgejo-source` key `token` |
|
||
|
|
| Consumer | rapp-core-hub `publisher.existingSecret: repo-manager-forgejo-source` (already supported by the chart; mounts read-only at `/var/run/secrets/repo-manager/forgejo/token`) |
|
||
|
|
| Rotation | every 180 days or owner change; Forgejo PATs have no server-side expiry |
|
||
|
|
| Front door | ops-warden `core-hub-forgejo-source-read`, follow-up after approval (see below) |
|
||
|
|
|
||
|
|
Naming follows the CCR-2026-0014 precedent (`<workload>-source`,
|
||
|
|
`<workload>-source-readers`). repo-manager has no service-user naming canon.
|
||
|
|
Its outstanding `identity-canon` correction is a registry/Forgejo identity
|
||
|
|
mismatch for one repository. It blocks the 123/0 acceptance, not this
|
||
|
|
credential or its name.
|
||
|
|
|
||
|
|
## Draft manifests (land in `argocd/platform-addons/openbao-secretstore/` only after metadata apply)
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# CCR-2026-0031. Do not apply until approval and confirm-binding.
|
||
|
|
apiVersion: external-secrets.io/v1
|
||
|
|
kind: ClusterSecretStore
|
||
|
|
metadata:
|
||
|
|
name: openbao-core-hub-forgejo-source
|
||
|
|
labels:
|
||
|
|
app.kubernetes.io/part-of: railiance-gitops
|
||
|
|
railiance-platform/component: external-secrets
|
||
|
|
app.kubernetes.io/name: core-hub
|
||
|
|
spec:
|
||
|
|
provider:
|
||
|
|
vault:
|
||
|
|
server: http://openbao.openbao.svc:8200
|
||
|
|
path: platform
|
||
|
|
version: v2
|
||
|
|
auth:
|
||
|
|
kubernetes:
|
||
|
|
mountPath: kubernetes
|
||
|
|
role: external-secrets-core-hub-forgejo-source
|
||
|
|
serviceAccountRef:
|
||
|
|
name: external-secrets
|
||
|
|
namespace: external-secrets
|
||
|
|
conditions:
|
||
|
|
- namespaces:
|
||
|
|
- core-hub
|
||
|
|
---
|
||
|
|
apiVersion: external-secrets.io/v1
|
||
|
|
kind: ExternalSecret
|
||
|
|
metadata:
|
||
|
|
name: repo-manager-forgejo-source
|
||
|
|
namespace: core-hub
|
||
|
|
spec:
|
||
|
|
refreshInterval: 5m
|
||
|
|
secretStoreRef:
|
||
|
|
kind: ClusterSecretStore
|
||
|
|
name: openbao-core-hub-forgejo-source
|
||
|
|
target:
|
||
|
|
# Explicit target metadata prevents ESO copying source last-applied annotations.
|
||
|
|
template:
|
||
|
|
metadata: {}
|
||
|
|
name: repo-manager-forgejo-source
|
||
|
|
creationPolicy: Owner
|
||
|
|
deletionPolicy: Retain
|
||
|
|
data:
|
||
|
|
- secretKey: token
|
||
|
|
remoteRef:
|
||
|
|
key: workloads/core-hub/forgejo-source-read
|
||
|
|
property: FORGEJO_SOURCE_TOKEN
|
||
|
|
```
|
||
|
|
|
||
|
|
## Attended sequence (after approval)
|
||
|
|
|
||
|
|
1. Reviewers approve and confirm the binding (human acts, recorded by the
|
||
|
|
CCR tooling): `credential-change.py approve CCR-2026-0031 …` and
|
||
|
|
`credential-change.py confirm-binding CCR-2026-0031 …`.
|
||
|
|
2. Founder, in their own terminal (child is silent; read the diagnostic file
|
||
|
|
on failure, never the output):
|
||
|
|
`warden access openbao-platform-admin-login --exec -- scripts/openbao-bootstrap-core-hub-source.sh`.
|
||
|
|
This runs the delegated metadata apply (policy + auth role), then
|
||
|
|
`scripts/provision-core-hub-forgejo-source.py`, which gets the Forgejo admin
|
||
|
|
token only through `warden access forgejo-admin-api-token --exec`, mints the
|
||
|
|
PAT, verifies scope, private-repo read and denials, writes the value to
|
||
|
|
OpenBao from stdin, reads it back for equality, and records non-secret
|
||
|
|
evidence. Re-running when the PAT and the OpenBao value both exist is a no-op;
|
||
|
|
a half state fails closed and points to rotation. Failure diagnostics:
|
||
|
|
`/tmp/core-hub-source-bootstrap-diagnostic.json` (stage + bounded reason only).
|
||
|
|
3. Commit the two manifests above and let Argo sync; check presence only with
|
||
|
|
`scripts/secret_annotation_maintenance.py` through the authorized admin path.
|
||
|
|
4. rapp-core-hub sets `publisher.existingSecret`, deploys, runs
|
||
|
|
`make verify-publisher` (expects 123/0 once repo-manager ships the
|
||
|
|
identity-canon correction), then enables `connectCandidate`.
|
||
|
|
5. Add the ops-warden catalog entry `core-hub-forgejo-source-read`
|
||
|
|
(risk high, owner railiance-platform, path above, rotation steps from the
|
||
|
|
CCR) and move the CCR to `verified`/`active` with evidence.
|
||
|
|
|
||
|
|
Offline tests: `python3 -m unittest tests/test_core_hub_forgejo_source_provision.py`.
|