Add EJBCA UpstreamAuthority plugin support to spire-server chart (#873)

Add support for the EJBCA UpstreamAuthority plugin, allowing the SPIRE
server to use an EJBCA instance as its upstream CA over mTLS.

- Add upstreamAuthority.ejbca values (hostname, caName, endEntityProfileName,
  certificateProfileName, optional endEntityName and accountBindingId).
- Render the ejbca UpstreamAuthority block in the server config and count it
  toward the single-upstream-authority guard.
- Mount the mTLS client credentials (and optional CA cert) from a secret,
  either chart-created (secret.create) or externally provided.
- Gate ca_cert_path on secret.data.caCert, mirroring the disk plugin's bundle
  handling for deterministic rendering.
- Regenerate the chart README and add a unit render test.

Signed-off-by: sabsari <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
This commit is contained in:
sabsari
2026-07-13 01:14:37 +00:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 0d6894037c
commit cc164bad6b
7 changed files with 128 additions and 0 deletions
@@ -230,6 +230,19 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr
| `upstreamAuthority.disk.secret.data.certificate` | Certificate to store within disk upstreamAuthority. | `""` |
| `upstreamAuthority.disk.secret.data.key` | Key corresponding to the upstreamAuthority. | `""` |
| `upstreamAuthority.disk.secret.data.bundle` | Trust bundle for upstreamAuthority. | `""` |
| `upstreamAuthority.ejbca.enabled` | Flag to enable upstream authority plugin with EJBCA | `false` |
| `upstreamAuthority.ejbca.hostname` | Hostname of the connected EJBCA server (e.g. "ejbca.example.com:8443") | `""` |
| `upstreamAuthority.ejbca.caName` | Name of a CA in the connected EJBCA instance that will issue the intermediate signing certificates | `""` |
| `upstreamAuthority.ejbca.endEntityProfileName` | Name of an end entity profile in the connected EJBCA instance that is configured to issue SPIFFE certificates | `""` |
| `upstreamAuthority.ejbca.certificateProfileName` | Name of a certificate profile in the connected EJBCA instance that is configured to issue intermediate CA certificates | `""` |
| `upstreamAuthority.ejbca.endEntityName` | (Optional) Customizes how the End Entity Name is selected. One of "cn", "dns", "uri", "ip", or a custom value | `""` |
| `upstreamAuthority.ejbca.accountBindingId` | (Optional) An account binding ID in EJBCA to associate with issued certificates | `""` |
| `upstreamAuthority.ejbca.secret.create` | If disabled requires you to create a secret with the given keys (clientCert, clientKey and optional caCert) yourself. | `true` |
| `upstreamAuthority.ejbca.secret.name` | If secret creation is disabled, the secret with this name will be used. | `spiffe-ejbca-client` |
| `upstreamAuthority.ejbca.secret.data` | If secret creation is enabled, will create a secret with the following mTLS credentials | |
| `upstreamAuthority.ejbca.secret.data.clientCert` | Client certificate (public key) used to authenticate to EJBCA via mTLS. | `""` |
| `upstreamAuthority.ejbca.secret.data.clientKey` | Client key matching the client certificate used to authenticate to EJBCA. | `""` |
| `upstreamAuthority.ejbca.secret.data.caCert` | CA certificate used to validate the EJBCA server's certificate. Leave empty when the EJBCA server uses a publicly trusted certificate. When secret.create is false, set this to any non-empty value to enable ca_cert_path against your externally provided secret (mirrors the disk plugin's bundle behavior). | `""` |
| `upstreamAuthority.awsPCA.enabled` | Flag to enable upstream authority plugin with AWS PCA | `false` |
| `upstreamAuthority.awsPCA.region` | AWS Region to use | `""` |
| `upstreamAuthority.awsPCA.certificateAuthorityARN` | ARN of the "upstream" CA certificate | `""` |
@@ -164,6 +164,17 @@ Create the name of the service account to use
{{- end -}}
{{- end }}
{{- define "spire-server.upstream-ejbca-secret" -}}
{{- $root := . }}
{{- with .Values.upstreamAuthority.ejbca -}}
{{- if eq (.secret.create | toString) "true" -}}
{{ include "spire-server.fullname" $root }}-upstream-ejbca
{{- else -}}
{{ default (include "spire-server.fullname" $root) .secret.name }}
{{- end -}}
{{- end -}}
{{- end }}
{{- define "spire-controller-manager.fullname" -}}
{{ include "spire-server.fullname" . | trimSuffix "-server" }}-controller-manager
{{- end }}
@@ -525,6 +525,30 @@ plugins:
{{- end }}
{{- end }}
{{- with .Values.upstreamAuthority.ejbca }}
{{- if eq (.enabled | toString) "true" }}
{{- $upstreamAuthorityUsed = add1 $upstreamAuthorityUsed }}
UpstreamAuthority:
ejbca:
plugin_data:
hostname: {{ .hostname | quote }}
client_cert_path: "/run/spire/upstream_ejbca/client.crt"
client_cert_key_path: "/run/spire/upstream_ejbca/client.key"
ca_name: {{ .caName | quote }}
end_entity_profile_name: {{ .endEntityProfileName | quote }}
certificate_profile_name: {{ .certificateProfileName | quote }}
{{- if ne .secret.data.caCert "" }}
ca_cert_path: "/run/spire/upstream_ejbca/ca.crt"
{{- end }}
{{- if ne .endEntityName "" }}
end_entity_name: {{ .endEntityName | quote }}
{{- end }}
{{- if ne .accountBindingId "" }}
account_binding_id: {{ .accountBindingId | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.upstreamAuthority.certManager }}
{{- if eq (.enabled | toString) "true" }}
{{- $upstreamAuthorityUsed = add1 $upstreamAuthorityUsed }}
@@ -417,6 +417,11 @@ spec:
mountPath: /run/spire/upstream_ca
readOnly: false
{{ end }}
{{- if eq (.Values.upstreamAuthority.ejbca.enabled | toString) "true" }}
- name: upstream-ejbca
mountPath: /run/spire/upstream_ejbca
readOnly: true
{{ end }}
{{- if gt (len .Values.upstreamAuthority.spire.upstreamDriver) 0 }}
- name: upstream-agent
mountPath: /run/spire/upstream_agent
@@ -650,6 +655,11 @@ spec:
secret:
secretName: {{ include "spire-server.upstream-ca-secret" . }}
{{- end }}
{{- if eq (.Values.upstreamAuthority.ejbca.enabled | toString) "true" }}
- name: upstream-ejbca
secret:
secretName: {{ include "spire-server.upstream-ejbca-secret" . }}
{{- end }}
{{- if gt (len .Values.upstreamAuthority.spire.upstreamDriver) 0 }}
- name: upstream-agent
csi:
@@ -0,0 +1,20 @@
{{- $root := . }}
{{- with .Values.upstreamAuthority.ejbca }}
{{- if and (eq (.enabled | toString) "true") (eq (.secret.create | toString) "true") }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "spire-server.upstream-ejbca-secret" $root }}
namespace: {{ include "spire-server.namespace" $root }}
labels:
{{- include "spire-server.labels" $root | nindent 4 }}
data:
{{- with .secret.data }}
client.crt: {{ .clientCert | b64enc }}
client.key: {{ .clientKey | b64enc }}
{{- if ne .caCert "" }}
ca.crt: {{ .caCert | b64enc }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
@@ -454,6 +454,34 @@ upstreamAuthority:
key: ""
## @param upstreamAuthority.disk.secret.data.bundle Trust bundle for upstreamAuthority.
bundle: ""
ejbca:
## @param upstreamAuthority.ejbca.enabled Flag to enable upstream authority plugin with EJBCA
enabled: false
## @param upstreamAuthority.ejbca.hostname Hostname of the connected EJBCA server (e.g. "ejbca.example.com:8443")
hostname: ""
## @param upstreamAuthority.ejbca.caName Name of a CA in the connected EJBCA instance that will issue the intermediate signing certificates
caName: ""
## @param upstreamAuthority.ejbca.endEntityProfileName Name of an end entity profile in the connected EJBCA instance that is configured to issue SPIFFE certificates
endEntityProfileName: ""
## @param upstreamAuthority.ejbca.certificateProfileName Name of a certificate profile in the connected EJBCA instance that is configured to issue intermediate CA certificates
certificateProfileName: ""
## @param upstreamAuthority.ejbca.endEntityName (Optional) Customizes how the End Entity Name is selected. One of "cn", "dns", "uri", "ip", or a custom value
endEntityName: ""
## @param upstreamAuthority.ejbca.accountBindingId (Optional) An account binding ID in EJBCA to associate with issued certificates
accountBindingId: ""
secret:
## @param upstreamAuthority.ejbca.secret.create If disabled requires you to create a secret with the given keys (clientCert, clientKey and optional caCert) yourself.
create: true
## @param upstreamAuthority.ejbca.secret.name If secret creation is disabled, the secret with this name will be used.
name: "spiffe-ejbca-client"
## @extra upstreamAuthority.ejbca.secret.data If secret creation is enabled, will create a secret with the following mTLS credentials
data:
## @param upstreamAuthority.ejbca.secret.data.clientCert Client certificate (public key) used to authenticate to EJBCA via mTLS.
clientCert: ""
## @param upstreamAuthority.ejbca.secret.data.clientKey Client key matching the client certificate used to authenticate to EJBCA.
clientKey: ""
## @param upstreamAuthority.ejbca.secret.data.caCert CA certificate used to validate the EJBCA server's certificate. Leave empty when the EJBCA server uses a publicly trusted certificate. When secret.create is false, set this to any non-empty value to enable ca_cert_path against your externally provided secret (mirrors the disk plugin's bundle behavior).
caCert: ""
awsPCA:
## @param upstreamAuthority.awsPCA.enabled Flag to enable upstream authority plugin with AWS PCA
enabled: false