Skip to main content

Trust store and certificate management in the Graph Studio Operator

1. What is a trust store?​

A trust store is the pool of Certificate Authority (CA) certificates that a process/JVM uses to decide whether a certificate presented by a peer (e.g. a TLS server it connects to) should be trusted. It is the counterpart of a keystore, which holds a process's own private key and certificate (used to present an identity), whereas the trust store holds other parties' CA certificates (used to verify an identity).

In the Graph Studio Operator, the trust store concept shows up as two related but distinct CR fields on the Anzo resource:

FieldPurpose
spec.tlsCerts / spec.certificateThe server's own TLS identity: private key + certificate (+ optional PKCS12 keystore) presented by the Graph Studio pod.
spec.trustBundleName of a ConfigMap in the CR's namespace containing a pool of CA certificates that Graph Studio/AnzoGraph and its watcher sidecar should trust when acting as a client (e.g. talking to LDAP, Keycloak, other Graph Studio components, or any TLS endpoint signed by a private/internal CA).

2. Why trust store management is used in Graph Studio​

Graph Studio frequently runs in environments where it must both:

  1. Present a certificate to clients connecting to it (browsers, other Graph Studio/AnzoGraph nodes, REST/JDBC clients) — handled via spec.certificate (cert-manager issued) or spec.tlsCerts (a pre-existing secret).
  2. Trust CAs of other services it connects to — internal CAs, Keycloak, LDAP, corporate proxy/MITM CAs, etc. — handled via spec.trustBundle.

3. How to use certificate and trust management in the operator​

3.1 Server certificate (via cert-manager) — spec.certificate​

Set spec.certificate on the Anzo CR using the upstream cert-manager Certificate spec fields (the operator embeds certv1.CertificateSpec directly). The operator:

  • Creates a cert-manager Certificate object named after the Anzo CR (namespace/name are always taken from the owning Anzo, not from spec.certificate.metadata).
  • If spec.certificate.spec.keystores is not set, the operator auto-adds a PKCS12 keystore section and creates a Secret holding the keystore password (CreateKeystorePass), so a JKS/PKCS12 keystore is always available for Anzo's Java runtime.
  • Mounts the resulting TLS secret (spec.certificate.spec.secretName) into the pod once cert-manager reports the certificate as Ready.

3.2 Pre-existing certificate secret — spec.tlsCerts​

If you already manage certificates outside cert-manager, set spec.tlsCerts to the name of an existing Secret (in the CR's namespace) containing the TLS key/cert. This is mutually exclusive in practice with spec.certificate — prefer one or the other. spec.tlsCerts takes precedence when both are set.

3.3 Trust bundle (client-side trust store) — spec.trustBundle​

  1. Create/maintain a ConfigMap in the CR's namespace whose data values are PEM-encoded CA certificates.
  2. Set spec.trustBundle: <configmap-name> on the Anzo CR.
  3. The operator handles mounting, sidecar injection, and live reload on ConfigMap updates — no pod restart required.

4. Prerequisites​

  • cert-manager must be installed in the cluster if you use spec.certificate (the operator does not install cert-manager itself). See cert-manager installation docs.
  • An Issuer or ClusterIssuer must already exist in the cluster/namespace before creating the Anzo CR — the operator does not create issuers, it only references one via spec.certificate.spec.issuerRef.
  • CA bundle ConfigMap must exist before setting spec.trustBundle (create it ahead of, or alongside, the Anzo CR).
  • The Anzo ServiceAccount needs no extra RBAC for these features beyond what the operator's default install grants (it manages Certificate, Secret, and ConfigMap objects it owns).
  • If relying on the auto-created PKCS12 keystore password secret, no extra setup is needed; if you want to control the keystore password secret/key yourself, set spec.certificate.spec.keystores.pkcs12 explicitly (see snippet below).

5. Custom Resource YAML snippet​

5.1 Prerequisite: Issuer (or ClusterIssuer)​

apiVersion: cert-manager.io/v1
kind: Issuer # use ClusterIssuer for a cluster-wide issuer
metadata:
name: my-ca-issuer
namespace: "${NAMESPACE}"
spec:
ca:
secretName: my-ca-key-pair # Secret containing tls.crt/tls.key of your CA, created beforehand

5.2 Prerequisite: trust bundle ConfigMap​

apiVersion: v1
kind: ConfigMap
metadata:
name: bundle
namespace: "${NAMESPACE}"
data:
ca.pem: |
-----BEGIN CERTIFICATE-----
...PEM-encoded CA certificate(s) to trust...
-----END CERTIFICATE-----

5.3 Anzo CR with certificate + trust bundle configured​

apiVersion: anzo.cambridgesemantics.com/v2
kind: Anzo
metadata:
name: anzo
namespace: "${NAMESPACE}"
spec:
nodeConfig:
spec:
replicas: 1
serviceName: anzo
selector:
matchLabels:
app: "anzo"
template:
metadata:
labels:
app: "anzo"
spec:
serviceAccountName: anzo-operator
containers:
- name: anzo
image: artifacts.altair.com/graph-docker/anzo:6.3.1
resources:
requests:
cpu: "1000m"
memory: "4000Mi"
imagePullPolicy: Always
role: AnzoServer
jsonActivation: true
initJSON: |-
{
"sysadminUser": "k8s://anzo-anzo/admin_user",
"password": "k8s://anzo-anzo/admin_password",
"hostname": "anzo",
"serverId": "${SERVER_ID}",
"licenseEncoded": "${CSI_LICENSE}"
}
jvmMemory: 4096m
credentials: mysecret1

# --- Server identity: requested from cert-manager using the Issuer above ---
certificate:
metadata:
name: pkcs12-certs
namespace: "${NAMESPACE}"
spec:
isCA: false
secretName: pkcs12
commonName: what.ever
dnsNames:
- localhost
- anzo-anzo-lb.ns1
- anzo-anzo-lb
issuerRef:
# Issuer/ClusterIssuer must already exist in the cluster (see prerequisites)
name: my-ca-issuer
# kind: ClusterIssuer
group: cert-manager.io
# Optional: control the PKCS12 keystore password secret/key yourself.
# If omitted, the operator auto-creates a keystore and a password secret.
# keystores:
# pkcs12:
# create: true
# passwordSecretRef:
# name: keystorepass
# key: password

# --- Client-side trust store: pool of CA certs Anzo should trust ---
# ConfigMap "bundle" must already exist in the same namespace (see prerequisites)
trustBundle: bundle

# --- Alternative to `certificate`: use a pre-existing TLS secret instead ---
# tlsCerts: pkcs12-secret