A TemporalClusterClient issues mTLS client credentials for a Temporal cluster.
The operator requests a cert-manager Certificate from the cluster’s mTLS CA
issuer and writes the result (tls.crt, tls.key, ca.crt) into a Kubernetes
Secret. Workers and client applications can then mount that Secret to connect to
the cluster’s frontend over mTLS.
Requirement: this CRD only works against an mTLS-enabled
TemporalCluster(mtls.provider: cert-manager). Against a non-mTLSTemporalClusterthe controller reports aClusterMTLSDisabledcondition, and against aTemporalDevServerit reportsDevServerUnsupported— in both cases it issues no certificate.
Prerequisites: cert-manager must be installed in the cluster.
Files #
| File | Description |
|---|---|
issuer.yaml | Self-signed root Issuer, CA Certificate, and temporal-ca-issuer CA Issuer. Apply first. |
temporalcluster.yaml | mTLS-enabled TemporalCluster (temporal-mtls) that references temporal-ca-issuer. |
clusterclient.yaml | TemporalClusterClient that issues credentials from the cluster above. |
Apply #
# 1. Bootstrap the cert-manager CA issuer
kubectl apply -f issuer.yaml
# 2. Create the mTLS-enabled cluster (adjust persistence config for your env)
kubectl apply -f temporalcluster.yaml
# 3. Issue client credentials
kubectl apply -f clusterclient.yaml
Wait for the cluster to become ready, then check the client:
kubectl get temporalclusterclients # short name: tcc
kubectl describe tcc temporal-mtls-client
The READY column becomes True once cert-manager has issued the certificate
(CertificateReady condition). Inspect the generated Secret:
kubectl get secret temporal-mtls-client -o yaml
# Data keys: tls.crt, tls.key, ca.crt
Using the credentials #
Mount the Secret in a worker or client deployment to connect over mTLS:
volumes:
- name: temporal-client-tls
secret:
secretName: temporal-mtls-client
containers:
- name: worker
volumeMounts:
- name: temporal-client-tls
mountPath: /etc/temporal/tls
readOnly: true
Pass the mounted paths to your Temporal SDK’s TLS configuration
(ClientCertPath, ClientKeyPath, CACertPath) when dialing the cluster’s
frontend (<cluster-name>-frontend.<namespace>:7233).
Caveats #
- The cluster referenced by
clusterRef.namemust exist in the same namespace as theTemporalClusterClient. - If the cluster has no mTLS configured, the controller sets a
ClusterMTLSDisabledcondition and does not issue a certificate. secretNamedefaults to theTemporalClusterClientresource name when omitted.
Manifests #
clusterclient.yaml #
apiVersion: temporal.bmor10.com/v1alpha1
kind: TemporalClusterClient
metadata:
name: temporal-mtls-client
spec:
# Must reference an mTLS-enabled TemporalCluster in the same namespace.
clusterRef:
name: temporal-mtls
# Name of the Secret the operator writes the generated client credentials into.
secretName: temporal-mtls-client
issuer.yaml #
# A self-signed root issuer and CA, then a CA issuer that the operator uses to
# mint internode and frontend certificates. Requires cert-manager installed.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: temporal-selfsigned
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: temporal-ca
spec:
isCA: true
commonName: temporal-ca
secretName: temporal-ca
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: temporal-selfsigned
kind: Issuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: temporal-ca-issuer
spec:
ca:
secretName: temporal-ca
temporalcluster.yaml #
# An mTLS-enabled TemporalCluster backed by the cert-manager CA issuer above.
# TemporalClusterClient requires an mTLS-enabled cluster — the controller reads
# mtls.issuerRef to issue client certificates.
apiVersion: temporal.bmor10.com/v1alpha1
kind: TemporalCluster
metadata:
name: temporal-mtls
spec:
version: "1.31.1"
numHistoryShards: 512
mtls:
provider: cert-manager
issuerRef:
name: temporal-ca-issuer
kind: Issuer
persistence:
defaultStore:
sql:
pluginName: postgres12
host: temporal-pg-rw
port: 5432
database: temporal
user: temporal
passwordSecretRef:
name: temporal-pg-app
key: password
visibilityStore:
sql:
pluginName: postgres12
host: temporal-pg-rw
port: 5432
database: temporal_visibility
user: temporal
passwordSecretRef:
name: temporal-pg-app
key: password