--- # 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"