# deploy/trillian — Trillian + transparency-log on Kubernetes Deploys the production backend for ADR-0005 `POST /api/v1/log/entries` into the `agent-trust` namespace of the BasicStack cluster. ## Component overview | Manifest | What it brings up | | ----------------------------- | ----------------------------------------------------- | | `00-namespace.yaml` | `agent-trust` namespace. | | `10-mysql.yaml` | MySQL 8.4 StatefulSet + schema init ConfigMap + secret. | | `20-logserver.yaml` | Trillian LogServer Deployment + Service (8090 gRPC). | | `21-logsigner.yaml` | Trillian LogSigner Deployment (`--force_master=true`). | | `30-createtree-job.yaml` | One-shot Job that creates the LOG tree and writes the TreeID into a ConfigMap. Safe to re-apply. | | `40-transparency-log.yaml` | `transparency-log` Deployment (ADR-0005 HTTP server) with `--backend=trillian`. | `storage.sql` is the upstream Trillian MySQL schema (v1.6.1) vendored for reference. The applied form lives inline inside the `trillian-mysql-init` ConfigMap in `10-mysql.yaml`. ## First-time deploy ```bash # From a node with cluster access (e.g. k3s-cp-1). kubectl apply -f deploy/trillian/00-namespace.yaml kubectl apply -f deploy/trillian/10-mysql.yaml kubectl -n agent-trust rollout status statefulset/trillian-mysql --timeout=5m kubectl apply -f deploy/trillian/20-logserver.yaml kubectl apply -f deploy/trillian/21-logsigner.yaml kubectl -n agent-trust rollout status deployment/trillian-log-server --timeout=5m kubectl -n agent-trust rollout status deployment/trillian-log-signer --timeout=5m # Creates the tree and populates the trillian-log-id ConfigMap. kubectl apply -f deploy/trillian/30-createtree-job.yaml kubectl -n agent-trust wait --for=condition=complete job/trillian-createtree --timeout=5m kubectl -n agent-trust get configmap trillian-log-id -o jsonpath='{.data.TRILLIAN_LOG_ID}{"\n"}' # Build and push the transparency-log image to the in-cluster registry. # See services/transparency-log/Dockerfile. docker build -t harbor.basicstack.de/proofedmesh/transparency-log:v0.1.0 \ -f services/transparency-log/Dockerfile services/transparency-log docker push harbor.basicstack.de/proofedmesh/transparency-log:v0.1.0 kubectl apply -f deploy/trillian/40-transparency-log.yaml kubectl -n agent-trust rollout status deployment/transparency-log --timeout=5m ``` ## Smoke test Exercise the deployed service end-to-end against the real Trillian backend. ```bash # From inside the cluster: kubectl -n agent-trust run smoke --rm -it --restart=Never --image=curlimages/curl -- \ sh -euxc ' ENV=$(printf "%s" "{\"payloadType\":\"application/vnd.in-toto+json\",\"payload\":\"aGVsbG8\",\"signatures\":[{\"keyid\":\"k\",\"sig\":\"c2ln\"}]}") # content_hash comes from the admin-api attest.EnvelopeContentHash (or the # transparency-log backend.EnvelopeContentHash helper). The two produce # byte-identical SHA-256(canonical envelope). curl -sS -X POST http://transparency-log.agent-trust.svc.cluster.local/api/v1/log/entries \ -H "Content-Type: application/json" \ -d "{\"envelope\":$ENV,\"content_hash\":\"\"}" ' ``` A successful first submit returns `201 Created` with an inclusion proof against a tree size >= 1. Repeating the same submit returns `200 OK` with the same `log_index` (idempotency). ## Secret rotation `trillian-mysql` currently ships with hard-coded credentials for the first deploy. Rotate them to a Sealed Secret before any real attestations land: ```bash # Example — generate new creds, seal them, and replace 10-mysql.yaml's Secret. NEW_PW=$(openssl rand -hex 24) kubectl create secret generic trillian-mysql \ --namespace agent-trust \ --from-literal=MYSQL_ROOT_PASSWORD="$(openssl rand -hex 24)" \ --from-literal=MYSQL_USER=trillian \ --from-literal=MYSQL_PASSWORD="$NEW_PW" \ --from-literal=MYSQL_DATABASE=trillian \ --from-literal=MYSQL_URI="trillian:$NEW_PW@tcp(trillian-mysql.agent-trust.svc.cluster.local:3306)/trillian?parseTime=true" \ --dry-run=client -o yaml \ | kubeseal -o yaml > deploy/trillian/sealed-mysql-secret.yaml ``` Replace the plain Secret block in `10-mysql.yaml` with that sealed form and re-apply. ## Signer key (future work) Trillian stores its own tree-head signing key inside the `Trees` MySQL row. That key is created and sealed by the createtree Job (`--signature_algorithm=ED25519`), and the LogSigner uses it to sign STHs internally. **Our** transparency-log service does not touch that key. Services like admin-api sign DSSE envelopes via the separate `signing-service` (DEV-599, already shipped). That service uses OpenBao Transit (future) or an in-process keyring (current). It is unrelated to the Trillian tree key.