You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 93c3473
Browse filesBrowse the repository at this point in the historyBrowse files
1. Remove the obsolete guard rejecting serverIssuerRef + clientCaFromServerTlsSecret=true.
The internal server certificate is always signed by the chart CA (the same
CA that signs the client cert), so clientCaFromServerTlsSecret=true is
correct — its filtered ca.crt is exactly the right trust anchor. The old
workaround (mounting openshell-ca-tls directly) unnecessarily exposed the
CA private key to the gateway container. Remove the client-CA overrides
from docs, CI overlay, and production examples.
2. Route host validation now supports wildcard certificates per RFC 6125:
single-level wildcards like *.example.com match gateway.example.com but
not deep.sub.example.com. Require an explicit openshiftRoute.host when
an external issuer is configured — without one, OpenShift generates a
hostname absent from serverDnsNames.
3. Reject serverIssuerRef.name when certManager.enabled is false — the
external certificate, its Secret mount, and the gateway TLS config all
require cert-manager to be enabled.
Validated on ROSA (dev.dyee.p3) with branch-built images:
- Fresh install with letsencrypt-prod ClusterIssuer
- SNI dual-cert: external hostname served Let's Encrypt cert
- Supervisor mTLS via internal cert path: ConnectSupervisor accepted
- Client CA volume: filtered ca.crt from internal server secret (no key)
- CLI connected via Route + OIDC
Helm tests: 81 pass across 7 suites.
Signed-off-by: Jesse Jaggars <[email protected]>
| certManager.clientCaFromServerTlsSecret | bool |`true`| Mount gateway client CA from the server TLS secret's ca.crt (populated by cert-manager for certs issued by a CA Issuer). Set to false when serverIssuerRef points at an external issuer (its secret's ca.crt would be that issuer's chain, not the CA that signs the client cert). When false, also set server.tls.clientCaSecretName to a secret containing the actual client CA — for example caSecretName's value, since that's the CA the client certificate above is issued from by default. |
147
+
| certManager.clientCaFromServerTlsSecret | bool |`true`| Mount gateway client CA from the internal server TLS secret's ca.crt. The internal server certificate is always signed by the chart CA — the same CA that signs the client (mTLS) certificate — so the default (true) is correct for all configurations, including when serverIssuerRef is set. Only set to false if you mount the client CA from a separate secret via server.tls.clientCaSecretName. |
148
148
| certManager.enabled | bool |`false`| Create cert-manager Issuer and Certificate resources. When enabled, cert-manager owns TLS and the chart runs a JWT-only certgen hook to create the sandbox JWT signing Secret that cert-manager does not manage. |
149
149
| certManager.serverDnsNames | list |`["openshell","openshell.openshell.svc","openshell.openshell.svc.cluster.local","localhost","openshell.localhost","*.openshell.localhost","host.docker.internal"]`| DNS SANs on the cert-manager-issued server certificate. |
150
150
| certManager.serverIpAddresses | list |`["127.0.0.1"]`| IP SANs on the cert-manager-issued server certificate. |
151
-
| certManager.serverIssuerRef | object |`{"group":"","kind":"","name":""}`| Override the issuerRef for the server Certificate (e.g. a real ACME ClusterIssuer for a publicly-trusted cert on an external hostname). Leave name empty to use the chart's own self-signed CA issuer (default). |
151
+
| certManager.serverIssuerRef | object |`{"group":"","kind":"","name":""}`| Override the issuerRef for the external server Certificate (e.g. a real ACME ClusterIssuer for a publicly-trusted cert on an external hostname). When set, the chart creates a second server certificate from this issuer with only the hostnames in serverDnsNames; the internal server certificate is always signed by the chart's own CA. Leave name empty to use the chart CA for all server certificates (default). Requires certManager.enabled=true. |
152
152
| fullnameOverride | string |`""`| Override the full generated resource name. |
153
153
| grpcRoute.enabled | bool |`false`| Create a Gateway API GRPCRoute for the gateway service. |
154
154
| grpcRoute.gateway.className | string |`"eg"`| GatewayClass to reference. Envoy Gateway installs one named "eg". |
Copy file name to clipboardExpand all lines: deploy/helm/openshell/templates/cert-manager-pki.yaml
-3Lines changed: 0 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -46,9 +46,6 @@ spec:
46
46
{{- if and (not .Values.certManager.clientCaFromServerTlsSecret) (eq .Values.server.tls.clientCaSecretName "openshell-server-client-ca") }}
47
47
{{- fail "certManager.clientCaFromServerTlsSecret is false but server.tls.clientCaSecretName is still the default (openshell-server-client-ca), which nothing creates when cert-manager owns TLS. Set server.tls.clientCaSecretName to the secret containing the client CA (e.g. the value of certManager.caSecretName, which defaults to openshell-ca-tls), or set it to empty to disable mTLS client verification." }}
48
48
{{- end }}
49
-
{{- if and $externalServerIssuer .Values.certManager.clientCaFromServerTlsSecret }}
50
-
{{- fail "certManager.serverIssuerRef.name is set but certManager.clientCaFromServerTlsSecret is still true \u2014 the server cert Secret's ca.crt comes from the external issuer, not the CA that signs the client (mTLS) certificate. Set certManager.clientCaFromServerTlsSecret=false and set server.tls.clientCaSecretName to the secret containing the client CA (e.g. the value of certManager.caSecretName, which defaults to openshell-ca-tls)." }}
51
-
{{- end }}
52
49
{{- if $externalServerIssuer }}
53
50
{{- if not .Values.certManager.serverDnsNames }}
54
51
{{- fail "certManager.serverIssuerRef.name is set but certManager.serverDnsNames is empty — the external certificate requires at least one externally-resolvable DNS name." }}
Copy file name to clipboardExpand all lines: deploy/helm/openshell/templates/gateway-config.yaml
+3Lines changed: 3 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,9 @@ One value is intentionally NOT rendered here:
12
12
when server.externalDbSecret is set, otherwise
13
13
--db-url arg for SQLite
14
14
*/}}
15
+
{{- if and .Values.certManager.serverIssuerRef.name (not .Values.certManager.enabled) }}
16
+
{{- fail "certManager.serverIssuerRef.name is set but certManager.enabled is false \u2014 the external server certificate, its Secret mount, and the gateway TLS configuration all require cert-manager to be enabled. Set certManager.enabled=true or remove certManager.serverIssuerRef.name." }}
Copy file name to clipboardExpand all lines: deploy/helm/openshell/templates/route.yaml
+20-2Lines changed: 20 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -5,8 +5,26 @@
5
5
{{- if .Values.server.disableTls }}
6
6
{{- fail "openshiftRoute.enabled=true requires TLS (server.disableTls must be false) \u2014 a passthrough Route forwards encrypted traffic by SNI, so the gateway must terminate its own TLS." }}
7
7
{{- end }}
8
-
{{- if and .Values.openshiftRoute.host .Values.certManager.serverIssuerRef.name .Values.certManager.serverDnsNames (not (has .Values.openshiftRoute.host .Values.certManager.serverDnsNames)) }}
9
-
{{- fail (printf "openshiftRoute.host %q is not listed in certManager.serverDnsNames %v — the Route will forward SNI for a hostname the external certificate does not cover, causing TLS verification failures for CLI clients." .Values.openshiftRoute.host .Values.certManager.serverDnsNames) }}
8
+
{{- if and .Values.certManager.serverIssuerRef.name (not .Values.openshiftRoute.host) }}
9
+
{{- fail "openshiftRoute.enabled=true with certManager.serverIssuerRef requires an explicit openshiftRoute.host \u2014 without one, OpenShift generates a hostname absent from certManager.serverDnsNames, causing the gateway to serve its internal certificate to external clients." }}
10
+
{{- end }}
11
+
{{- if and .Values.openshiftRoute.host .Values.certManager.serverIssuerRef.name .Values.certManager.serverDnsNames }}
{{- if and (ne $prefix $routeHost) (gt (len $prefix) 0) (not (contains "." $prefix)) }}
21
+
{{- $hostCovered = true }}
22
+
{{- end }}
23
+
{{- end }}
24
+
{{- end }}
25
+
{{- if not $hostCovered }}
26
+
{{- fail (printf "openshiftRoute.host %q is not covered by certManager.serverDnsNames %v \u2014 the Route will forward SNI for a hostname the external certificate does not cover, causing TLS verification failures for CLI clients. Exact names and single-level wildcards (e.g. *.example.com) are checked." $routeHost .Values.certManager.serverDnsNames) }}
errorMessage: "certManager.serverIssuerRef.name is set but certManager.clientCaFromServerTlsSecret is still true \u2014 the server cert Secret's ca.crt comes from the external issuer, not the CA that signs the client (mTLS) certificate. Set certManager.clientCaFromServerTlsSecret=false and set server.tls.clientCaSecretName to the secret containing the client CA (e.g. the value of certManager.caSecretName, which defaults to openshell-ca-tls)."
151
-
152
135
- it: fails when serverIssuerRef is set but serverDnsNames contains internal-only names
errorMessage: "certManager.serverIssuerRef.name is set but certManager.enabled is false \u2014 the external server certificate, its Secret mount, and the gateway TLS configuration all require cert-manager to be enabled. Set certManager.enabled=true or remove certManager.serverIssuerRef.name."
Copy file name to clipboardExpand all lines: deploy/helm/openshell/tests/route_test.yaml
+48Lines changed: 48 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -58,6 +58,54 @@ tests:
58
58
- failedTemplate:
59
59
errorMessage: "openshiftRoute.enabled=true requires TLS (server.disableTls must be false) \u2014 a passthrough Route forwards encrypted traffic by SNI, so the gateway must terminate its own TLS."
60
60
61
+
- it: fails when external issuer is set but Route host is empty
errorMessage: "openshiftRoute.enabled=true with certManager.serverIssuerRef requires an explicit openshiftRoute.host \u2014 without one, OpenShift generates a hostname absent from certManager.serverDnsNames, causing the gateway to serve its internal certificate to external clients."
71
+
72
+
- it: accepts a Route host covered by a wildcard serverDnsNames entry
errorMessage: "openshiftRoute.host \"gateway.other.com\" is not covered by certManager.serverDnsNames [*.example.com] \u2014 the Route will forward SNI for a hostname the external certificate does not cover, causing TLS verification failures for CLI clients. Exact names and single-level wildcards (e.g. *.example.com) are checked."
96
+
97
+
- it: rejects a multi-level subdomain against a single-level wildcard
errorMessage: "openshiftRoute.host \"deep.sub.example.com\" is not covered by certManager.serverDnsNames [*.example.com] \u2014 the Route will forward SNI for a hostname the external certificate does not cover, causing TLS verification failures for CLI clients. Exact names and single-level wildcards (e.g. *.example.com) are checked."
0 commit comments