--- # mTLS for buildkitd, issued by cert-manager from a CA that exists ONLY for this purpose. # # buildkit-selfsigned (Issuer) --signs--> buildkit-ca (CA Certificate, 10y) # buildkit-ca (Issuer) --signs--> buildkitd-tls (server, the daemon presents it) # --signs--> buildkit-client-ci (client, CI presents it) # # buildkitd verifies EVERY client certificate against this CA (--tlscacert), so holding a client # certificate signed by it is what "may build" means. Nothing else in the cluster trusts this CA, # and it trusts nothing else. # # THE CLIENT CERTIFICATE REACHES CI AS ACTIONS SECRETS, not through the cluster: CI jobs hold no # cluster credential (R-SEC-02). infra/gitea/buildkit-client-secret.sh copies ca.crt/tls.crt/ # tls.key from the Secret below into the repository secrets BUILDKIT_CA, BUILDKIT_CLIENT_CERT and # BUILDKIT_CLIENT_KEY without printing them. Re-run it after every renewal (see renewBefore). # # WHY A PRIVATE CA AND NOT LET'S ENCRYPT. The platform's TLS rule (R-TLS-01/02, docs/08, # ADR-0006: ACME DNS-01) is about EXTERNALLY REACHABLE services; ADR-0006 itself says "mTLS between # workloads is a separate concern … not covered here", and a public CA cannot issue for a # `*.svc.cluster.local` name or a client-auth certificate anyway. buildkitd is ClusterIP-only. Each # Certificate below is therefore annotated `homelab.keithjackson.dev/tls-scope: workload-mtls`, # which the L0 check tls-lifecycle-automated accepts ONLY if the certificate proves it: no # Gateway serves its Secret, every name is cluster-internal, and the issuer is a namespaced # selfSigned/CA Issuer whose CA is itself issued here. Issuance and renewal stay unattended. # # ROTATION. cert-manager renews both leaves `renewBefore` their expiry and rewrites the Secrets. # * server: buildkitd reads its certificate at START, so the pod must restart inside the 30-day # renewal window (a node reboot by kured, a Deployment rollout, or a manual restart). # * client: the Actions secrets are a COPY; re-run the script. Until then CI fails loudly at # its TLS preflight (.gitea/workflows/scripts/images.sh), never silently. apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: buildkit-selfsigned namespace: buildkit spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: buildkit-ca namespace: buildkit annotations: homelab.keithjackson.dev/tls-scope: workload-mtls # see the header: R-TLS-01 is about external TLS spec: isCA: true commonName: buildkit-ca secretName: buildkit-ca duration: 87600h # 10 years: rotating the CA means re-issuing everything and re-copying privateKey: algorithm: ECDSA size: 256 issuerRef: name: buildkit-selfsigned kind: Issuer --- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: buildkit-ca namespace: buildkit spec: ca: secretName: buildkit-ca --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: buildkitd-tls namespace: buildkit annotations: homelab.keithjackson.dev/tls-scope: workload-mtls spec: secretName: buildkitd-tls commonName: buildkitd.buildkit.svc.cluster.local dnsNames: - buildkitd.buildkit.svc.cluster.local # what CI dials (platform/buildkit/versions.env) - buildkitd.buildkit.svc - buildkitd duration: 8760h renewBefore: 720h usages: - server auth - digital signature privateKey: algorithm: ECDSA size: 256 rotationPolicy: Always issuerRef: name: buildkit-ca kind: Issuer --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: buildkit-client-ci namespace: buildkit annotations: homelab.keithjackson.dev/tls-scope: workload-mtls spec: secretName: buildkit-client-ci commonName: gitea-actions-image-pipeline duration: 8760h renewBefore: 720h usages: - client auth - digital signature privateKey: algorithm: ECDSA size: 256 rotationPolicy: Always issuerRef: name: buildkit-ca kind: Issuer