Skip to content

TLS and custom CAs

Use TLS for public HTTP and gRPC endpoints and for connections to external dependencies. Certificates must be valid for the DNS names actually used by clients and Koldan pods.

Prerequisites

Prepare the public endpoint names, certificate chain, unencrypted PEM private key where the chart must terminate TLS, issuing CA bundle, renewal owner, and an overlap plan for CA rotation. Confirm whether TLS terminates at an Ingress controller, an OpenShift Route, or the Koldan gRPC service before changing values.

Public HTTP TLS

For Kubernetes Ingress, create a TLS Secret through the cluster's certificate controller or your approved secret process, then reference it from web.ingress.tls:

web:
  ingress:
    enabled: true
    hosts:
      - host: api.example.net
        paths:
          - path: /
            pathType: Prefix
    tls:
      - secretName: koldan-web-tls
        hosts:
          - api.example.net

The referenced Secret must be in the Koldan namespace. Renewing that Secret is normally the responsibility of the certificate controller or operator that owns it.

For OpenShift, configure web.route.tls. Route TLS fields can contain certificate material directly and therefore become part of Helm release data. Prefer a platform-managed certificate when your Route configuration and organizational controls allow it.

Public gRPC TLS

When Koldan terminates gRPC TLS, enable the chart-managed certificate:

grpc:
  certificate:
    enabled: true
    cert: |
      <PEM certificate chain>
    key: |
      <PEM private key>

The chart creates a Kubernetes Secret and configures the gRPC service to use the PEM files. Both populated values also remain in Helm release data. Protect the source values and release objects as secrets. When an OpenShift Route terminates gRPC TLS instead, configure grpc.route.tls consistently with the selected edge, re-encrypt, or passthrough mode.

The application-property reference lists the supported koldan.api-grpc.ssl.* PEM and PKCS12 settings for deployments that provide their own mounted certificate files. Do not set both chart-managed PEM values and a separate application TLS configuration unless the resulting file paths and termination model have been deliberately reconciled.

Trust a private CA

Add PEM-encoded issuing certificates under customCA.data when PostgreSQL, Temporal, S3, OIDC, an LLM provider, or another required service uses a private CA:

customCA:
  enabled: true
  data:
    organization-root.pem: |
      <PEM CA certificate>
    organization-intermediate.pem: |
      <PEM intermediate CA certificate>

The chart stores these files in a Kubernetes Secret and mounts them at /mnt/trust-certs in supported Koldan workloads. Include only CA certificates needed to build the serving chain. Never place a private key in customCA.data.

customCA supplies outbound trust; it does not configure an Ingress, Route, or gRPC serving certificate. It also does not alter third-party dependency pods installed by their own subcharts. Configure trust for those dependencies through their supported interfaces.

Trust a private PostgreSQL CA from Temporal

When using self-managed Temporal from Koldan helm chart, it does not use Koldan's CA truststore. When the bundled Temporal deployment connects to PostgreSQL through TLS, mount the chart-managed custom-CA Secret into both the Temporal server and admin-tools workloads, then reference the mounted CA explicitly from every SQL datastore.

customCA:
  enabled: true
  data:
    postgresql-ca.pem: |
      <PEM PostgreSQL issuing CA chain>

temporal:
  install: true

  server:
    additionalVolumes:
      - name: koldan-custom-ca
        secret:
          # For a release named "koldan". Use the rendered
          # <Koldan fullname>-custom-ca-certs name for another release.
          secretName: koldan-custom-ca-certs
    additionalVolumeMounts:
      - name: koldan-custom-ca
        mountPath: /mnt/trust-certs
        readOnly: true

    config:
      persistence:
        datastores:
          default:
            sql:
              tls:
                enabled: true
                caFile: /mnt/trust-certs/postgresql-ca.pem
                serverName: postgresql.example.internal
                enableHostVerification: true
          visibility:
            sql:
              tls:
                enabled: true
                caFile: /mnt/trust-certs/postgresql-ca.pem
                serverName: postgresql.example.internal
                enableHostVerification: true

  admintools:
    additionalVolumes:
      - name: koldan-custom-ca
        secret:
          secretName: koldan-custom-ca-certs
    additionalVolumeMounts:
      - name: koldan-custom-ca
        mountPath: /mnt/trust-certs
        readOnly: true

Set serverName to a DNS SAN in the PostgreSQL serving certificate and keep enableHostVerification: true.

Verify

Before rollout, verify that the certificate matches its key and includes every required SAN. From a network location equivalent to the relevant client or pod, inspect each endpoint without printing private material:

openssl s_client -connect api.example.net:443 -servername api.example.net -verify_return_error </dev/null
openssl s_client -connect grpc.example.net:443 -servername grpc.example.net -alpn h2 -verify_return_error </dev/null

After the Helm upgrade:

  • Confirm the public HTTP certificate, chain, hostname, and expiry.
  • Confirm the gRPC path negotiates HTTP/2 and presents the intended certificate.
  • Test OIDC discovery and login, PostgreSQL, Temporal, S3, and enabled provider connections from the Koldan namespace.
  • Confirm affected pods restarted and became Ready. Updating a mounted Secret alone does not guarantee that an application has reloaded trust material.

Rotate certificates and CAs

  1. Add the new CA certificate while retaining the old CA.
  2. Apply the values and restart every workload that makes connections through that trust path.
  3. Verify that both old and new serving chains are accepted.
  4. Rotate serving certificates and confirm HTTP, gRPC, OIDC, PostgreSQL, Temporal, S3, and provider operations.
  5. Remove the old CA only after every server and client has moved, then restart and verify again.

For an emergency rollback, restore the prior serving certificate and key as a matched pair and retain both trust anchors until connectivity is stable.

Symptom Likely cause and recovery
Hostname verification fails The connected DNS name is absent from the SAN; issue a corrected certificate rather than disabling verification
Unknown issuer or path-building error Missing root/intermediate certificate, wrong CA bundle, or workload not restarted after the bundle changed
Private key does not match certificate Restore the matched pair and repeat the rotation
Browser works but gRPC fails gRPC endpoint, HTTP/2/ALPN, Route termination mode, or gRPC certificate is configured differently from HTTP
Only a bundled dependency fails That subchart does not consume Koldan's customCA; configure its trust separately