ProofedMesh/deploy/trillian/30-createtree-job.yaml
CTO 951f22f80e
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
transparency-log: real Trillian backend wiring + agent-trust deploy (DEV-604)
- 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

115 lines
4.4 KiB
YAML

---
# ConfigMap populated by the createtree Job below. The transparency-log
# Deployment reads TRILLIAN_LOG_ID out of this ConfigMap. The Job owns
# writing the value; GitOps owns the structure of this object.
apiVersion: v1
kind: ConfigMap
metadata:
name: trillian-log-id
namespace: agent-trust
data:
TRILLIAN_LOG_ID: ""
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: trillian-createtree
namespace: agent-trust
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: trillian-createtree
namespace: agent-trust
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["trillian-log-id"]
verbs: ["get", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: trillian-createtree
namespace: agent-trust
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: trillian-createtree
subjects:
- kind: ServiceAccount
name: trillian-createtree
namespace: agent-trust
---
# One-shot Job: creates a Trillian LOG tree the first time it runs and
# writes the TreeID into the ConfigMap above. On a re-run the Job detects
# a non-empty ConfigMap value and exits early — so it is safe to re-apply.
apiVersion: batch/v1
kind: Job
metadata:
name: trillian-createtree
namespace: agent-trust
spec:
backoffLimit: 3
template:
spec:
restartPolicy: OnFailure
serviceAccountName: trillian-createtree
containers:
- name: createtree
image: golang:1.23-alpine3.21
env:
- name: TRILLIAN_ADMIN_SERVER
value: trillian-log-server.agent-trust.svc.cluster.local:8090
- name: NAMESPACE
value: agent-trust
- name: CONFIGMAP_NAME
value: trillian-log-id
command:
- /bin/sh
- -c
- |
set -eu
apk add --no-cache git curl ca-certificates jq
# Short-circuit if the ConfigMap already carries a tree id.
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
API="https://kubernetes.default.svc"
EXISTING=$(curl -sS --cacert "$CACERT" -H "Authorization: Bearer $TOKEN" \
"$API/api/v1/namespaces/$NAMESPACE/configmaps/$CONFIGMAP_NAME" \
| jq -r '.data.TRILLIAN_LOG_ID // ""')
if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ] && [ "$EXISTING" != "0" ]; then
echo "trillian-log-id ConfigMap already carries TRILLIAN_LOG_ID=$EXISTING, nothing to do."
exit 0
fi
echo "Building createtree from source (one-shot)..."
GOFLAGS=-mod=mod GOBIN=/usr/local/bin \
go install github.com/google/trillian/cmd/createtree@v1.6.1
echo "Calling admin RPC at $TRILLIAN_ADMIN_SERVER ..."
# Trillian v1.6+ removed per-flag hash/signature algorithm choices
# from createtree. The server always uses SHA256 + RFC6962_SHA256
# for LOG trees; the Trees row's PrivateKey column is unused in
# modern Trillian (STH signatures use the server's own key).
TREE_ID=$(createtree \
--admin_server="$TRILLIAN_ADMIN_SERVER" \
--tree_type=LOG \
--display_name=proofedmesh-transparency-log \
--description="ProofedMesh Transparency Log (ADR-0005)" \
--max_root_duration=0s 2>&1 | tail -n1)
# createtree writes the integer tree id to stdout as the last line.
TREE_ID=$(printf '%s' "$TREE_ID" | tr -d '[:space:]')
if [ -z "$TREE_ID" ] || [ "$TREE_ID" = "0" ] || ! printf '%s' "$TREE_ID" | grep -qE '^[0-9]+$'; then
echo "createtree returned no tree id" >&2
exit 1
fi
echo "Got tree id: $TREE_ID"
# Merge-patch the ConfigMap with the fresh tree id.
PATCH=$(printf '{"data":{"TRILLIAN_LOG_ID":"%s"}}' "$TREE_ID")
curl -sS --cacert "$CACERT" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/merge-patch+json" \
-X PATCH \
-d "$PATCH" \
"$API/api/v1/namespaces/$NAMESPACE/configmaps/$CONFIGMAP_NAME"
echo
echo "Patched ConfigMap trillian-log-id with TRILLIAN_LOG_ID=$TREE_ID"