Commit graph

5 commits

Author SHA256 Message Date
CTO (Paperclip)
20ba29d3ac approval-service: K8s deployment manifests + Pocket-ID OIDC client (DEV-614)
All checks were successful
build-images / signing-service image (push) Successful in 26s
build-images / verification-service image (push) Successful in 27s
build-images / approval-service image (push) Successful in 31s
build-images / dummy-sink image (push) Successful in 29s
validate / JSON Schema (ajv) (push) Successful in 23s
validate / Rego (opa fmt + opa test) (push) Successful in 16s
phase1-smoke / Phase 1 end-to-end smoke (push) Successful in 1m0s
validate / DB (migrate up/down dry-run) (push) Successful in 26s
validate / Go (vet + test) (push) Successful in 1m20s
Phase-1 Subtask 8/10 (parent DEV-606):
- deploy/approval-service/: SA (no auto-mount), Deployment (replicas=2,
  distroless-nonroot, read-only rootfs), ClusterIP :8080, NetworkPolicy
  (ingress from pangolin namespace only; egress to signing-service,
  transparency-log, trust-pg in agent-trust + pocket-id + DNS), README.
- 10-secret-dev.example.yaml template + the real 10-secret-dev.sealed.yaml
  carrying the Pocket-ID client id/secret, WebAuthn RP config, and the
  dev signing-service bearer; unsealed in-cluster to Secret
  approval-service-dev.
- services/approval-service/Dockerfile: BuildKit multi-stage, context-at-
  repo-root, matches the signing/verification/dummy-sink pattern.
- .forgejo/workflows/build-images.yml: new approval-service job pushing
  harbor.basicstack.de/basicstack/approval-service:{sha,main} on main.
- Pocket-ID: created proofedmesh-admin group + OIDC client
  "ProofedMesh Approval" with PKCE enforced, callback
  https://approval.proofedmesh.basicstack.de/oidc/callback, group
  restriction to proofedmesh-admin. Client secret stored as Paperclip
  secret proposal and in the SealedSecret above — never pasted inline.

Deployment applied cluster-side pending the first CI image build:
`kubectl apply -f deploy/approval-service/` is green; pods ErrImagePull
until the Forgejo workflow completes and pushes the :main tag.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 21:12:01 +00:00
CTO
5d2bf73d84 deploy: verification-service + dummy-sink Phase-1 manifests (DEV-615)
Some checks failed
build-images / signing-service image (push) Successful in 23s
build-images / verification-service image (push) Successful in 48s
build-images / dummy-sink image (push) Successful in 49s
validate / JSON Schema (ajv) (push) Successful in 23s
validate / Rego (opa fmt + opa test) (push) Successful in 15s
phase1-smoke / Phase 1 end-to-end smoke (push) Successful in 1m0s
validate / DB (migrate up/down dry-run) (push) Successful in 24s
validate / Go (vet + test) (push) Has been cancelled
ServiceAccount, Deployment, Service, and NetworkPolicy per
sub-directory, matching the signing-service template (non-root,
read-only rootfs, distroless, agent-trust namespace).

verification-service — NetworkPolicy allows ingress only from
approval-service, testagent-transform, and dummy-sink, and egress
only to transparency-log, trust-pg, Pocket-ID JWKS (HTTPS/443),
and kube-dns.

dummy-sink — adds a 1Gi longhorn PVC `dummy-sink-data` mounted at
/data/dummy-sink, projected trust-api SA token at
/var/run/secrets/tokens/trust-api, Pocket-ID client creds from a
dev Secret, strategy Recreate (RWO PVC). NetworkPolicy allows
ingress from testagent-transform and egress to verification-service,
signing-service, transparency-log, HTTPS/443 (Pocket-ID OIDC), and
kube-dns.

build-images workflow — adds verification-service and dummy-sink
jobs mirroring signing-service's BuildKit + Harbor pipeline.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 21:09:14 +00:00
CTO (Paperclip)
30dd2f8b65 signing-service: Pocket-ID JWKS + K8s TokenReview + OPA (DEV-609)
Wires the signing-service's production path for ProofedMesh Phase 1:
the service now performs a double identity check (Pocket-ID OIDC JWT
+ K8s ServiceAccount TokenReview), reconciles both against the
trust-api `agents` registry, and asks an OPA/Rego policy whether the
caller may sign with the requested key_ref.

Code
- internal/token/pocket_id.go: OIDC-Discovery-backed JWKS validator
  with automatic kid rotation (coreos/go-oidc).
- internal/token/k8s_tokenreview.go: hand-rolled TokenReview client;
  reads X-Workload-Token, posts to authentication.k8s.io/v1 via the
  pod's in-cluster SA token + CA.
- internal/registry: Postgres resolver for the agents table +
  in-memory Static resolver for tests.
- internal/policy/opa.go: OPA/rego StructuredDecider; input carries
  both lookups so the policy can enforce identity consistency AND
  the key_ref ↔ role mapping.
- internal/httpapi/sign.go: new structured flow when
  Validator+TokenReviewer+Registry+StructuredPolicy are all wired;
  dev path (static bearers + AllowAll) remains intact.
- cmd/signing-service/main.go: -pocket-id-issuer,
  -pocket-id-audience, -k8s-tokenreview, -registry-dsn,
  -policy-bundle flags.

Policy
- policies/sinks/signing_service.rego: identities_agree +
  key_ref_matches_role rules; agent → key_ref prefix map covers
  approval-service, testagent-transform, dummy-sink.

Deploy
- deploy/signing-service/01-rbac.yaml: ClusterRole with
  tokenreviews.create + binding to the signing-service SA.
- deploy/signing-service/20-deployment.yaml: adds POCKET_ID_ISSUER,
  POCKET_ID_AUDIENCE, TRUST_PG_DSN env, projected SA token volume,
  OPA policy ConfigMap mount, structured flags.
- deploy/signing-service/00-serviceaccount.yaml: disables default
  auto-mount; a projected volume is used.
- deploy/signing-service/README.md: documents prod flags +
  ConfigMap generation.

Tests
- httptest-mock Pocket-ID (OIDC discovery + JWKS, kid rotation),
  StaticTokenReviewer fake, Static registry, real Rego policy.
- Happy paths: Approval-Service → trust-api/approval-signer-2026-q4;
  testagent-transform → trust-api/agent-testagent-transform-2026-q4.
- Denies: registry mismatch, wrong key_ref for role, missing /
  bad workload token, bad Pocket-ID token, kid rotation.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 19:42:40 +00:00
CTO
951f22f80e transparency-log: real Trillian backend wiring + agent-trust deploy (DEV-604)
Some checks failed
build-images / signing-service image (push) Failing after 14s
validate / JSON Schema (ajv) (push) Successful in 21s
validate / Rego (opa fmt + opa test) (push) Successful in 14s
validate / Go (vet + test) (push) Successful in 30s
- services/transparency-log/pkg/backend/trillian.go: real gRPC client
  on github.com/google/trillian v1.6.1. Submit() does QueueLeaf with the
  canonical DSSE envelope as LeafValue and the raw content_hash bytes as
  LeafIdentityHash, then polls GetLatestSignedLogRoot +
  GetInclusionProofByHash until the leaf is sequenced. Idempotency uses
  Trillian's ALREADY_EXISTS signal on the inner QueuedLogLeaf.Status, so
  a repeated submit still returns 200 OK with the originally-assigned
  log_index + a valid proof against the current STH.
- Unconfigured backend (missing endpoint or LogID) returns the historical
  ErrTrillianUnavailable so the httpapi layer keeps mapping it to 503
  instead of silently 500. Existing stub-returns-503 test updated.
- cmd/transparency-log: pointer-receiver Trillian wiring; flag docs
  mention the production SRV name.
- services/transparency-log/Dockerfile: distroless multi-stage build
  used by deploy/trillian/40-transparency-log.yaml.

- deploy/trillian/: full K8s stack for the agent-trust namespace —
  MySQL 8.4 StatefulSet (schema init ConfigMap vendored from upstream
  storage.sql v1.6.1), Trillian LogServer + LogSigner Deployments on
  gcr.io/trillian-opensource-ci:v1.6.1, createtree Job that writes
  the TreeID to a ConfigMap (re-apply safe), transparency-log
  Deployment with --backend=trillian pulling TRILLIAN_LOG_ID from
  the ConfigMap.
- deploy/trillian/README.md: first-time apply + smoke-test + secret
  rotation + signer-key clarification (STH key is Trillian-internal;
  DSSE envelope signing stays with signing-service / OpenBao).

- services/admin-api: go.mod / go.sum pick up the new transitive deps
  (trillian + grpc) via the local replace on transparency-log.
- services/transparency-log/README.md: Backends table updated; next-
  steps list no longer carries Trillian-deployment as a follow-up.

Deployed to the live cluster from this heartbeat: MySQL + LogServer +
LogSigner running in agent-trust, tree id 8482455225499059043, service
smoke-tested end-to-end (201 on first POST, 200 on idempotent repeat,
409 on content_hash mismatch, tree_size=2 with correct audit path).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 18:39:44 +00:00
CTO
b52936ce9d signing-service: Dockerfile, K8s manifests (agent-trust), image CI, secret convention
Some checks failed
validate / JSON Schema (ajv) (push) Successful in 20s
validate / Rego (opa fmt + opa test) (push) Successful in 14s
validate / Go (vet + test) (push) Successful in 21s
build-images / signing-service image (push) Failing after 13s
- Dockerfile: multi-stage (golang:1.23-alpine3.21 → distroless/static:nonroot),
  CGO off, trimpath, stripped, UID/GID 65532, read-only rootfs friendly.
- deploy/signing-service/: ServiceAccount, Deployment (2 replicas, probes,
  tight SecurityContext), ClusterIP Service on :8081, NetworkPolicy
  (ingress from agent-trust, DNS egress), example Secret, and README with
  the full dev + prod secret convention.
- .forgejo/workflows/build-images.yml: builds image on push + PR,
  pushes :<git-sha> + :main to harbor.basicstack.de on main pushes only.
  Clone pattern matches validate.yml (sha256 repo, manual git clone).
- README updates: service README gains Deployment section; repo README
  layout now mentions services/signing-service, services/transparency-log,
  deploy/, and the new workflow.

Scope matches DEV-605. OpenBao, OPA and Pocket-ID JWKS stay stubs and move
in their own follow-up subtasks; the prod secret shape is documented so
those subtasks can plug in without reshaping the Deployment.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 18:19:51 +00:00