OpenZiti Helm Chart - Using Enterprise PKI Instead of Self-Signed CA

As I have understood after reviewing the Helm chart YAML files for ziti-controller, the default CA structure is as follows:

[ROOT CA] release-name-controller-selfsigned-ca-issuer (Self-Signed)
 ├── [ROOT CA] release-name-controller-ctrl-plane-root-issuer
 │    ├── [INTERMEDIATE CA] release-name-controller-ctrl-plane-intermediate-issuer
 │    │    ├── [CERT] release-name-controller-ctrl-plane-identity (Controller)
 │    │    ├── [CERT] release-name-controller-ctrl-plane-client-identity (Client)
 │
 ├── [ROOT CA] release-name-controller-edge-root-issuer
 │    ├── [INTERMEDIATE CA] release-name-controller-edge-signer-issuer
 │         ├── [CERT] release-name-controller-admin-client-cert (Admin)
 │
 ├── [ROOT CA] release-name-controller-web-root-issuer
 │    ├── [INTERMEDIATE CA] release-name-controller-web-intermediate-issuer
 │         ├── [CERT] release-name-controller-web-identity-cert (Web)
 │         ├── [CERT] release-name-controller-web-client-identity (Web Client)

Expected CA Structure with Enterprise PKI

I want to use Enterprise PKI as the root CA instead of the Helm-generated self-signed CA, with the expected structure as follows:

[ROOT CA] Enterprise PKI Root CA  <-- (Managed by Organization's Security Team)
 ├── [INTERMEDIATE CA] Enterprise PKI Intermediate CA  <-- (Issued from Root CA)
 │    ├── [INTERMEDIATE CA] release-name-controller-ctrl-plane-root-issuer
 │    │    ├── [INTERMEDIATE CA] release-name-controller-ctrl-plane-intermediate-issuer
 │    │    │    ├── [CERT] release-name-controller-ctrl-plane-identity (Controller)
 │    │    │    ├── [CERT] release-name-controller-ctrl-plane-client-identity (Client)
 │    │
 │    ├── [INTERMEDIATE CA] release-name-controller-edge-root-issuer
 │    │    ├── [INTERMEDIATE CA] release-name-controller-edge-signer-issuer
 │    │         ├── [CERT] release-name-controller-admin-client-cert (Admin)
 │    │
 │    ├── [INTERMEDIATE CA] release-name-controller-web-root-issuer
 │         ├── [INTERMEDIATE CA] release-name-controller-web-intermediate-issuer
 │         │    ├── [CERT] release-name-controller-web-identity-cert (Web)
 │         │    ├── [CERT] release-name-controller-web-client-identity (Web Client)

What I Tried

After reading the following sources:

I thought that mentioning ctrlPlane.alternativeIssuer.kind & ctrlPlane.alternativeIssuer.name in Helm values would allow Enterprise PKI to be used instead of the self-signed CA.

However, the CA structure generated by Helm still uses self-signed issuers instead of the external PKI.


What I Found

After checking the Helm templates (templates/) directory in:
:link: https://github.com/openziti/helm-charts/tree/main/charts/ziti-controller/templates

I do not see ctrlPlane.alternativeIssuer.kind & ctrlPlane.alternativeIssuer.name being used anywhere in the Helm templates.

This raises the question:

  • Does the Helm chart support using an external CA like Enterprise PKI?
  • If yes, what values should be set in values.yaml?
  • Or do we need to manually create the CA and inject it via Kubernetes Secrets before Helm installation?

values.yaml Used

This is the values.yaml file we used:

clientApi:
  advertisedHost: ziti-controller.example.com
  service:
    enabled: true
    type: ClusterIP

  ingress:
    enabled: true
    ingressClassName: "nginx"
    annotations:
      kubernetes.io/ingress.allow-http: "false"
      nginx.ingress.kubernetes.io/ssl-passthrough: "true"
      external-dns.alpha.kubernetes.io/hostname: "ziti-controller.example.com"
      service.beta.kubernetes.io/aws-load-balancer-internal: "false"  # Ensures the LB is public
      service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
      service.beta.kubernetes.io/aws-load-balancer-security-groups: "sg-0d5ee2792bcbd86a4"
      service.beta.kubernetes.io/aws-load-balancer-manage-backend-security-group-rules: "true"

ctrlPlane:
  containerPort: "{{ .Values.clientApi.containerPort }}"
  advertisedHost: "{{ .Values.clientApi.advertisedHost }}"
  advertisedPort: "{{ .Values.clientApi.advertisedPort }}"
  service:
    enabled: true
    type: ClusterIP
  alternativeIssuer:
    kind: ClusterIssuer
    name: enterprise-pki-cluster-issuer

highAvailability:
  mode: standalone
  replicas: 1

persistence:
  enabled: true
  storageClass: "ebs-sc"
  accessMode: ReadWriteOnce
  size: 3Gi

cert-manager:
  enabled: false # Installed it manually in ziti-controller namespace

trust-manager:
  enabled: false # Installed it manually in ziti-controller namespace

ingress-nginx:
  enabled: true
  controller:
    extraArgs:
      enable-ssl-passthrough: "true"
    service:
      annotations:
        service.beta.kubernetes.io/aws-load-balancer-internal: "false"
        service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
        service.beta.kubernetes.io/aws-load-balancer-security-groups: "sg-0d5ee2792bcbd86a4"
        service.beta.kubernetes.io/aws-load-balancer-manage-backend-security-group-rules: "true"

Despite setting ctrlPlane.alternativeIssuer.kind=ClusterIssuer and ctrlPlane.alternativeIssuer.name=enterprise-pki-cluster-issuer, the Helm deployment still created self-signed CAs instead of using the external PKI.


Request for Help

  1. How can we correctly use Enterprise PKI as the root CA?
  2. Is there a proper way to override the Helm chart defaults to prevent self-signed CA creation?
  3. Do we need to manually provision the CA secrets and then reference them in the Helm values?
  4. Has anyone successfully used an external CA with OpenZiti in Kubernetes?

Any help or guidance would be much appreciated!

1 Like

You're on the right track, @am3y. To clarify for all readers, you're looking to change the root of trust for the PKI that issues the Ziti controller's identity, not to configure the Ziti controller to trust a 3rd party CA for enrolling identities.

You can accomplish this enterprise single-root-of-trust model by deploying a new Ziti controller with these settings:

  1. set the alternative issuer to the Cert Manager issuer ref you wish to issue the controller's identity (link to Helm template where .ctrlPlane.alternativeIssuer is used).
  2. disable the independent web PKI, causing the controller to have only one PKI from your specified root: webBindingPki.enabled=false.

Known issues that can be fixed in future releases:

  • some unnecessary PKI resources are created and unused with this approach
  • some web PKI features are unavailable when web PKI is disabled, e.g., alt server certs for the web console

Clarifying information: {{ .Release.Name }}-controller-edge-root-issuer will continue to be created and is used to issue the intermediate CA cert that is the edge signer CA from which router and identity enrollments are created because the Ziti controller must own a CA for this purpose.

The controller also supports adding 3rd party CAs (CAs that are external to it's own edge signer CA) for identity enrollment, e.g. SPIRE.

There's no reason we couldn't change the chart so this intermediate CA that is the edge signer CA has an alternative issuer like the ctrl plane CA. In that case, Ziti's edge signer CA has the same root of trust as the controller's identity.

1 Like

Dear @qrkourier

Thank you for your prompt and insightful response to my query. I appreciate your guidance and wanted to let you know that I have successfully addressed the PKI configuration for the Ziti controller.

Now, I’m focusing on setting up the Ziti router and configuring identities and services. Are there any specific considerations or configurations I should be aware of to ensure everything integrates properly with my Enterprise PKI setup?

Looking forward to your insights!

1 Like

You're welcome. I'm glad you found an acceptable solution.

I don't know if the following information will be important for your case, so I'll just state some facts in case they're helpful.

The Ziti controller manages the identity for all routers. The routers certificates are automatically issued by the built-in edge signer CA. When a router runs with the --extend option, then it will immediately renew its identity certificates. This will occur automatically, periodically as well, assuming the filesystem is writable where the identity files are located. The router chart provides a PVC for this purpose.

You have two categories of enrollments you can use to recognize a Ziti (endpoint) identity, e.g. for an edge tunneler: enroll with a certificate from the built-in edge signer CA (default option) or enroll with a certificate from another CA you control and have administratively verified in the Ziti controller.

If you choose to verify your other CA, then you may use it to enroll identities with certificates you issued independently (one ziti identity per certificate), or you may configure the Ziti controller to recognize a "claim" in the certificate, e.g. spiffe id, to represent an existing Ziti identity (many short lived certificates with identical claim map to one Ziti identity by external ID).