Update spire-identity-exchange for 0.4.0 (#900)

* Update spire-identity-exchange for 0.4.0

Signed-off-by: Kevin Fox <[email protected]>

* Understand the plugin config

Signed-off-by: Kevin Fox <[email protected]>

* Fix test

Signed-off-by: Kevin Fox <[email protected]>

* Update ip

Signed-off-by: Kevin Fox <[email protected]>

* Update name

Signed-off-by: Kevin Fox <[email protected]>

* Update name

Signed-off-by: Kevin Fox <[email protected]>

* Update name

Signed-off-by: Kevin Fox <[email protected]>

* Fix broken socket path

Signed-off-by: Kevin Fox <[email protected]>

* Nope, it was right before

Signed-off-by: Kevin Fox <[email protected]>

* Try disabling the spiffe plugin for now

Signed-off-by: Kevin Fox <[email protected]>

* Try logging more

Signed-off-by: Kevin Fox <[email protected]>

* Map non container behavior

Signed-off-by: Kevin Fox <[email protected]>

* Map non container behavior

Signed-off-by: Kevin Fox <[email protected]>

* Map non container behavior

Signed-off-by: Kevin Fox <[email protected]>

* Map non container behavior

Signed-off-by: Kevin Fox <[email protected]>

* Map non container behavior

Signed-off-by: Kevin Fox <[email protected]>

* Map non container behavior

Signed-off-by: Kevin Fox <[email protected]>

* Map non container behavior

Signed-off-by: Kevin Fox <[email protected]>

* Add missing csi driver settings

Signed-off-by: Kevin Fox <[email protected]>

* Test

Signed-off-by: Kevin Fox <[email protected]>

* Test

Signed-off-by: Kevin Fox <[email protected]>

* Fix

Signed-off-by: Kevin Fox <[email protected]>

* Use local oidc discovery provider path by default

Signed-off-by: Kevin Fox <[email protected]>

* Enable spire-identity-exchange in shared infrastructure

Signed-off-by: Kevin Fox <[email protected]>

* Update timeout

Signed-off-by: Kevin Fox <[email protected]>

* Update timeout

Signed-off-by: Kevin Fox <[email protected]>

* Test config

Signed-off-by: Kevin Fox <[email protected]>

* Test config

Signed-off-by: Kevin Fox <[email protected]>

* Test config

Signed-off-by: Kevin Fox <[email protected]>

* Test config

Signed-off-by: Kevin Fox <[email protected]>

* Fix

Signed-off-by: Kevin Fox <[email protected]>

* Fix

Signed-off-by: Kevin Fox <[email protected]>

* Bump spire-ha-agent version to fix issue

Signed-off-by: Kevin Fox <[email protected]>

* Fix

Signed-off-by: Kevin Fox <[email protected]>

* Fix

Signed-off-by: Kevin Fox <[email protected]>

* Bump version

Signed-off-by: Kevin Fox <[email protected]>

* Update version bits to match what it should be, minus final bump

Signed-off-by: Kevin Fox <[email protected]>

---------

Signed-off-by: Kevin Fox <[email protected]>
Signed-off-by: kfox1111 <[email protected]>
Co-authored-by: Faisal Memon <[email protected]>
This commit is contained in:
kfox1111
2026-08-18 05:17:43 +00:00
committed by GitHub
co-authored by Faisal Memon
parent de48d14312
commit 07ba722da0
45 changed files with 2120 additions and 580 deletions
+8
View File
@@ -25,6 +25,14 @@ $(kubectl get pods -o name -n "$1" | while read -r line; do echo logs for "${lin
$( ([[ -n "$2" ]] && kubectl get pods -o name -n "$2") | while read -r line; do echo logs for "${line}"; kubectl logs -n "$2" "${line}" --all-containers=true --ignore-errors=true; done) $( ([[ -n "$2" ]] && kubectl get pods -o name -n "$2") | while read -r line; do echo logs for "${line}"; kubectl logs -n "$2" "${line}" --all-containers=true --ignore-errors=true; done)
\`\`\` \`\`\`
MAX_BYTES=1048576
if [ "$(wc -c < "${GITHUB_STEP_SUMMARY}")" -gt "${MAX_BYTES}" ]; then
# shellcheck disable=SC2094
truncate -s $((MAX_BYTES - 14)) "${GITHUB_STEP_SUMMARY}"
# shellcheck disable=SC2094
printf "\ntruncated...\n" >> "${GITHUB_STEP_SUMMARY}"
fi
EOF EOF
} }
+1 -1
View File
@@ -3,7 +3,7 @@ name: spire-ha-agent
description: A Helm chart to install the SPIRE HA agent. description: A Helm chart to install the SPIRE HA agent.
type: application type: application
version: 0.3.0 version: 0.3.0
appVersion: "0.2.0" appVersion: "0.3.0"
keywords: ["spiffe", "spire-ha-agent"] keywords: ["spiffe", "spire-ha-agent"]
home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire-ha-agent home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire-ha-agent
sources: sources:
+1 -1
View File
@@ -3,7 +3,7 @@ name: spire-identity-exchange
description: A Helm chart to install the SPIRE Identity Exchange. description: A Helm chart to install the SPIRE Identity Exchange.
type: application type: application
version: 0.2.0 version: 0.2.0
appVersion: "v0.3.0" appVersion: "v0.5.0"
keywords: ["spiffe", "spire", "identity exchange"] keywords: ["spiffe", "spire", "identity exchange"]
home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire-identity-exchange home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire-identity-exchange
sources: sources:
+166 -57
View File
@@ -1,6 +1,6 @@
# spire-identity-exchange # spire-identity-exchange
![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.3.0](https://img.shields.io/badge/AppVersion-0.3.0-informational?style=flat-square) ![Version: 0.2.0](https://img.shields.io/badge/Version-0.2.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.5.0](https://img.shields.io/badge/AppVersion-0.5.0-informational?style=flat-square)
A Helm chart to install the SPIRE Identity Exchange. A Helm chart to install the SPIRE Identity Exchange.
@@ -18,6 +18,54 @@ A Helm chart to install the SPIRE Identity Exchange.
* <https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire-identity-exchange> * <https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire-identity-exchange>
## Listeners
Serving is a two-axis matrix: protocol (gRPC or REST) crossed with the source of the
certificate the listener presents. All four listeners are independent and can run at once.
| Values block | Serves with | Default port | Default |
| -------------- | ---------------------------------------------------------- | ------------ | ------- |
| `tls.rest` | the certificate from `tls.externalSecret` / `tls.certManager` | 8444 | off |
| `tls.grpc` | the certificate from `tls.externalSecret` / `tls.certManager` | 8443 | off |
| `spiffe.rest` | this deployment's own X509-SVID | 8544 | **on** |
| `spiffe.grpc` | this deployment's own X509-SVID | 8543 | off |
The `spiffe.*` listeners need no certificate files: the SVID is fetched from the SPIRE Agent
Workload API and rotated automatically, so a SPIFFE-only install requires neither cert-manager
nor a TLS Secret. A cert source under `tls:` is required only when `tls.rest` or `tls.grpc` is
enabled. Client authentication is identical on all four — callers present a bearer token.
With `tls.certManager`, the requested certificate's `dnsNames` are taken from whichever exposures
are enabled — the `ingress.host`, the `gatewayAPI.host`, or both — across every enabled `tls.*`
listener, deduplicated. Each enabled `tls.*` listener must therefore have an ingress or a gateway
enabled, unless you set `tls.certManager.certificate.dnsNames` explicitly.
## The stack selector
Every exchange addresses a **stack**: an entry in `auth.stacks`, or — with
`auth.passthroughPlugins` (the default) — a single plugin addressed under its own name. It is
the `{stack}` segment of the REST path (`/api/v1/svid/{stack}/x509`).
As of app version v0.4.0 the exchange asserts one selector on its own behalf, naming the stack
that was addressed:
| Selector type | Value | Example |
| ------------------------ | ---------------------- | ---------------------------------------------- |
| `spire_identity_exchange` | `stack:name:<stack>` | `spire_identity_exchange:stack:name:k8s_psat` |
Add it to a registration entry to scope that entry to a single stack:
```yaml
controllerManager:
identities:
clusterStaticEntries:
test:
selectors:
- k8s_psat:namespace:default
- k8s_psat:service_account_name:default
- spire_identity_exchange:stack:name:k8s_psat # only issuable via this stack
```
<!-- The parameters section is generated using helm-docs.sh and should not be edited by hand. --> <!-- The parameters section is generated using helm-docs.sh and should not be edited by hand. -->
## Parameters ## Parameters
@@ -57,19 +105,12 @@ A Helm chart to install the SPIRE Identity Exchange.
| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` | | `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `5` |
| `podAnnotations` | Pod annotations for SPIRE Identity Exchange | `{}` | | `podAnnotations` | Pod annotations for SPIRE Identity Exchange | `{}` |
| `podLabels` | Labels to add to pods | `{}` | | `podLabels` | Labels to add to pods | `{}` |
| `tls.externalSecret.enabled` | Provide your own certificate/key via tls style Kubernetes Secret | `false` |
| `tls.externalSecret.secretName` | Specify which Secret to use | `""` |
| `tls.certManager.enabled` | Use certificateManager to create the certificate | `false` |
| `tls.certManager.issuer.create` | Create an issuer to use to issue the certificate | `true` |
| `tls.certManager.issuer.acme.email` | Must be set in order to register with LetsEncrypt. By setting, you agree to their Terms of Service | `""` |
| `tls.certManager.issuer.acme.server` | Server to use to get certificate. Defaults to LetsEncrypt | `https://acme-v02.api.letsencrypt.org/directory` |
| `tls.certManager.issuer.acme.solvers` | Configure the issuer solvers. Defaults to http01 via ingress. | `{}` |
| `tls.certManager.certificate.dnsNames` | Override the dnsNames on the certificate request. Defaults to the same settings as Ingress | `[]` |
| `tls.certManager.certificate.issuerRef.group` | If you are using an external plugin, specify the group for it here | `""` |
| `tls.certManager.certificate.issuerRef.kind` | Kind of the issuer reference. Override if you want to use a ClusterIssuer | `Issuer` |
| `tls.certManager.certificate.issuerRef.name` | Name of the issuer to use. If unset, it will use the name of the built in issuer | `""` |
| `config.logLevel` | The log level, valid values are "debug", "info", "warn", and "error" | `info` | | `config.logLevel` | The log level, valid values are "debug", "info", "warn", and "error" | `info` |
| `config.logFormat` | The log format, valid values are "text" and "json" | `text` | | `config.logFormat` | The log format, valid values are "text" and "json" | `text` |
| `telemetry.prometheus.port` | Port for prometheus metrics | `4950` |
| `telemetry.prometheus.podMonitor.enabled` | Enable podMonitor for prometheus | `false` |
| `telemetry.prometheus.podMonitor.namespace` | Override where to install the podMonitor, if not set will use the same namespace as the helm release | `""` |
| `telemetry.prometheus.podMonitor.labels` | Pod labels to filter for prometheus monitoring | `{}` |
| `imagePullSecrets` | Image pull secret names | `[]` | | `imagePullSecrets` | Image pull secret names | `[]` |
| `nameOverride` | Name override | `""` | | `nameOverride` | Name override | `""` |
| `fullnameOverride` | Full name override | `""` | | `fullnameOverride` | Full name override | `""` |
@@ -83,54 +124,122 @@ A Helm chart to install the SPIRE Identity Exchange.
| `autoscaling.targetCPUUtilizationPercentage` | Target CPU utlization that triggers autoscaling | `80` | | `autoscaling.targetCPUUtilizationPercentage` | Target CPU utlization that triggers autoscaling | `80` |
| `autoscaling.targetMemoryUtilizationPercentage` | Target Memory utlization that triggers autoscaling | `80` | | `autoscaling.targetMemoryUtilizationPercentage` | Target Memory utlization that triggers autoscaling | `80` |
| `nodeSelector` | Node selector | `{}` | | `nodeSelector` | Node selector | `{}` |
| `tolerations` | iist of tolerations | `[]` | | `tolerations` | list of tolerations | `[]` |
| `affinity` | Node affinity | `{}` | | `affinity` | Node affinity | `{}` |
| `trustDomain` | Set the trust domain to be used for the SPIFFE identifiers | `example.org` | | `trustDomain` | Set the trust domain to be used for the SPIFFE identifiers | `example.org` |
| `clusterName` | The name of this Kubernetes cluster, as it appears in SPIFFE ID paths | `example-cluster` |
| `jwtIssuer` | The issuer URL for JWT-SVIDs. Defaults to https://oidc-discovery.$trustDomain | `""` |
| `clusterDomain` | The name of the Kubernetes cluster (`kubeadm init --service-dns-domain`) | `cluster.local` | | `clusterDomain` | The name of the Kubernetes cluster (`kubeadm init --service-dns-domain`) | `cluster.local` |
| `auth.plugins` | Plugins to load | `{}` | | `auth.plugins.k8s_psat.enabled` | Enable the k8s psat plugin | `true` |
| `auth.stacks` | Stacks to load | `{}` | | `auth.plugins.k8s_psat.config.audiences` | The audiences to allow | `[]` |
| `rest.enabled` | Enable the rest service | `true` | | `auth.plugins.k8s_psat.config.allowedServiceAccounts` | The service accounts that are allowed | `[]` |
| `rest.service.type` | Service type | `ClusterIP` | | `auth.plugins.spiffe.enabled` | Enable the spiffe plugin | `true` |
| `rest.service.port` | port for the service | `443` | | `auth.plugins.spiffe.keySource` | What source to use to fetch the keys. Can be oidc or oidcLocal. oidcLocal forces discoveryURL to be the internal discovery address. | `oidcLocal` |
| `rest.service.annotations` | Annotations for service resource | `{}` | | `auth.plugins.spiffe.csiDriverName` | The CSI driver providing the SPIRE Agent workload socket this plugin attests against. Defaults to the chart level csiDriverName. Requires config.connectWithTrustBundle. | |
| `rest.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` | | `auth.plugins.spiffe.config.issuerURL` | The url to connect to for JWKS discovery | `${SPIFFE_JWT_ISSUER}` |
| `rest.ingress.enabled` | Flag to enable ingress | `false` | | `auth.plugins.spiffe.config.trustDomain` | The trust domain to use | `${SPIFFE_TRUST_DOMAIN}` |
| `rest.ingress.className` | Ingress class name | `""` | | `auth.plugins.spiffe.config.pathPatterns` | The service accounts that are allowed | `[]` |
| `rest.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` | | `auth.plugins.spiffe.config.audiences` | The audiences to allow | `[]` |
| `rest.ingress.annotations` | Annotations for ingress object | `{}` | | `auth.plugins.spiffe.config.connectWithTrustBundle` | Use the trust bundle to validate the issuerURL | `true` |
| `rest.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The rest of the rules will be autogenerated. For more customizability, use hosts[] instead. | `spire-identity-exchange-rest` | | `auth.stacks.image_pull.enabled` | Enable the image_pull stack | `true` |
| `rest.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` | | `auth.stacks.image_pull.plugins` | List of plugins that are required by this stack | `[]` |
| `rest.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` | | `auth.unsupportedBuiltInPlugins` | Unsupported mechanism to use plugins not yet supported by the chart. | `{}` |
| `rest.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` | | `auth.passthroughPlugins` | Address each plugin as a stack of its own, in addition to any stacks defined | `false` |
| `rest.gatewayAPI.enabled` | Flag to expose the REST endpoint via Gateway API | `false` | | `tls.externalSecret.enabled` | Provide your own certificate/key via tls style Kubernetes Secret | `false` |
| `rest.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-rest` | | `tls.externalSecret.secretName` | Specify which Secret to use | `""` |
| `rest.gatewayAPI.tlsSecret` | Secret with the TLS cert for edge termination. Blank keeps passthrough. | `""` | | `tls.certManager.enabled` | Use certificateManager to create the certificate | `false` |
| `rest.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` | | `tls.certManager.issuer.create` | Create an issuer to use to issue the certificate | `true` |
| `rest.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` | | `tls.certManager.issuer.acme.email` | Must be set in order to register with LetsEncrypt. By setting, you agree to their Terms of Service | `""` |
| `rest.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` | | `tls.certManager.issuer.acme.server` | Server to use to get certificate. Defaults to LetsEncrypt | `https://acme-v02.api.letsencrypt.org/directory` |
| `rest.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` | | `tls.certManager.issuer.acme.solvers` | Configure the issuer solvers. Defaults to http01 via ingress. | `{}` |
| `rest.gatewayAPI.backendTLS.caCertificateRefs` | ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap. | `[]` | | `tls.certManager.certificate.dnsNames` | Override the dnsNames on the certificate request. Defaults to the same settings as Ingress | `[]` |
| `grpc.enabled` | Enable the grpc service | `false` | | `tls.certManager.certificate.issuerRef.group` | If you are using an external plugin, specify the group for it here | `""` |
| `grpc.service.type` | Service type | `ClusterIP` | | `tls.certManager.certificate.issuerRef.kind` | Kind of the issuer reference. Override if you want to use a ClusterIssuer | `Issuer` |
| `grpc.service.port` | port for the service | `443` | | `tls.certManager.certificate.issuerRef.name` | Name of the issuer to use. If unset, it will use the name of the built in issuer | `""` |
| `grpc.service.annotations` | Annotations for service resource | `{}` | | `tls.rest.enabled` | Enable the REST listener served with the certificate from disk | `false` |
| `grpc.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` | | `tls.rest.port` | Container port for the REST listener served with the certificate from disk | `8444` |
| `grpc.ingress.enabled` | Flag to enable ingress | `false` | | `tls.rest.service.type` | Service type | `ClusterIP` |
| `grpc.ingress.className` | Ingress class name | `""` | | `tls.rest.service.port` | port for the service | `443` |
| `grpc.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` | | `tls.rest.service.annotations` | Annotations for service resource | `{}` |
| `grpc.ingress.annotations` | Annotations for ingress object | `{}` | | `tls.rest.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` |
| `grpc.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The grpc of the rules will be autogenerated. For more customizability, use hosts[] instead. | `spire-identity-exchange-grpc` | | `tls.rest.ingress.enabled` | Flag to enable ingress | `false` |
| `grpc.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` | | `tls.rest.ingress.className` | Ingress class name | `""` |
| `grpc.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` | | `tls.rest.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `grpc.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` | | `tls.rest.ingress.annotations` | Annotations for ingress object | `{}` |
| `grpc.gatewayAPI.enabled` | Flag to expose the gRPC endpoint via Gateway API | `false` | | `tls.rest.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The rest of the rules will be autogenerated. For more customizability, use hosts[] instead. | `spire-identity-exchange-rest` |
| `grpc.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-grpc` | | `tls.rest.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` |
| `grpc.gatewayAPI.tlsSecret` | Secret with the TLS cert for edge termination. Blank keeps passthrough. | `""` | | `tls.rest.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` |
| `grpc.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` | | `tls.rest.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` |
| `grpc.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` | | `tls.rest.gatewayAPI.enabled` | Flag to expose the endpoint via Gateway API | `false` |
| `grpc.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` | | `tls.rest.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-rest` |
| `grpc.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` | | `tls.rest.gatewayAPI.tlsSecret` | Secret with the TLS cert for edge termination. Blank keeps passthrough. | `""` |
| `grpc.gatewayAPI.backendTLS.caCertificateRefs` | ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap. | `[]` | | `tls.rest.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` |
| `tls.rest.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` |
| `tls.rest.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` |
| `tls.rest.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` |
| `tls.rest.gatewayAPI.backendTLS.caCertificateRefs` | ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap. | `[]` |
| `tls.grpc.enabled` | Enable the gRPC listener served with the certificate from disk | `false` |
| `tls.grpc.port` | Container port for the gRPC listener served with the certificate from disk | `8443` |
| `tls.grpc.service.type` | Service type | `ClusterIP` |
| `tls.grpc.service.port` | port for the service | `443` |
| `tls.grpc.service.annotations` | Annotations for service resource | `{}` |
| `tls.grpc.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` |
| `tls.grpc.ingress.enabled` | Flag to enable ingress | `false` |
| `tls.grpc.ingress.className` | Ingress class name | `""` |
| `tls.grpc.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `tls.grpc.ingress.annotations` | Annotations for ingress object | `{}` |
| `tls.grpc.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The grpc of the rules will be autogenerated. For more customizability, use hosts[] instead. | `spire-identity-exchange-grpc` |
| `tls.grpc.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` |
| `tls.grpc.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` |
| `tls.grpc.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` |
| `tls.grpc.gatewayAPI.enabled` | Flag to expose the endpoint via Gateway API | `false` |
| `tls.grpc.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-grpc` |
| `tls.grpc.gatewayAPI.tlsSecret` | Secret with the TLS cert for edge termination. Blank keeps passthrough. | `""` |
| `tls.grpc.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` |
| `tls.grpc.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` |
| `tls.grpc.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` |
| `tls.grpc.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` |
| `tls.grpc.gatewayAPI.backendTLS.caCertificateRefs` | ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap. | `[]` |
| `spiffe.rest.enabled` | Enable the REST listener served with this deployment's own X509-SVID | `true` |
| `spiffe.rest.port` | Container port for the REST listener served with this deployment's own X509-SVID | `8544` |
| `spiffe.rest.service.type` | Service type | `ClusterIP` |
| `spiffe.rest.service.port` | port for the service | `443` |
| `spiffe.rest.service.annotations` | Annotations for service resource | `{}` |
| `spiffe.rest.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` |
| `spiffe.rest.ingress.enabled` | Flag to enable ingress | `false` |
| `spiffe.rest.ingress.className` | Ingress class name | `""` |
| `spiffe.rest.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `spiffe.rest.ingress.annotations` | Annotations for ingress object | `{}` |
| `spiffe.rest.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The rest of the rules will be autogenerated. For more customizability, use hosts[] instead. | `spire-identity-exchange-rest-spiffe` |
| `spiffe.rest.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` |
| `spiffe.rest.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` |
| `spiffe.rest.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` |
| `spiffe.rest.gatewayAPI.enabled` | Flag to expose the endpoint via Gateway API | `false` |
| `spiffe.rest.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-rest-spiffe` |
| `spiffe.rest.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` |
| `spiffe.rest.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` |
| `spiffe.rest.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` |
| `spiffe.rest.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` |
| `spiffe.grpc.enabled` | Enable the gRPC listener served with this deployment's own X509-SVID | `false` |
| `spiffe.grpc.port` | Container port for the gRPC listener served with this deployment's own X509-SVID | `8543` |
| `spiffe.grpc.service.type` | Service type | `ClusterIP` |
| `spiffe.grpc.service.port` | port for the service | `443` |
| `spiffe.grpc.service.annotations` | Annotations for service resource | `{}` |
| `spiffe.grpc.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` |
| `spiffe.grpc.ingress.enabled` | Flag to enable ingress | `false` |
| `spiffe.grpc.ingress.className` | Ingress class name | `""` |
| `spiffe.grpc.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `spiffe.grpc.ingress.annotations` | Annotations for ingress object | `{}` |
| `spiffe.grpc.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The grpc of the rules will be autogenerated. For more customizability, use hosts[] instead. | `spire-identity-exchange-grpc-spiffe` |
| `spiffe.grpc.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` |
| `spiffe.grpc.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` |
| `spiffe.grpc.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` |
| `spiffe.grpc.gatewayAPI.enabled` | Flag to expose the endpoint via Gateway API | `false` |
| `spiffe.grpc.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-grpc-spiffe` |
| `spiffe.grpc.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` |
| `spiffe.grpc.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` |
| `spiffe.grpc.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` |
| `spiffe.grpc.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` |
| `tools.kubectl.image.registry` | The OCI registry to pull the image from | `registry.k8s.io` | | `tools.kubectl.image.registry` | The OCI registry to pull the image from | `registry.k8s.io` |
| `tools.kubectl.image.repository` | The repository within the registry | `kubectl` | | `tools.kubectl.image.repository` | The repository within the registry | `kubectl` |
| `tools.kubectl.image.pullPolicy` | The image pull policy | `IfNotPresent` | | `tools.kubectl.image.pullPolicy` | The image pull policy | `IfNotPresent` |
@@ -1,14 +0,0 @@
spire-identity-exchange:
enabled: true
tls:
externalSecret:
enabled: true
secretName: spire-identity-exchange
auth:
plugins:
- plugin: k8s_psat
config:
audiences:
- spire-identity-exchange
allowedServiceAccounts:
- default/default
@@ -92,6 +92,64 @@ Create the name of the service account to use
{{- printf "/spiffe-workload-api/%s" .Values.agentSocketName }} {{- printf "/spiffe-workload-api/%s" .Values.agentSocketName }}
{{- end }} {{- end }}
{{/*
Volume name for an extra SPIFFE CSI driver. Driver names are DNS subdomains and may
contain dots, which a volume name (a DNS-1123 label) may not, so squash every run of
non-alphanumeric characters down to a single dash.
Args: the driver name as a string
*/}}
{{- define "spire-identity-exchange.csi-volume-name" -}}
{{- printf "spiffe-workload-api-%s" (trimAll "-" (regexReplaceAll "[^a-z0-9]+" (lower .) "-")) | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Path to the SPIRE Agent workload socket one auth plugin should talk to. A plugin that
names no driver of its own, or names the one the exchange itself uses, gets the socket
already mounted for the pod; anything else gets its own mount under /spiffe-workload-apis.
Args: dict "root" <root context> "driver" <csi driver name, may be empty>
*/}}
{{- define "spire-identity-exchange.plugin-workload-api-socket-path" -}}
{{- $root := .root }}
{{- $driver := .driver | default "" }}
{{- if or (eq $driver "") (eq $driver $root.Values.csiDriverName) }}
{{- include "spire-identity-exchange.workload-api-socket-path" $root }}
{{- else }}
{{- printf "/spiffe-workload-apis/%s/%s" $driver $root.Values.agentSocketName }}
{{- end }}
{{- end }}
{{/*
The CSI drivers this release must mount in addition to the pod's own, collected from the
enabled spiffe auth plugins. Deduplicated, so two plugins naming the same driver share one
volume. Returns JSON of driver name -> volume name; callers pipe it through fromJson.
*/}}
{{- define "spire-identity-exchange.extra-csi-drivers" -}}
{{- $root := . }}
{{- $drivers := dict }}
{{- $volumeNames := dict }}
{{- range $name, $config := .Values.auth.plugins }}
{{- $config = $config | default dict }}
{{- if ne (dig "enabled" true $config) false }}
{{- $pluginType := include "spire-identity-exchange.plugin-type" (dict "root" $root "name" $name "config" $config) }}
{{- $driver := dig "csiDriverName" "" $config }}
{{- if and (eq $pluginType "spiffe") (not (empty $driver)) }}
{{- if not (kindIs "string" $driver) }}
{{- fail (printf "auth.plugins.%s.csiDriverName: expected string, got %s" $name (kindOf $driver)) }}
{{- end }}
{{- if ne $driver $root.Values.csiDriverName }}
{{- $volumeName := include "spire-identity-exchange.csi-volume-name" $driver }}
{{- if and (hasKey $volumeNames $volumeName) (ne (index $volumeNames $volumeName) $driver) }}
{{- fail (printf "auth.plugins.%s.csiDriverName: %q and %q both reduce to the volume name %q. Volume names allow only lowercase alphanumerics and dashes, so these two drivers cannot be told apart; rename one so they differ by more than punctuation." $name $driver (index $volumeNames $volumeName) $volumeName) }}
{{- end }}
{{- $_ := set $volumeNames $volumeName $driver }}
{{- $_ := set $drivers $driver $volumeName }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- $drivers | toJson }}
{{- end }}
{{- define "spire-identity-exchange.podSecurityContext" -}} {{- define "spire-identity-exchange.podSecurityContext" -}}
{{- $podSecurityContext := include "spire-lib.podsecuritycontext" . | fromYaml }} {{- $podSecurityContext := include "spire-lib.podsecuritycontext" . | fromYaml }}
{{- $openshift := ((.Values).global).openshift | default false }} {{- $openshift := ((.Values).global).openshift | default false }}
@@ -131,3 +189,57 @@ Create the name of the service account to use
{{ .Release.Name }}-server.{{ include "spire-identity-exchange.server.namespace" . }} {{ .Release.Name }}-server.{{ include "spire-identity-exchange.server.namespace" . }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- define "spire-identity-exchange.plugin-type" }}
{{- $type := .name }}
{{- with .config.plugin }}
{{- $type = . }}
{{- end }}
{{- if not (has $type (list "k8s_psat" "spiffe" "github" "gitlab" )) }}
{{- fail (printf "Unknown plugin type specified: %s" $type) }}
{{- end }}
{{- printf "%s" $type }}
{{- end }}
{{/*
Validate one plugin's config block against the option table for its type.
Emits nothing; only fails.
Args: dict "name" <instance name> "type" <plugin type> "config" <config map>
"options" <dict of option name -> "string" | "[]string" | "bool">
*/}}
{{- define "spire-identity-exchange.check-plugin-options" }}
{{- $ctx := . }}
{{- $valid := keys $ctx.options | sortAlpha | join ", " }}
{{- range $key, $val := $ctx.config }}
{{- if not (hasKey $ctx.options $key) }}
{{- fail (printf "auth.plugins.%s.config: %q is not a valid option for plugin type %q (valid options: %s). Use auth.unsupportedBuiltInPlugins to pass through options this chart does not model." $ctx.name $key $ctx.type $valid) }}
{{- end }}
{{- $want := index $ctx.options $key }}
{{- if eq $want "[]string" }}
{{- if not (kindIs "slice" $val) }}
{{- fail (printf "auth.plugins.%s.config.%s: expected a list of strings, got %s" $ctx.name $key (kindOf $val)) }}
{{- end }}
{{- range $val }}
{{- if not (kindIs "string" .) }}
{{- fail (printf "auth.plugins.%s.config.%s: every entry must be a string, got %s" $ctx.name $key (kindOf .)) }}
{{- end }}
{{- end }}
{{- else if not (kindIs $want $val) }}
{{- fail (printf "auth.plugins.%s.config.%s: expected %s, got %s" $ctx.name $key $want (kindOf $val)) }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Fail if any of the named options is absent or empty. Emits nothing.
Args: dict "name" <instance name> "type" <plugin type> "config" <config map>
"required" <list of option names>
*/}}
{{- define "spire-identity-exchange.check-plugin-required" }}
{{- $ctx := . }}
{{- range $ctx.required }}
{{- if empty (index $ctx.config .) }}
{{- fail (printf "auth.plugins.%s.config.%s is required for plugin type %q" $ctx.name . $ctx.type) }}
{{- end }}
{{- end }}
{{- end }}
@@ -4,13 +4,19 @@ dnsNames:
{{- if ne (len .Values.tls.certManager.certificate.dnsNames) 0 }} {{- if ne (len .Values.tls.certManager.certificate.dnsNames) 0 }}
{{- toYaml .Values.tls.certManager.certificate.dnsNames | nindent 4 }} {{- toYaml .Values.tls.certManager.certificate.dnsNames | nindent 4 }}
{{- else }} {{- else }}
{{- if .Values.rest.enabled }} {{- $hosts := list }}
- {{ include "spire-lib.ingress-calculated-name" (dict "ingress" .Values.rest.ingress "Values" .Values) }} {{- range $l := list .Values.tls.rest .Values.tls.grpc }}
{{- if $l.enabled }}
{{- if $l.ingress.enabled }}
{{- $hosts = append $hosts (include "spire-lib.ingress-calculated-name" (dict "ingress" $l.ingress "Values" $.Values) | trim) }}
{{- end }} {{- end }}
{{- if .Values.grpc.enabled }} {{- if $l.gatewayAPI.enabled }}
- {{ include "spire-lib.ingress-calculated-name" (dict "ingress" .Values.grpc.ingress "Values" .Values) }} {{- $hosts = append $hosts (include "spire-lib.ingress-calculated-name" (dict "ingress" (dict "host" $l.gatewayAPI.host) "Values" $.Values) | trim) }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- end }}
{{- toYaml (uniq $hosts) | nindent 4 }}
{{- end }}
issuerRef: issuerRef:
{{- with .Values.tls.certManager.certificate.issuerRef.group }} {{- with .Values.tls.certManager.certificate.issuerRef.group }}
group: {{ . }} group: {{ . }}
@@ -19,7 +25,7 @@ issuerRef:
name: {{ default $fullName .Values.tls.certManager.certificate.issuerRef.name }} name: {{ default $fullName .Values.tls.certManager.certificate.issuerRef.name }}
secretName: {{ $fullName }}-cert secretName: {{ $fullName }}-cert
{{- end }} {{- end }}
{{- if .Values.tls.certManager.enabled }} {{- if and .Values.tls.certManager.enabled (or .Values.tls.rest.enabled .Values.tls.grpc.enabled) }}
--- ---
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
@@ -1,3 +1,5 @@
{{- $fileTLS := or .Values.tls.rest.enabled .Values.tls.grpc.enabled }}
{{- if $fileTLS }}
{{- $tlsCount := 0 }} {{- $tlsCount := 0 }}
{{- if .Values.tls.externalSecret.enabled }} {{- if .Values.tls.externalSecret.enabled }}
{{- $tlsCount = add $tlsCount 1 }} {{- $tlsCount = add $tlsCount 1 }}
@@ -6,15 +8,40 @@
{{- $tlsCount = add $tlsCount 1 }} {{- $tlsCount = add $tlsCount 1 }}
{{- end }} {{- end }}
{{- if ne $tlsCount 1 }} {{- if ne $tlsCount 1 }}
{{- fail "You must have one and only one TLS configuration enabled" }} {{- fail "You must have one and only one TLS configuration enabled (tls.externalSecret or tls.certManager) when a tls listener is enabled" }}
{{- end }}
{{- if and .Values.tls.certManager.enabled (eq (len .Values.tls.certManager.certificate.dnsNames) 0) }}
{{- if and .Values.tls.rest.enabled (not (or .Values.tls.rest.ingress.enabled .Values.tls.rest.gatewayAPI.enabled)) }}
{{- fail "tls.certManager takes the certificate hostname from the exposure: enable tls.rest.ingress or tls.rest.gatewayAPI, or set tls.certManager.certificate.dnsNames" }}
{{- end }}
{{- if and .Values.tls.grpc.enabled (not (or .Values.tls.grpc.ingress.enabled .Values.tls.grpc.gatewayAPI.enabled)) }}
{{- fail "tls.certManager takes the certificate hostname from the exposure: enable tls.grpc.ingress or tls.grpc.gatewayAPI, or set tls.certManager.certificate.dnsNames" }}
{{- end }}
{{- end }}
{{- end }}
{{- if kindIs "slice" .Values.auth.plugins }}
{{- fail "auth.plugins is a mapping keyed by plugin name, not a list: replace each `- plugin: k8s_psat` entry with a `k8s_psat:` key holding its config" }}
{{- end }}
{{- if kindIs "slice" .Values.auth.stacks }}
{{- fail "auth.stacks is a mapping keyed by stack name, not a list: replace each `- name: foo` / `plugins: [...]` entry with a `foo:` key holding `plugins: [...]`" }}
{{- end }} {{- end }}
{{- if lt (len .Values.auth.plugins) 1 }} {{- if lt (len .Values.auth.plugins) 1 }}
{{- fail "You must have at least one auth plugin defined" }} {{- fail "You must have at least one auth plugin defined" }}
{{- end }} {{- end }}
{{- if not (or .Values.rest.enabled .Values.grpc.enabled) }} {{- if not (or $fileTLS .Values.spiffe.rest.enabled .Values.spiffe.grpc.enabled) }}
{{- fail "You must have rest and/or grpc enabled" }} {{- fail "You must enable at least one listener: tls.rest, tls.grpc, spiffe.rest or spiffe.grpc" }}
{{- end }} {{- end }}
{{- $trustDomain := include "spire-lib.trust-domain" . }} {{- $trustDomain := include "spire-lib.trust-domain" . }}
{{- $root := . }}
{{- $enabledPlugins := list }}
{{- range $name, $config := .Values.auth.plugins }}
{{- if ne (dig "enabled" true ($config | default dict)) false }}
{{- $enabledPlugins = append $enabledPlugins $name }}
{{- end }}
{{- end }}
{{- if lt (len $enabledPlugins) 1 }}
{{- fail "Every auth plugin is disabled: at least one entry in auth.plugins must have enabled: true" }}
{{- end }}
{{- include "spire-lib.check-strict-mode" (list . "trustDomain must be set" (eq $trustDomain "example.org"))}} {{- include "spire-lib.check-strict-mode" (list . "trustDomain must be set" (eq $trustDomain "example.org"))}}
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -28,23 +55,147 @@ metadata:
data: data:
six.conf: | six.conf: |
name: spire-identity-exchange name: spire-identity-exchange
logLevel: info logLevel: {{ .Values.config.logLevel }}
server: server:
port: 8443 metricsPort: {{ .Values.telemetry.prometheus.port }}
restPort: 8444
metricsPort: 4950
tls: tls:
{{- if $fileTLS }}
certFile: /secret/tls.crt certFile: /secret/tls.crt
keyFile: /secret/tls.key keyFile: /secret/tls.key
{{- end }}
grpc:
enable: {{ .Values.tls.grpc.enabled }}
port: {{ .Values.tls.grpc.port }}
rest:
enable: {{ .Values.tls.rest.enabled }}
port: {{ .Values.tls.rest.port }}
spiffe:
grpc:
enable: {{ .Values.spiffe.grpc.enabled }}
port: {{ .Values.spiffe.grpc.port }}
rest:
enable: {{ .Values.spiffe.rest.enabled }}
port: {{ .Values.spiffe.rest.port }}
spire: spire:
agentWorkloadSocketPath: /spiffe-workload-api/spire-agent.sock agentWorkloadSocketPath: {{ include "spire-identity-exchange.workload-api-socket-path" . }}
agentDelegatedSocketPath: /agent/admin.sock agentDelegatedSocketPath: /agent/admin.sock
trustDomain: {{ $trustDomain }} trustDomain: {{ $trustDomain }}
svidTTL: 1h svidTTL: 1h
auth: auth:
passthroughPlugins: {{ .Values.auth.passthroughPlugins }}
plugins: plugins:
{{- toYaml .Values.auth.plugins | nindent 8 }} {{- range $name, $config := .Values.auth.plugins }}
{{ with .Values.auth.stacks }} {{- if has $name $enabledPlugins }}
{{- $pluginType := include "spire-identity-exchange.plugin-type" (dict "root" $root "name" $name "config" $config) }}
{{- $cfg := $config.config | default dict }}
{{- if hasKey ($config | default dict) "csiDriverName" }}
{{- if ne $pluginType "spiffe" }}
{{- fail (printf "auth.plugins.%s: csiDriverName is only supported on plugins of type \"spiffe\". Plugin type %q does not talk to a SPIRE Agent workload socket, so there is nothing to mount the driver for." $name $pluginType) }}
{{- end }}
{{- if not (kindIs "string" $config.csiDriverName) }}
{{- fail (printf "auth.plugins.%s.csiDriverName: expected string, got %s" $name (kindOf $config.csiDriverName)) }}
{{- end }}
{{- end }}
{{ if eq $name "k8sPSAT" }}k8s_psat{{ else }}{{ $name | quote }}{{ end }}:
{{- with $config.plugin }}
plugin: {{ . | quote }}
{{- end }}
config:
{{- if eq $pluginType "k8s_psat" }}
{{- if hasKey $cfg "kubeconfig" }}
{{- fail (printf "auth.plugins.%s.config: kubeconfig is not supported by this chart. In a pod, spire-identity-exchange always authenticates to the Kubernetes API with the in-cluster credentials of its own ServiceAccount and ignores a kubeconfig file, so pointing it at another cluster would silently validate tokens against the local one instead." $name) }}
{{- end }}
{{- $_ := include "spire-identity-exchange.check-plugin-options" (dict "name" $name "type" $pluginType "config" $cfg "options" (dict
"clusterName" "string"
"audiences" "[]string"
"allowedNamespaces" "[]string"
"allowedServiceAccounts" "[]string"
"jwksCheck" "bool"
"tokenReview" "bool")) }}
{{- $jwksCheck := ne (dig "jwksCheck" true $cfg) false }}
{{- $tokenReview := ne (dig "tokenReview" true $cfg) false }}
{{- if not (or $jwksCheck $tokenReview) }}
{{- fail (printf "auth.plugins.%s.config: jwksCheck and tokenReview cannot both be false; at least one validation stage must remain active" $name) }}
{{- end }}
{{- if $jwksCheck }}
{{- $_ := include "spire-identity-exchange.check-plugin-required" (dict "name" $name "type" $pluginType "config" $cfg "required" (list "audiences")) }}
{{- end }}
{{- if and (empty $cfg.allowedNamespaces) (empty $cfg.allowedServiceAccounts) }}
{{- fail (printf "auth.plugins.%s.config: at least one of allowedNamespaces or allowedServiceAccounts must be set" $name) }}
{{- end }}
{{- toYaml $config.config | nindent 12 }}
{{- else if eq $pluginType "spiffe" }}
{{- if hasKey $cfg "agentWorkloadSocketPath" }}
{{- fail (printf "auth.plugins.%s.config: agentWorkloadSocketPath is set by this chart, not in values. The SPIRE Agent workload socket is mounted from the SPIFFE CSI driver and the path is filled in automatically when connectWithTrustBundle is true." $name) }}
{{- end }}
{{- $_ := include "spire-identity-exchange.check-plugin-options" (dict "name" $name "type" $pluginType "config" $cfg "options" (dict
"issuerURL" "string"
"discoveryURL" "string"
"trustDomain" "string"
"audiences" "[]string"
"pathPatterns" "[]string"
"connectWithTrustBundle" "bool")) }}
{{- $_ := include "spire-identity-exchange.check-plugin-required" (dict "name" $name "type" $pluginType "config" $cfg "required" (list "issuerURL" "audiences" "trustDomain" "pathPatterns")) }}
{{- $driver := dig "csiDriverName" "" ($config | default dict) }}
{{- if and (not (empty $driver)) (not $cfg.connectWithTrustBundle) }}
{{- fail (printf "auth.plugins.%s: csiDriverName is only meaningful when config.connectWithTrustBundle is true; the SPIRE Agent workload socket is not used otherwise." $name) }}
{{- end }}
{{- $keySource := dig "keySource" "oidc" ($config | default dict) }}
{{- if not (has $keySource (list "oidc" "oidcLocal")) }}
{{- fail (printf "auth.plugins.%s.keySource: %q is not valid; must be oidc or oidcLocal" $name $keySource) }}
{{- end }}
{{- $effective := $cfg }}
{{- if $cfg.connectWithTrustBundle }}
{{- $effective = merge (dict "agentWorkloadSocketPath" (include "spire-identity-exchange.plugin-workload-api-socket-path" (dict "root" $root "driver" $driver))) $cfg }}
{{- end }}
{{- if and (eq $keySource "oidcLocal") (empty $cfg.discoveryURL) }}
{{- $effective = merge (dict "discoveryURL" (printf "https://%s-spiffe-oidc-discovery-provider" $root.Release.Name)) $effective }}
{{- end }}
{{- toYaml $effective | nindent 12 }}
{{- else if eq $pluginType "github" }}
{{- $_ := include "spire-identity-exchange.check-plugin-options" (dict "name" $name "type" $pluginType "config" $cfg "options" (dict
"issuerURL" "string"
"audiences" "[]string"
"allowedRepositoryOwners" "[]string"
"allowedRepositories" "[]string")) }}
{{- $_ := include "spire-identity-exchange.check-plugin-required" (dict "name" $name "type" $pluginType "config" $cfg "required" (list "audiences")) }}
{{- if and (empty $cfg.allowedRepositoryOwners) (empty $cfg.allowedRepositories) }}
{{- fail (printf "auth.plugins.%s.config: at least one of allowedRepositoryOwners or allowedRepositories must be set" $name) }}
{{- end }}
{{- toYaml $config.config | nindent 12 }}
{{- else if eq $pluginType "gitlab" }}
{{- $_ := include "spire-identity-exchange.check-plugin-options" (dict "name" $name "type" $pluginType "config" $cfg "options" (dict
"issuerURL" "string"
"audiences" "[]string"
"allowedNamespacePaths" "[]string"
"allowedProjectPaths" "[]string")) }}
{{- $_ := include "spire-identity-exchange.check-plugin-required" (dict "name" $name "type" $pluginType "config" $cfg "required" (list "audiences")) }}
{{- if and (empty $cfg.allowedNamespacePaths) (empty $cfg.allowedProjectPaths) }}
{{- fail (printf "auth.plugins.%s.config: at least one of allowedNamespacePaths or allowedProjectPaths must be set" $name) }}
{{- end }}
{{- toYaml $config.config | nindent 12 }}
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.auth.unsupportedBuiltInPlugins }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- $stacks := dict }}
{{- range $stackName, $stack := .Values.auth.stacks }}
{{- if ne (dig "enabled" true ($stack | default dict)) false }}
{{- range $plugin := $stack.plugins }}
{{- if not (has $plugin $enabledPlugins) }}
{{- if hasKey $root.Values.auth.plugins $plugin }}
{{- fail (printf "auth.stacks.%s lists plugin %q, which is disabled. Set auth.plugins.%s.enabled: true or drop it from the stack; the exchange refuses to start when a stack names a plugin it did not load." $stackName $plugin $plugin) }}
{{- else }}
{{- fail (printf "auth.stacks.%s lists plugin %q, which is not defined in auth.plugins" $stackName $plugin) }}
{{- end }}
{{- end }}
{{- end }}
{{- $_ := set $stacks $stackName (omit $stack "enabled") }}
{{- end }}
{{- end }}
{{- with $stacks }}
stacks: stacks:
{{- toYaml . | nindent 8 }} {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}
@@ -80,7 +231,7 @@ data:
NodeAttestor "x509pop" { NodeAttestor "x509pop" {
plugin_data { plugin_data {
spiffe_endpoint_socket = "unix:///spiffe-workload-api/spire-agent.sock" spiffe_endpoint_socket = "unix://{{ include "spire-identity-exchange.workload-api-socket-path" . }}"
} }
} }
@@ -1,5 +1,7 @@
{{- $configSum := (include (print $.Template.BasePath "/configmap.yaml") . | sha256sum) }} {{- $configSum := (include (print $.Template.BasePath "/configmap.yaml") . | sha256sum) }}
{{- $trustDomain := include "spire-lib.trust-domain" . }} {{- $trustDomain := include "spire-lib.trust-domain" . }}
{{- $fileTLS := or .Values.tls.rest.enabled .Values.tls.grpc.enabled }}
{{- $extraCSIDrivers := include "spire-identity-exchange.extra-csi-drivers" . | fromJson }}
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
@@ -55,7 +57,7 @@ spec:
- /trustbundle/socket - /trustbundle/socket
env: env:
- name: SPIFFE_ENDPOINT_SOCKET - name: SPIFFE_ENDPOINT_SOCKET
value: "unix:///spiffe-workload-api/spire-agent.sock" value: "unix://{{ include "spire-identity-exchange.workload-api-socket-path" . }}"
- name: SPIFFE_TRUST_DOMAIN - name: SPIFFE_TRUST_DOMAIN
value: {{ $trustDomain }} value: {{ $trustDomain }}
readinessProbe: readinessProbe:
@@ -124,26 +126,49 @@ spec:
- -config - -config
- /etc/spire/identity-exchange/six.conf - /etc/spire/identity-exchange/six.conf
- -expand-env - -expand-env
{{- with .Values.extraEnv }}
env: env:
- name: SPIFFE_TRUST_DOMAIN
value: {{ $trustDomain | quote }}
- name: K8S_CLUSTER_NAME
value: {{ include "spire-lib.cluster-name" . | trim | quote }}
- name: SPIFFE_JWT_ISSUER
value: {{ include "spire-lib.jwt-issuer" . | trim | quote }}
{{- with .Values.extraEnv }}
{{- . | toYaml | nindent 12 }} {{- . | toYaml | nindent 12 }}
{{- end }} {{- end }}
ports: ports:
{{- if .Values.rest.enabled }} {{- if .Values.tls.rest.enabled }}
- containerPort: 8444 - containerPort: {{ .Values.tls.rest.port }}
name: rest name: rest
{{- end }} {{- end }}
{{- if .Values.grpc.enabled }} {{- if .Values.tls.grpc.enabled }}
- containerPort: 8443 - containerPort: {{ .Values.tls.grpc.port }}
name: grpc name: grpc
{{- end }} {{- end }}
{{- if .Values.spiffe.rest.enabled }}
- containerPort: {{ .Values.spiffe.rest.port }}
name: rest-spiffe
{{- end }}
{{- if .Values.spiffe.grpc.enabled }}
- containerPort: {{ .Values.spiffe.grpc.port }}
name: grpc-spiffe
{{- end }}
- containerPort: {{ .Values.telemetry.prometheus.port }}
name: prom
volumeMounts: volumeMounts:
- name: spiffe-workload-api - name: spiffe-workload-api
mountPath: {{ include "spire-identity-exchange.workload-api-socket-path" . | dir }} mountPath: {{ include "spire-identity-exchange.workload-api-socket-path" . | dir }}
readOnly: true readOnly: true
{{- range $driver, $volumeName := $extraCSIDrivers }}
- name: {{ $volumeName }}
mountPath: /spiffe-workload-apis/{{ $driver }}
readOnly: true
{{- end }}
{{- if $fileTLS }}
- name: certdir - name: certdir
mountPath: /secret mountPath: /secret
readOnly: true readOnly: true
{{- end }}
- name: spire-identity-exchange-config - name: spire-identity-exchange-config
mountPath: /etc/spire/identity-exchange/six.conf mountPath: /etc/spire/identity-exchange/six.conf
subPath: six.conf subPath: six.conf
@@ -168,6 +193,13 @@ spec:
csi: csi:
driver: "{{ .Values.csiDriverName }}" driver: "{{ .Values.csiDriverName }}"
readOnly: true readOnly: true
{{- range $driver, $volumeName := $extraCSIDrivers }}
- name: {{ $volumeName }}
csi:
driver: "{{ $driver }}"
readOnly: true
{{- end }}
{{- if $fileTLS }}
- name: certdir - name: certdir
{{- if .Values.tls.externalSecret.enabled }} {{- if .Values.tls.externalSecret.enabled }}
secret: secret:
@@ -176,6 +208,7 @@ spec:
secret: secret:
secretName: {{ include "spire-identity-exchange.fullname" . }}-cert secretName: {{ include "spire-identity-exchange.fullname" . }}-cert
{{- end }} {{- end }}
{{- end }}
- name: spire-agent-socket - name: spire-agent-socket
emptyDir: {} emptyDir: {}
- name: spire-agent-data - name: spire-agent-data
@@ -1,13 +0,0 @@
{{- if .Values.grpc.gatewayAPI.enabled -}}
{{- $routeKind := include "spire-lib.gateway-route-kind" (dict "gatewayAPI" .Values.grpc.gatewayAPI) -}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.grpc.gatewayAPI
"name" (printf "%s-grpc" (include "spire-identity-exchange.fullname" .))
"namespace" (include "spire-identity-exchange.namespace" .)
"svcName" (printf "%s-grpc" (include "spire-identity-exchange.fullname" .))
"port" .Values.grpc.service.port
"labels" (include "spire-identity-exchange.labels" .)
"routeKind" $routeKind
"backendTLS" (eq $routeKind "HTTPRoute")) }}
{{- end }}
@@ -10,7 +10,7 @@ solvers:
- http01: - http01:
ingress: {} ingress: {}
{{- end }} {{- end }}
{{- if and .Values.tls.certManager.enabled .Values.tls.certManager.issuer.create }} {{- if and .Values.tls.certManager.enabled .Values.tls.certManager.issuer.create (or .Values.tls.rest.enabled .Values.tls.grpc.enabled) }}
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Issuer kind: Issuer
metadata: metadata:
@@ -0,0 +1,28 @@
{{- if (dig "telemetry" "prometheus" "podMonitor" "enabled" .Values.telemetry.prometheus.podMonitor.enabled .Values.global) }}
{{- $namespace := include "spire-identity-exchange.podMonitor.namespace" . }}
{{- $podNamespace := include "spire-identity-exchange.namespace" . }}
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: {{ include "spire-identity-exchange.fullname" . }}
namespace: {{ $namespace | quote }}
labels:
{{- include "spire-identity-exchange.labels" . | nindent 4 }}
{{- if ne (len (dig "telemetry" "prometheus" "podMonitor" "labels" (dict) .Values.global)) 0 }}
{{- .Values.global.telemetry.prometheus.podMonitor.labels | toYaml | nindent 4 }}
{{- end }}
{{- with .Values.telemetry.prometheus.podMonitor.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
{{- include "spire-identity-exchange.selectorLabels" . | nindent 6 }}
podMetricsEndpoints:
- port: prom
{{- if ne $namespace $podNamespace }}
namespaceSelector:
matchNames:
- {{ $podNamespace | quote }}
{{- end }}
{{- end }}
@@ -1,13 +0,0 @@
{{- if .Values.rest.gatewayAPI.enabled -}}
{{- $routeKind := include "spire-lib.gateway-route-kind" (dict "gatewayAPI" .Values.rest.gatewayAPI) -}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.rest.gatewayAPI
"name" (printf "%s-rest" (include "spire-identity-exchange.fullname" .))
"namespace" (include "spire-identity-exchange.namespace" .)
"svcName" (printf "%s-rest" (include "spire-identity-exchange.fullname" .))
"port" .Values.rest.service.port
"labels" (include "spire-identity-exchange.labels" .)
"routeKind" $routeKind
"backendTLS" (eq $routeKind "HTTPRoute")) }}
{{- end }}
@@ -0,0 +1,15 @@
{{- if and .Values.spiffe.grpc.enabled .Values.spiffe.grpc.gatewayAPI.enabled -}}
{{- $fullName := printf "%s-grpc-spiffe" (include "spire-identity-exchange.fullname" .) -}}
{{/* Passthrough only. This backend serves an X509-SVID, whose only SAN is a
spiffe:// URI, so a BackendTLSPolicy hostname check could never match. */}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.spiffe.grpc.gatewayAPI
"name" $fullName
"namespace" (include "spire-identity-exchange.namespace" .)
"svcName" $fullName
"port" .Values.spiffe.grpc.service.port
"labels" (include "spire-identity-exchange.labels" .)
"routeKind" "TLSRoute"
"backendTLS" false) }}
{{- end }}
@@ -0,0 +1,39 @@
{{- if and .Values.spiffe.grpc.enabled .Values.spiffe.grpc.ingress.enabled -}}
{{- $port := .Values.spiffe.grpc.service.port }}
{{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.spiffe.grpc.ingress) }}
{{- $fullName := printf "%s-grpc-spiffe" (include "spire-identity-exchange.fullname" .) }}
{{- $path := "/" }}
{{- $pathType := "Prefix" }}
{{- $tlsSection := true }}
{{- $annotations := deepCopy .Values.spiffe.grpc.ingress.annotations }}
{{- if eq $ingressControllerType "ingress-nginx" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }}
{{- if not .Values.spiffe.grpc.ingress.tlsSecret }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }}
{{- end }}
{{- else if eq $ingressControllerType "openshift" }}
{{- if .Values.spiffe.grpc.ingress.tlsSecret }}
{{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }}
{{- else }}
{{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }}
{{- end }}
{{- $path = "" }}
{{- $pathType = "ImplementationSpecific" }}
{{- $tlsSection = false }}
{{- end }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ include "spire-identity-exchange.namespace" . }}
labels:
{{ include "spire-identity-exchange.labels" . | nindent 4 }}
{{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{ include "spire-lib.ingress-spec" (dict "ingress" .Values.spiffe.grpc.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }}
{{- end }}
@@ -0,0 +1,23 @@
{{- if .Values.spiffe.grpc.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "spire-identity-exchange.fullname" . }}-grpc-spiffe
namespace: {{ include "spire-identity-exchange.namespace" . }}
{{- with .Values.spiffe.grpc.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.spiffe.grpc.service.type }}
{{- if and (eq .Values.spiffe.grpc.service.type "LoadBalancer") .Values.spiffe.grpc.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.spiffe.grpc.service.loadBalancerIP }}
{{- end }}
ports:
- name: https
port: {{ .Values.spiffe.grpc.service.port }}
targetPort: grpc-spiffe
protocol: TCP
selector:
{{- include "spire-identity-exchange.selectorLabels" . | nindent 4 }}
{{- end }}
@@ -0,0 +1,15 @@
{{- if and .Values.spiffe.rest.enabled .Values.spiffe.rest.gatewayAPI.enabled -}}
{{- $fullName := printf "%s-rest-spiffe" (include "spire-identity-exchange.fullname" .) -}}
{{/* Passthrough only. This backend serves an X509-SVID, whose only SAN is a
spiffe:// URI, so a BackendTLSPolicy hostname check could never match. */}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.spiffe.rest.gatewayAPI
"name" $fullName
"namespace" (include "spire-identity-exchange.namespace" .)
"svcName" $fullName
"port" .Values.spiffe.rest.service.port
"labels" (include "spire-identity-exchange.labels" .)
"routeKind" "TLSRoute"
"backendTLS" false) }}
{{- end }}
@@ -0,0 +1,39 @@
{{- if and .Values.spiffe.rest.enabled .Values.spiffe.rest.ingress.enabled -}}
{{- $port := .Values.spiffe.rest.service.port }}
{{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.spiffe.rest.ingress) }}
{{- $fullName := printf "%s-rest-spiffe" (include "spire-identity-exchange.fullname" .) }}
{{- $path := "/" }}
{{- $pathType := "Prefix" }}
{{- $tlsSection := true }}
{{- $annotations := deepCopy .Values.spiffe.rest.ingress.annotations }}
{{- if eq $ingressControllerType "ingress-nginx" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }}
{{- if not .Values.spiffe.rest.ingress.tlsSecret }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }}
{{- end }}
{{- else if eq $ingressControllerType "openshift" }}
{{- if .Values.spiffe.rest.ingress.tlsSecret }}
{{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }}
{{- else }}
{{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }}
{{- end }}
{{- $path = "" }}
{{- $pathType = "ImplementationSpecific" }}
{{- $tlsSection = false }}
{{- end }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ include "spire-identity-exchange.namespace" . }}
labels:
{{ include "spire-identity-exchange.labels" . | nindent 4 }}
{{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{ include "spire-lib.ingress-spec" (dict "ingress" .Values.spiffe.rest.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }}
{{- end }}
@@ -0,0 +1,23 @@
{{- if .Values.spiffe.rest.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "spire-identity-exchange.fullname" . }}-rest-spiffe
namespace: {{ include "spire-identity-exchange.namespace" . }}
{{- with .Values.spiffe.rest.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.spiffe.rest.service.type }}
{{- if and (eq .Values.spiffe.rest.service.type "LoadBalancer") .Values.spiffe.rest.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.spiffe.rest.service.loadBalancerIP }}
{{- end }}
ports:
- name: https
port: {{ .Values.spiffe.rest.service.port }}
targetPort: rest-spiffe
protocol: TCP
selector:
{{- include "spire-identity-exchange.selectorLabels" . | nindent 4 }}
{{- end }}
@@ -0,0 +1,14 @@
{{- if and .Values.tls.grpc.enabled .Values.tls.grpc.gatewayAPI.enabled -}}
{{- $fullName := printf "%s-grpc" (include "spire-identity-exchange.fullname" .) -}}
{{- $routeKind := include "spire-lib.gateway-route-kind" (dict "gatewayAPI" .Values.tls.grpc.gatewayAPI) -}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.tls.grpc.gatewayAPI
"name" $fullName
"namespace" (include "spire-identity-exchange.namespace" .)
"svcName" $fullName
"port" .Values.tls.grpc.service.port
"labels" (include "spire-identity-exchange.labels" .)
"routeKind" $routeKind
"backendTLS" (eq $routeKind "HTTPRoute")) }}
{{- end }}
@@ -1,20 +1,20 @@
{{- if .Values.grpc.ingress.enabled -}} {{- if and .Values.tls.grpc.enabled .Values.tls.grpc.ingress.enabled -}}
{{- $port := .Values.grpc.service.port }} {{- $port := .Values.tls.grpc.service.port }}
{{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.grpc.ingress) }} {{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.tls.grpc.ingress) }}
{{- $fullName := printf "%s-grpc" (include "spire-identity-exchange.fullname" .) }} {{- $fullName := printf "%s-grpc" (include "spire-identity-exchange.fullname" .) }}
{{- $path := "/" }} {{- $path := "/" }}
{{- $pathType := "Prefix" }} {{- $pathType := "Prefix" }}
{{- $tlsSection := true }} {{- $tlsSection := true }}
{{- $annotations := deepCopy .Values.grpc.ingress.annotations }} {{- $annotations := deepCopy .Values.tls.grpc.ingress.annotations }}
{{- if eq $ingressControllerType "ingress-nginx" }} {{- if eq $ingressControllerType "ingress-nginx" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }}
{{- if not (and .Values.grpc.ingress.enabled .Values.grpc.ingress.tlsSecret) }} {{- if not .Values.tls.grpc.ingress.tlsSecret }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }}
{{- end }} {{- end }}
{{- else if eq $ingressControllerType "openshift" }} {{- else if eq $ingressControllerType "openshift" }}
{{- if and .Values.grpc.ingress.enabled .Values.grpc.ingress.tlsSecret }} {{- if .Values.tls.grpc.ingress.tlsSecret }}
{{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }} {{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }}
{{- else }} {{- else }}
{{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }} {{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }}
@@ -35,5 +35,5 @@ metadata:
{{- toYaml . | nindent 4 }} {{- toYaml . | nindent 4 }}
{{- end }} {{- end }}
spec: spec:
{{ include "spire-lib.ingress-spec" (dict "ingress" .Values.grpc.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }} {{ include "spire-lib.ingress-spec" (dict "ingress" .Values.tls.grpc.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }}
{{- end }} {{- end }}
@@ -1,21 +1,21 @@
{{- if .Values.grpc.enabled }} {{- if .Values.tls.grpc.enabled }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ include "spire-identity-exchange.fullname" . }}-grpc name: {{ include "spire-identity-exchange.fullname" . }}-grpc
namespace: {{ include "spire-identity-exchange.namespace" . }} namespace: {{ include "spire-identity-exchange.namespace" . }}
{{- with .Values.service.annotations }} {{- with .Values.tls.grpc.service.annotations }}
annotations: annotations:
{{- toYaml . | nindent 4 }} {{- toYaml . | nindent 4 }}
{{- end }} {{- end }}
spec: spec:
type: {{ .Values.grpc.service.type }} type: {{ .Values.tls.grpc.service.type }}
{{- if and (eq .Values.grpc.service.type "LoadBalancer") .Values.grpc.service.loadBalancerIP }} {{- if and (eq .Values.tls.grpc.service.type "LoadBalancer") .Values.tls.grpc.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.grpc.service.loadBalancerIP }} loadBalancerIP: {{ .Values.tls.grpc.service.loadBalancerIP }}
{{- end }} {{- end }}
ports: ports:
- name: https - name: https
port: {{ .Values.grpc.service.port }} port: {{ .Values.tls.grpc.service.port }}
targetPort: grpc targetPort: grpc
protocol: TCP protocol: TCP
selector: selector:
@@ -0,0 +1,14 @@
{{- if and .Values.tls.rest.enabled .Values.tls.rest.gatewayAPI.enabled -}}
{{- $fullName := printf "%s-rest" (include "spire-identity-exchange.fullname" .) -}}
{{- $routeKind := include "spire-lib.gateway-route-kind" (dict "gatewayAPI" .Values.tls.rest.gatewayAPI) -}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.tls.rest.gatewayAPI
"name" $fullName
"namespace" (include "spire-identity-exchange.namespace" .)
"svcName" $fullName
"port" .Values.tls.rest.service.port
"labels" (include "spire-identity-exchange.labels" .)
"routeKind" $routeKind
"backendTLS" (eq $routeKind "HTTPRoute")) }}
{{- end }}
@@ -1,20 +1,20 @@
{{- if .Values.rest.ingress.enabled -}} {{- if and .Values.tls.rest.enabled .Values.tls.rest.ingress.enabled -}}
{{- $port := .Values.rest.service.port }} {{- $port := .Values.tls.rest.service.port }}
{{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.rest.ingress) }} {{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.tls.rest.ingress) }}
{{- $fullName := printf "%s-rest" (include "spire-identity-exchange.fullname" .) }} {{- $fullName := printf "%s-rest" (include "spire-identity-exchange.fullname" .) }}
{{- $path := "/" }} {{- $path := "/" }}
{{- $pathType := "Prefix" }} {{- $pathType := "Prefix" }}
{{- $tlsSection := true }} {{- $tlsSection := true }}
{{- $annotations := deepCopy .Values.rest.ingress.annotations }} {{- $annotations := deepCopy .Values.tls.rest.ingress.annotations }}
{{- if eq $ingressControllerType "ingress-nginx" }} {{- if eq $ingressControllerType "ingress-nginx" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }}
{{- if not (and .Values.rest.ingress.enabled .Values.rest.ingress.tlsSecret) }} {{- if not .Values.tls.rest.ingress.tlsSecret }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }}
{{- end }} {{- end }}
{{- else if eq $ingressControllerType "openshift" }} {{- else if eq $ingressControllerType "openshift" }}
{{- if and .Values.rest.ingress.enabled .Values.rest.ingress.tlsSecret }} {{- if .Values.tls.rest.ingress.tlsSecret }}
{{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }} {{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }}
{{- else }} {{- else }}
{{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }} {{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }}
@@ -35,5 +35,5 @@ metadata:
{{- toYaml . | nindent 4 }} {{- toYaml . | nindent 4 }}
{{- end }} {{- end }}
spec: spec:
{{ include "spire-lib.ingress-spec" (dict "ingress" .Values.rest.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }} {{ include "spire-lib.ingress-spec" (dict "ingress" .Values.tls.rest.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }}
{{- end }} {{- end }}
@@ -1,21 +1,21 @@
{{- if .Values.rest.enabled }} {{- if .Values.tls.rest.enabled }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ include "spire-identity-exchange.fullname" . }}-rest name: {{ include "spire-identity-exchange.fullname" . }}-rest
namespace: {{ include "spire-identity-exchange.namespace" . }} namespace: {{ include "spire-identity-exchange.namespace" . }}
{{- with .Values.rest.service.annotations }} {{- with .Values.tls.rest.service.annotations }}
annotations: annotations:
{{- toYaml . | nindent 4 }} {{- toYaml . | nindent 4 }}
{{- end }} {{- end }}
spec: spec:
type: {{ .Values.rest.service.type }} type: {{ .Values.tls.rest.service.type }}
{{- if and (eq .Values.rest.service.type "LoadBalancer") .Values.rest.service.loadBalancerIP }} {{- if and (eq .Values.tls.rest.service.type "LoadBalancer") .Values.tls.rest.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.rest.service.loadBalancerIP }} loadBalancerIP: {{ .Values.tls.rest.service.loadBalancerIP }}
{{- end }} {{- end }}
ports: ports:
- name: https - name: https
port: {{ .Values.rest.service.port }} port: {{ .Values.tls.rest.service.port }}
targetPort: rest targetPort: rest
protocol: TCP protocol: TCP
selector: selector:
+286 -93
View File
@@ -138,49 +138,25 @@ podAnnotations: {}
## @param podLabels [object] Labels to add to pods ## @param podLabels [object] Labels to add to pods
podLabels: {} podLabels: {}
# Select one of the options below to be the source of certificates for SPIRE Identity Exchange
tls:
externalSecret:
## @param tls.externalSecret.enabled Provide your own certificate/key via tls style Kubernetes Secret
enabled: false
## @param tls.externalSecret.secretName Specify which Secret to use
secretName: ""
certManager:
## @param tls.certManager.enabled Use certificateManager to create the certificate
enabled: false
issuer:
## @param tls.certManager.issuer.create Create an issuer to use to issue the certificate
create: true
acme:
## @param tls.certManager.issuer.acme.email Must be set in order to register with LetsEncrypt. By setting, you agree to their Terms of Service
email: ""
## @param tls.certManager.issuer.acme.server Server to use to get certificate. Defaults to LetsEncrypt
server: https://acme-v02.api.letsencrypt.org/directory
# Testing server: https://acme-staging-v02.api.letsencrypt.org/directory
## @param tls.certManager.issuer.acme.solvers [object] Configure the issuer solvers. Defaults to http01 via ingress.
solvers: {}
# - http01:
# ingress:
# ingressClassName: nginx
certificate:
## @param tls.certManager.certificate.dnsNames Override the dnsNames on the certificate request. Defaults to the same settings as Ingress
dnsNames: []
## @param tls.certManager.certificate.issuerRef.group If you are using an external plugin, specify the group for it here
## @param tls.certManager.certificate.issuerRef.kind Kind of the issuer reference. Override if you want to use a ClusterIssuer
## @param tls.certManager.certificate.issuerRef.name Name of the issuer to use. If unset, it will use the name of the built in issuer
issuerRef:
group: ""
kind: Issuer
name: ""
config: config:
## @param config.logLevel The log level, valid values are "debug", "info", "warn", and "error" ## @param config.logLevel The log level, valid values are "debug", "info", "warn", and "error"
logLevel: info logLevel: info
## @param config.logFormat The log format, valid values are "text" and "json" ## @param config.logFormat The log format, valid values are "text" and "json"
logFormat: text logFormat: text
# The metrics endpoint is always served; spire-identity-exchange requires a nonzero port for it.
telemetry:
prometheus:
## @param telemetry.prometheus.port Port for prometheus metrics
port: 4950
podMonitor:
## @param telemetry.prometheus.podMonitor.enabled Enable podMonitor for prometheus
enabled: false
## @param telemetry.prometheus.podMonitor.namespace Override where to install the podMonitor, if not set will use the same namespace as the helm release
namespace: ""
## @param telemetry.prometheus.podMonitor.labels [object] Pod labels to filter for prometheus monitoring
labels: {}
## @param imagePullSecrets [array] Image pull secret names ## @param imagePullSecrets [array] Image pull secret names
imagePullSecrets: [] imagePullSecrets: []
@@ -219,7 +195,7 @@ autoscaling:
## @param nodeSelector [object] Node selector ## @param nodeSelector [object] Node selector
nodeSelector: {} nodeSelector: {}
## @param tolerations [array] iist of tolerations ## @param tolerations [array] list of tolerations
tolerations: [] tolerations: []
## @param affinity [object] Node affinity ## @param affinity [object] Node affinity
@@ -228,159 +204,376 @@ affinity: {}
## @param trustDomain Set the trust domain to be used for the SPIFFE identifiers ## @param trustDomain Set the trust domain to be used for the SPIFFE identifiers
trustDomain: example.org trustDomain: example.org
## @param clusterName The name of this Kubernetes cluster, as it appears in SPIFFE ID paths
clusterName: example-cluster
## @param jwtIssuer The issuer URL for JWT-SVIDs. Defaults to https://oidc-discovery.$trustDomain
jwtIssuer: ""
## @param clusterDomain The name of the Kubernetes cluster (`kubeadm init --service-dns-domain`) ## @param clusterDomain The name of the Kubernetes cluster (`kubeadm init --service-dns-domain`)
clusterDomain: cluster.local clusterDomain: cluster.local
auth: auth:
## @param auth.plugins [object] Plugins to load plugins:
plugins: [] k8s_psat:
## @param auth.stacks [object] Stacks to load ## @param auth.plugins.k8s_psat.enabled Enable the k8s psat plugin
stacks: []
rest:
## @param rest.enabled Enable the rest service
enabled: true enabled: true
## @param rest.service.type Service type config:
## @param rest.service.port port for the service ## @param auth.plugins.k8s_psat.config.audiences [array] The audiences to allow
## @param rest.service.annotations Annotations for service resource audiences:
- spire-identity-exchange
## @param auth.plugins.k8s_psat.config.allowedServiceAccounts [array] The service accounts that are allowed
allowedServiceAccounts:
- "*"
spiffe:
## @param auth.plugins.spiffe.enabled Enable the spiffe plugin
enabled: true
## @param auth.plugins.spiffe.keySource What source to use to fetch the keys. Can be oidc or oidcLocal. oidcLocal forces discoveryURL to be the internal discovery address.
keySource: oidcLocal
## @extra auth.plugins.spiffe.csiDriverName The CSI driver providing the SPIRE Agent workload socket this plugin attests against. Defaults to the chart level csiDriverName. Requires config.connectWithTrustBundle.
config:
## @param auth.plugins.spiffe.config.issuerURL The url to connect to for JWKS discovery
issuerURL: "${SPIFFE_JWT_ISSUER}"
## @param auth.plugins.spiffe.config.trustDomain The trust domain to use
trustDomain: "${SPIFFE_TRUST_DOMAIN}"
## @param auth.plugins.spiffe.config.pathPatterns [array] The service accounts that are allowed
pathPatterns:
- "^/k8s/${K8S_CLUSTER_NAME}/node/[^/]+"
## @param auth.plugins.spiffe.config.audiences [array] The audiences to allow
audiences:
- spire-identity-exchange
## @param auth.plugins.spiffe.config.connectWithTrustBundle Use the trust bundle to validate the issuerURL
connectWithTrustBundle: true
stacks:
image_pull:
## @param auth.stacks.image_pull.enabled Enable the image_pull stack
enabled: true
## @param auth.stacks.image_pull.plugins [array] List of plugins that are required by this stack
plugins:
- spiffe
- k8s_psat
## @param auth.unsupportedBuiltInPlugins [object] Unsupported mechanism to use plugins not yet supported by the chart.
unsupportedBuiltInPlugins: {}
## @param auth.passthroughPlugins Address each plugin as a stack of its own, in addition to any stacks defined
passthroughPlugins: false
# Listeners served with a certificate from disk. Select one of the options below to be the source of that certificate.
tls:
externalSecret:
## @param tls.externalSecret.enabled Provide your own certificate/key via tls style Kubernetes Secret
enabled: false
## @param tls.externalSecret.secretName Specify which Secret to use
secretName: ""
certManager:
## @param tls.certManager.enabled Use certificateManager to create the certificate
enabled: false
issuer:
## @param tls.certManager.issuer.create Create an issuer to use to issue the certificate
create: true
acme:
## @param tls.certManager.issuer.acme.email Must be set in order to register with LetsEncrypt. By setting, you agree to their Terms of Service
email: ""
## @param tls.certManager.issuer.acme.server Server to use to get certificate. Defaults to LetsEncrypt
server: https://acme-v02.api.letsencrypt.org/directory
# Testing server: https://acme-staging-v02.api.letsencrypt.org/directory
## @param tls.certManager.issuer.acme.solvers [object] Configure the issuer solvers. Defaults to http01 via ingress.
solvers: {}
# - http01:
# ingress:
# ingressClassName: nginx
certificate:
## @param tls.certManager.certificate.dnsNames Override the dnsNames on the certificate request. Defaults to the same settings as Ingress
dnsNames: []
## @param tls.certManager.certificate.issuerRef.group If you are using an external plugin, specify the group for it here
## @param tls.certManager.certificate.issuerRef.kind Kind of the issuer reference. Override if you want to use a ClusterIssuer
## @param tls.certManager.certificate.issuerRef.name Name of the issuer to use. If unset, it will use the name of the built in issuer
issuerRef:
group: ""
kind: Issuer
name: ""
rest:
## @param tls.rest.enabled Enable the REST listener served with the certificate from disk
enabled: false
## @param tls.rest.port Container port for the REST listener served with the certificate from disk
port: 8444
## @param tls.rest.service.type Service type
## @param tls.rest.service.port port for the service
## @param tls.rest.service.annotations Annotations for service resource
## ##
service: service:
type: ClusterIP type: ClusterIP
port: 443 port: 443
annotations: {} annotations: {}
# external-dns.alpha.kubernetes.io/hostname: spire-identity-exchange-rest.example.org # external-dns.alpha.kubernetes.io/hostname: spire-identity-exchange-rest.example.org
## @param rest.service.loadBalancerIP IP address to assign to load balancer (if supported) ## @param tls.rest.service.loadBalancerIP IP address to assign to load balancer (if supported)
loadBalancerIP: "" loadBalancerIP: ""
ingress: ingress:
## @param rest.ingress.enabled Flag to enable ingress ## @param tls.rest.ingress.enabled Flag to enable ingress
enabled: false enabled: false
## @param rest.ingress.className Ingress class name ## @param tls.rest.ingress.className Ingress class name
className: "" className: ""
## @param rest.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. ## @param tls.rest.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
controllerType: "" controllerType: ""
## @param rest.ingress.annotations [object] Annotations for ingress object ## @param tls.rest.ingress.annotations [object] Annotations for ingress object
annotations: {} annotations: {}
# kubernetes.io/ingress.class: nginx # kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true" # kubernetes.io/tls-acme: "true"
# nginx.ingress.kubernetes.io/ssl-redirect: "true" # nginx.ingress.kubernetes.io/ssl-redirect: "true"
# nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
## @param rest.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The rest of the rules will be autogenerated. For more customizability, use hosts[] instead. ## @param tls.rest.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The rest of the rules will be autogenerated. For more customizability, use hosts[] instead.
host: "spire-identity-exchange-rest" host: "spire-identity-exchange-rest"
## @param rest.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var. ## @param tls.rest.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var.
tlsSecret: "" tlsSecret: ""
## @param rest.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var. ## @param tls.rest.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var.
hosts: [] hosts: []
# - host: spire-identity-exchange-rest.example.org # - host: spire-identity-exchange-rest.example.org
# paths: # paths:
# - path: / # - path: /
# pathType: Prefix # pathType: Prefix
## @param rest.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. ## @param tls.rest.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars.
tls: [] tls: []
# - secretName: chart-example-tls # - secretName: chart-example-tls
# hosts: # hosts:
# - spire-identity-exchange-rest.example.org # - spire-identity-exchange-rest.example.org
## Gateway API exposure for the REST endpoint. Independent of rest.ingress. The ## Gateway API exposure for this endpoint. A set tlsSecret gives HTTPRoute (reencrypt); blank gives TLSRoute (SNI passthrough).
## backend serves HTTPS, so a set tlsSecret => HTTPRoute + BackendTLSPolicy
## (reencrypt); blank tlsSecret => TLSRoute (SNI passthrough).
gatewayAPI: gatewayAPI:
## @param rest.gatewayAPI.enabled Flag to expose the REST endpoint via Gateway API ## @param tls.rest.gatewayAPI.enabled Flag to expose the endpoint via Gateway API
enabled: false enabled: false
## @param rest.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended. ## @param tls.rest.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended.
host: "spire-identity-exchange-rest" host: "spire-identity-exchange-rest"
## @param rest.gatewayAPI.tlsSecret Secret with the TLS cert for edge termination. Blank keeps passthrough. ## @param tls.rest.gatewayAPI.tlsSecret Secret with the TLS cert for edge termination. Blank keeps passthrough.
tlsSecret: "" tlsSecret: ""
## @param rest.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet) ## @param tls.rest.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet)
annotations: {} annotations: {}
listenerSet: listenerSet:
## @param rest.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. ## @param tls.rest.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets.
enabled: null enabled: null
## @param rest.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach) ## @param tls.rest.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach)
parentRefs: [] parentRefs: []
## @param rest.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway ## @param tls.rest.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway
sectionName: "" sectionName: ""
# BackendTLSPolicy (reencrypt) is emitted automatically for the terminated # BackendTLSPolicy (reencrypt) is emitted automatically for the terminated
# HTTPS backend when gatewayAPI.tlsSecret is set. # HTTPS backend when gatewayAPI.tlsSecret is set.
backendTLS: backendTLS:
## @param rest.gatewayAPI.backendTLS.caCertificateRefs [array] ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap. ## @param tls.rest.gatewayAPI.backendTLS.caCertificateRefs [array] ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap.
caCertificateRefs: [] caCertificateRefs: []
grpc: grpc:
## @param grpc.enabled Enable the grpc service ## @param tls.grpc.enabled Enable the gRPC listener served with the certificate from disk
enabled: false enabled: false
## @param grpc.service.type Service type ## @param tls.grpc.port Container port for the gRPC listener served with the certificate from disk
## @param grpc.service.port port for the service port: 8443
## @param grpc.service.annotations Annotations for service resource ## @param tls.grpc.service.type Service type
## @param tls.grpc.service.port port for the service
## @param tls.grpc.service.annotations Annotations for service resource
## ##
service: service:
type: ClusterIP type: ClusterIP
port: 443 port: 443
annotations: {} annotations: {}
# external-dns.alpha.kubernetes.io/hostname: spire-identity-exchange-grpc.example.org # external-dns.alpha.kubernetes.io/hostname: spire-identity-exchange-grpc.example.org
## @param grpc.service.loadBalancerIP IP address to assign to load balancer (if supported) ## @param tls.grpc.service.loadBalancerIP IP address to assign to load balancer (if supported)
loadBalancerIP: "" loadBalancerIP: ""
ingress: ingress:
## @param grpc.ingress.enabled Flag to enable ingress ## @param tls.grpc.ingress.enabled Flag to enable ingress
enabled: false enabled: false
## @param grpc.ingress.className Ingress class name ## @param tls.grpc.ingress.className Ingress class name
className: "" className: ""
## @param grpc.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. ## @param tls.grpc.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
controllerType: "" controllerType: ""
## @param grpc.ingress.annotations [object] Annotations for ingress object ## @param tls.grpc.ingress.annotations [object] Annotations for ingress object
annotations: {} annotations: {}
# kubernetes.io/ingress.class: nginx # kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true" # kubernetes.io/tls-acme: "true"
# nginx.ingress.kubernetes.io/ssl-redirect: "true" # nginx.ingress.kubernetes.io/ssl-redirect: "true"
# nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
## @param grpc.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The grpc of the rules will be autogenerated. For more customizability, use hosts[] instead. ## @param tls.grpc.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The grpc of the rules will be autogenerated. For more customizability, use hosts[] instead.
host: "spire-identity-exchange-grpc" host: "spire-identity-exchange-grpc"
## @param grpc.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var. ## @param tls.grpc.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var.
tlsSecret: "" tlsSecret: ""
## @param grpc.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var. ## @param tls.grpc.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var.
hosts: [] hosts: []
# - host: spire-identity-exchange-grpc.example.org # - host: spire-identity-exchange-grpc.example.org
# paths: # paths:
# - path: / # - path: /
# pathType: Prefix # pathType: Prefix
## @param grpc.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. ## @param tls.grpc.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars.
tls: [] tls: []
# - secretName: chart-example-tls # - secretName: chart-example-tls
# hosts: # hosts:
# - spire-identiy-exchange-grpc.example.org # - spire-identiy-exchange-grpc.example.org
## Gateway API exposure for the gRPC endpoint. Independent of grpc.ingress. The ## Gateway API exposure for this endpoint. A set tlsSecret gives HTTPRoute (reencrypt); blank gives TLSRoute (SNI passthrough).
## backend serves HTTPS, so a set tlsSecret => HTTPRoute + BackendTLSPolicy
## (reencrypt); blank tlsSecret => TLSRoute (SNI passthrough).
gatewayAPI: gatewayAPI:
## @param grpc.gatewayAPI.enabled Flag to expose the gRPC endpoint via Gateway API ## @param tls.grpc.gatewayAPI.enabled Flag to expose the endpoint via Gateway API
enabled: false enabled: false
## @param grpc.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended. ## @param tls.grpc.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended.
host: "spire-identity-exchange-grpc" host: "spire-identity-exchange-grpc"
## @param grpc.gatewayAPI.tlsSecret Secret with the TLS cert for edge termination. Blank keeps passthrough. ## @param tls.grpc.gatewayAPI.tlsSecret Secret with the TLS cert for edge termination. Blank keeps passthrough.
tlsSecret: "" tlsSecret: ""
## @param grpc.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet) ## @param tls.grpc.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet)
annotations: {} annotations: {}
listenerSet: listenerSet:
## @param grpc.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. ## @param tls.grpc.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets.
enabled: null enabled: null
## @param grpc.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach) ## @param tls.grpc.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach)
parentRefs: [] parentRefs: []
## @param grpc.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway ## @param tls.grpc.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway
sectionName: "" sectionName: ""
# BackendTLSPolicy (reencrypt) is emitted automatically for the terminated # BackendTLSPolicy (reencrypt) is emitted automatically for the terminated
# HTTPS backend when gatewayAPI.tlsSecret is set. # HTTPS backend when gatewayAPI.tlsSecret is set.
backendTLS: backendTLS:
## @param grpc.gatewayAPI.backendTLS.caCertificateRefs [array] ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap. ## @param tls.grpc.gatewayAPI.backendTLS.caCertificateRefs [array] ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap.
caCertificateRefs: [] caCertificateRefs: []
# Listeners served with this deployment's own X509-SVID from the Workload API. No certificate files needed.
spiffe:
rest:
## @param spiffe.rest.enabled Enable the REST listener served with this deployment's own X509-SVID
enabled: true
## @param spiffe.rest.port Container port for the REST listener served with this deployment's own X509-SVID
port: 8544
## @param spiffe.rest.service.type Service type
## @param spiffe.rest.service.port port for the service
## @param spiffe.rest.service.annotations Annotations for service resource
##
service:
type: ClusterIP
port: 443
annotations: {}
# external-dns.alpha.kubernetes.io/hostname: spire-identity-exchange-rest-spiffe.example.org
## @param spiffe.rest.service.loadBalancerIP IP address to assign to load balancer (if supported)
loadBalancerIP: ""
ingress:
## @param spiffe.rest.ingress.enabled Flag to enable ingress
enabled: false
## @param spiffe.rest.ingress.className Ingress class name
className: ""
## @param spiffe.rest.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
controllerType: ""
## @param spiffe.rest.ingress.annotations [object] Annotations for ingress object
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
# nginx.ingress.kubernetes.io/ssl-redirect: "true"
# nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
## @param spiffe.rest.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The rest of the rules will be autogenerated. For more customizability, use hosts[] instead.
host: "spire-identity-exchange-rest-spiffe"
## @param spiffe.rest.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var.
tlsSecret: ""
## @param spiffe.rest.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var.
hosts: []
# - host: spire-identity-exchange-rest-spiffe.example.org
# paths:
# - path: /
# pathType: Prefix
## @param spiffe.rest.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars.
tls: []
# - secretName: chart-example-tls
# hosts:
# - spire-identity-exchange-rest-spiffe.example.org
## Gateway API exposure for this endpoint. Always a TLSRoute (SNI passthrough): an X509-SVID has no DNS SAN, so edge termination cannot validate this backend.
gatewayAPI:
## @param spiffe.rest.gatewayAPI.enabled Flag to expose the endpoint via Gateway API
enabled: false
## @param spiffe.rest.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended.
host: "spire-identity-exchange-rest-spiffe"
## @param spiffe.rest.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet)
annotations: {}
listenerSet:
## @param spiffe.rest.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets.
enabled: null
## @param spiffe.rest.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach)
parentRefs: []
## @param spiffe.rest.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway
sectionName: ""
grpc:
## @param spiffe.grpc.enabled Enable the gRPC listener served with this deployment's own X509-SVID
enabled: false
## @param spiffe.grpc.port Container port for the gRPC listener served with this deployment's own X509-SVID
port: 8543
## @param spiffe.grpc.service.type Service type
## @param spiffe.grpc.service.port port for the service
## @param spiffe.grpc.service.annotations Annotations for service resource
##
service:
type: ClusterIP
port: 443
annotations: {}
# external-dns.alpha.kubernetes.io/hostname: spire-identity-exchange-grpc-spiffe.example.org
## @param spiffe.grpc.service.loadBalancerIP IP address to assign to load balancer (if supported)
loadBalancerIP: ""
ingress:
## @param spiffe.grpc.ingress.enabled Flag to enable ingress
enabled: false
## @param spiffe.grpc.ingress.className Ingress class name
className: ""
## @param spiffe.grpc.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
controllerType: ""
## @param spiffe.grpc.ingress.annotations [object] Annotations for ingress object
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
# nginx.ingress.kubernetes.io/ssl-redirect: "true"
# nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
## @param spiffe.grpc.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. The grpc of the rules will be autogenerated. For more customizability, use hosts[] instead.
host: "spire-identity-exchange-grpc-spiffe"
## @param spiffe.grpc.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var.
tlsSecret: ""
## @param spiffe.grpc.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var.
hosts: []
# - host: spire-identity-exchange-grpc-spiffe.example.org
# paths:
# - path: /
# pathType: Prefix
## @param spiffe.grpc.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars.
tls: []
# - secretName: chart-example-tls
# hosts:
# - spire-identiy-exchange-grpc-spiffe.example.org
## Gateway API exposure for this endpoint. Always a TLSRoute (SNI passthrough): an X509-SVID has no DNS SAN, so edge termination cannot validate this backend.
gatewayAPI:
## @param spiffe.grpc.gatewayAPI.enabled Flag to expose the endpoint via Gateway API
enabled: false
## @param spiffe.grpc.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended.
host: "spire-identity-exchange-grpc-spiffe"
## @param spiffe.grpc.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet)
annotations: {}
listenerSet:
## @param spiffe.grpc.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets.
enabled: null
## @param spiffe.grpc.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach)
parentRefs: []
## @param spiffe.grpc.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway
sectionName: ""
tools: tools:
kubectl: kubectl:
## @param tools.kubectl.image.registry The OCI registry to pull the image from ## @param tools.kubectl.image.registry The OCI registry to pull the image from
+108 -9
View File
@@ -200,7 +200,7 @@ Now you can interact with the Spire agent socket from your own application. The
### Global parameters ### Global parameters
| Name | Description | Value | | Name | Description | Value |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `global.k8s.clusterDomain` | Cluster domain name configured for Spire install | `cluster.local` | | `global.k8s.clusterDomain` | Cluster domain name configured for Spire install | `cluster.local` |
| `global.spire.clusterName` | The name of the k8s cluster for Spire install | `example-cluster` | | `global.spire.clusterName` | The name of the k8s cluster for Spire install | `example-cluster` |
| `global.spire.jwtIssuer` | The issuer for Spire JWT tokens. Defaults to oidc-discovery.$trustDomain if unset | `""` | | `global.spire.jwtIssuer` | The issuer for Spire JWT tokens. Defaults to oidc-discovery.$trustDomain if unset | `""` |
@@ -227,6 +227,10 @@ Now you can interact with the Spire agent socket from your own application. The
| `global.spire.namespaces.server.labels` | Labels to apply to the Spire server Namespace. | `{}` | | `global.spire.namespaces.server.labels` | Labels to apply to the Spire server Namespace. | `{}` |
| `global.spire.strictMode` | Check values, such as trustDomain, are overridden with a suitable value for production. | `false` | | `global.spire.strictMode` | Check values, such as trustDomain, are overridden with a suitable value for production. | `false` |
| `global.spire.ingressControllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` | | `global.spire.ingressControllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `global.spire.gatewayAPI.manageListenerSets` | Default policy for whether services render a ListenerSet for their SNI listener. Each service may override via its gatewayAPI.listenerSet.enabled. | `true` |
| `global.spire.gatewayAPI.gateway.name` | Name of the shared Gateway object that routes and ListenerSets attach to | `spire` |
| `global.spire.gatewayAPI.gateway.namespace` | Namespace of the shared Gateway object. Defaults to the release namespace if blank. | `spire-server` |
| `global.spire.gatewayAPI.gateway.port` | Port the shared Gateway listens on. ListenerSet listeners must match this. | `443` |
| `global.spire.tools.kubectl.tag` | Set to force the tag to use for all kubectl instances | `""` | | `global.spire.tools.kubectl.tag` | Set to force the tag to use for all kubectl instances | `""` |
| `global.installAndUpgradeHooks.enabled` | Enable Helm hooks to autofix common install/upgrade issues (should be disabled when using `helm template`) | `true` | | `global.installAndUpgradeHooks.enabled` | Enable Helm hooks to autofix common install/upgrade issues (should be disabled when using `helm template`) | `true` |
| `global.deleteHooks.enabled` | Enable Helm hooks to autofix common delete issues (should be disabled when using `helm template`) | `true` | | `global.deleteHooks.enabled` | Enable Helm hooks to autofix common delete issues (should be disabled when using `helm template`) | `true` |
@@ -236,6 +240,93 @@ Now you can interact with the Spire agent socket from your own application. The
| `tags.haAgentCommon` | Set the chart mode to deploy the common portion of a spire-ha-agent setup | `false` | | `tags.haAgentCommon` | Set the chart mode to deploy the common portion of a spire-ha-agent setup | `false` |
| `tags.bottomTurtleHAA` | Setup HA side A for use with a Bottom Turtle architecture | `false` | | `tags.bottomTurtleHAA` | Setup HA side A for use with a Bottom Turtle architecture | `false` |
| `tags.bottomTurtleHAB` | Setup HA side B for use with a Bottom Turtle architecture | `false` | | `tags.bottomTurtleHAB` | Setup HA side B for use with a Bottom Turtle architecture | `false` |
| `gatewayAPI.gateway.enabled` | Render the shared Gateway object | `false` |
| `gatewayAPI.gateway.className` | gatewayClassName for the shared Gateway (e.g. "eg"). Required when enabled. | `""` |
| `gatewayAPI.gateway.annotations` | Annotations for the Gateway object | `{}` |
| `gatewayAPI.gateway.allowedListenersNamespaces` | From which namespaces ListenerSets may attach to the Gateway. One of All, Same, Selector. | `All` |
| `gatewayAPI.gateway.allowedRoutesNamespaces` | From which namespaces routes may attach directly to the base listener (used when ListenerSet management is off). One of All, Same, Selector. | `All` |
| `gatewayAPI.gateway.extraListeners` | Additional listeners to add to the Gateway | `[]` |
| `spireIdentityExchange.podSelector` | Labels selecting the exchange pods of both sides. Narrow it (for example by adding release-namespace) when other exchanges share the namespace. | `{}` |
| `spireIdentityExchange.tls.rest.enabled` | Expose the combined REST endpoint served with the on-disk certificate | `false` |
| `spireIdentityExchange.tls.rest.service.type` | Service type | `ClusterIP` |
| `spireIdentityExchange.tls.rest.service.port` | port for the service | `443` |
| `spireIdentityExchange.tls.rest.service.annotations` | Annotations for service resource | `{}` |
| `spireIdentityExchange.tls.rest.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` |
| `spireIdentityExchange.tls.rest.ingress.enabled` | Flag to enable ingress | `false` |
| `spireIdentityExchange.tls.rest.ingress.className` | Ingress class name | `""` |
| `spireIdentityExchange.tls.rest.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `spireIdentityExchange.tls.rest.ingress.annotations` | Annotations for ingress object | `{}` |
| `spireIdentityExchange.tls.rest.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. Must differ from the per-side hosts. | `spire-identity-exchange-rest` |
| `spireIdentityExchange.tls.rest.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` |
| `spireIdentityExchange.tls.rest.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` |
| `spireIdentityExchange.tls.rest.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` |
| `spireIdentityExchange.tls.rest.gatewayAPI.enabled` | Flag to expose the endpoint via Gateway API | `false` |
| `spireIdentityExchange.tls.rest.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-rest` |
| `spireIdentityExchange.tls.rest.gatewayAPI.tlsSecret` | Secret with the TLS cert for edge termination. Blank keeps passthrough. | `""` |
| `spireIdentityExchange.tls.rest.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` |
| `spireIdentityExchange.tls.rest.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` |
| `spireIdentityExchange.tls.rest.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` |
| `spireIdentityExchange.tls.rest.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` |
| `spireIdentityExchange.tls.rest.gatewayAPI.backendTLS.caCertificateRefs` | ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap. | `[]` |
| `spireIdentityExchange.tls.grpc.enabled` | Expose the combined gRPC endpoint served with the on-disk certificate | `false` |
| `spireIdentityExchange.tls.grpc.service.type` | Service type | `ClusterIP` |
| `spireIdentityExchange.tls.grpc.service.port` | port for the service | `443` |
| `spireIdentityExchange.tls.grpc.service.annotations` | Annotations for service resource | `{}` |
| `spireIdentityExchange.tls.grpc.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` |
| `spireIdentityExchange.tls.grpc.ingress.enabled` | Flag to enable ingress | `false` |
| `spireIdentityExchange.tls.grpc.ingress.className` | Ingress class name | `""` |
| `spireIdentityExchange.tls.grpc.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `spireIdentityExchange.tls.grpc.ingress.annotations` | Annotations for ingress object | `{}` |
| `spireIdentityExchange.tls.grpc.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. Must differ from the per-side hosts. | `spire-identity-exchange-grpc` |
| `spireIdentityExchange.tls.grpc.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` |
| `spireIdentityExchange.tls.grpc.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` |
| `spireIdentityExchange.tls.grpc.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` |
| `spireIdentityExchange.tls.grpc.gatewayAPI.enabled` | Flag to expose the endpoint via Gateway API | `false` |
| `spireIdentityExchange.tls.grpc.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-grpc` |
| `spireIdentityExchange.tls.grpc.gatewayAPI.tlsSecret` | Secret with the TLS cert for edge termination. Blank keeps passthrough. | `""` |
| `spireIdentityExchange.tls.grpc.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` |
| `spireIdentityExchange.tls.grpc.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` |
| `spireIdentityExchange.tls.grpc.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` |
| `spireIdentityExchange.tls.grpc.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` |
| `spireIdentityExchange.tls.grpc.gatewayAPI.backendTLS.caCertificateRefs` | ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap. | `[]` |
| `spireIdentityExchange.spiffe.rest.enabled` | Expose the combined REST endpoint served with each side's own X509-SVID | `false` |
| `spireIdentityExchange.spiffe.rest.service.type` | Service type | `ClusterIP` |
| `spireIdentityExchange.spiffe.rest.service.port` | port for the service | `443` |
| `spireIdentityExchange.spiffe.rest.service.annotations` | Annotations for service resource | `{}` |
| `spireIdentityExchange.spiffe.rest.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` |
| `spireIdentityExchange.spiffe.rest.ingress.enabled` | Flag to enable ingress | `false` |
| `spireIdentityExchange.spiffe.rest.ingress.className` | Ingress class name | `""` |
| `spireIdentityExchange.spiffe.rest.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `spireIdentityExchange.spiffe.rest.ingress.annotations` | Annotations for ingress object | `{}` |
| `spireIdentityExchange.spiffe.rest.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. Must differ from the per-side hosts. | `spire-identity-exchange-rest-spiffe` |
| `spireIdentityExchange.spiffe.rest.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` |
| `spireIdentityExchange.spiffe.rest.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` |
| `spireIdentityExchange.spiffe.rest.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` |
| `spireIdentityExchange.spiffe.rest.gatewayAPI.enabled` | Flag to expose the endpoint via Gateway API | `false` |
| `spireIdentityExchange.spiffe.rest.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-rest-spiffe` |
| `spireIdentityExchange.spiffe.rest.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` |
| `spireIdentityExchange.spiffe.rest.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` |
| `spireIdentityExchange.spiffe.rest.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` |
| `spireIdentityExchange.spiffe.rest.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` |
| `spireIdentityExchange.spiffe.grpc.enabled` | Expose the combined gRPC endpoint served with each side's own X509-SVID | `false` |
| `spireIdentityExchange.spiffe.grpc.service.type` | Service type | `ClusterIP` |
| `spireIdentityExchange.spiffe.grpc.service.port` | port for the service | `443` |
| `spireIdentityExchange.spiffe.grpc.service.annotations` | Annotations for service resource | `{}` |
| `spireIdentityExchange.spiffe.grpc.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` |
| `spireIdentityExchange.spiffe.grpc.ingress.enabled` | Flag to enable ingress | `false` |
| `spireIdentityExchange.spiffe.grpc.ingress.className` | Ingress class name | `""` |
| `spireIdentityExchange.spiffe.grpc.ingress.controllerType` | Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. | `""` |
| `spireIdentityExchange.spiffe.grpc.ingress.annotations` | Annotations for ingress object | `{}` |
| `spireIdentityExchange.spiffe.grpc.ingress.host` | Host name for the ingress. If no '.' in host, trustDomain is automatically appended. Must differ from the per-side hosts. | `spire-identity-exchange-grpc-spiffe` |
| `spireIdentityExchange.spiffe.grpc.ingress.tlsSecret` | Secret that has the certs. If blank will use default certs. Used with host var. | `""` |
| `spireIdentityExchange.spiffe.grpc.ingress.hosts` | Host paths for ingress object. If emtpy, rules will be built based on the host var. | `[]` |
| `spireIdentityExchange.spiffe.grpc.ingress.tls` | Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars. | `[]` |
| `spireIdentityExchange.spiffe.grpc.gatewayAPI.enabled` | Flag to expose the endpoint via Gateway API | `false` |
| `spireIdentityExchange.spiffe.grpc.gatewayAPI.host` | Host name for the route. If no '.' in host, trustDomain is automatically appended. | `spire-identity-exchange-grpc-spiffe` |
| `spireIdentityExchange.spiffe.grpc.gatewayAPI.annotations` | Annotations for the route (and its ListenerSet) | `{}` |
| `spireIdentityExchange.spiffe.grpc.gatewayAPI.listenerSet.enabled` | Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets. | `nil` |
| `spireIdentityExchange.spiffe.grpc.gatewayAPI.parentRefs` | parentRefs used when ListenerSet management is disabled (direct attach) | `[]` |
| `spireIdentityExchange.spiffe.grpc.gatewayAPI.sectionName` | Listener sectionName override when attaching directly to a Gateway | `""` |
### Spire agent parameters ### Spire agent parameters
@@ -385,7 +476,7 @@ Now you can interact with the Spire agent socket from your own application. The
### Spire server parameters ### Spire server parameters
| Name | Description | Value | | Name | Description | Value |
| ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------- | | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `internal-spire-server-bottom-turtle-ha-a.nameOverride` | Overrides the name of Spire server pods | `internal-server` | | `internal-spire-server-bottom-turtle-ha-a.nameOverride` | Overrides the name of Spire server pods | `internal-server` |
| `internal-spire-server-bottom-turtle-ha-a.caKeyType` | Key type to use for the ca | `ec-p256` | | `internal-spire-server-bottom-turtle-ha-a.caKeyType` | Key type to use for the ca | `ec-p256` |
| `internal-spire-server-bottom-turtle-ha-a.experimental.enabled` | enable experimental features | `true` | | `internal-spire-server-bottom-turtle-ha-a.experimental.enabled` | enable experimental features | `true` |
@@ -398,7 +489,7 @@ Now you can interact with the Spire agent socket from your own application. The
| `internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.oidc-discovery-provider.autoPopulateDNSNames` | Auto populate dns entries | `false` | | `internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.oidc-discovery-provider.autoPopulateDNSNames` | Auto populate dns entries | `false` |
| `internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.oidc-discovery-provider.type` | The type of the entry | `oidc-discovery-provider-common` | | `internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.oidc-discovery-provider.type` | The type of the entry | `oidc-discovery-provider-common` |
| `internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.enabled` | Enables the spire-ha-agent identity | `true` | | `internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.enabled` | Enables the spire-ha-agent identity | `true` |
| `internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.spire-identity-exchange-service.federatesWith` | List of trust domains to federate with | `[]` | | `internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.spire-identity-exchange-service.federatesWith` | List of trust domains to federate with | `[]` |
| `internal-spire-server-bottom-turtle-ha-a.persistence.type` | What type to use for peristence | `emptyDir` | | `internal-spire-server-bottom-turtle-ha-a.persistence.type` | What type to use for peristence | `emptyDir` |
| `internal-spire-server-bottom-turtle-ha-a.nodeAttestor.k8sPSAT.enabled` | Enable the k8s projected access token node attestor | `false` | | `internal-spire-server-bottom-turtle-ha-a.nodeAttestor.k8sPSAT.enabled` | Enable the k8s projected access token node attestor | `false` |
| `internal-spire-server-bottom-turtle-ha-a.nodeAttestor.x509POP.enabled` | Enable the x509 pop node attestor | `true` | | `internal-spire-server-bottom-turtle-ha-a.nodeAttestor.x509POP.enabled` | Enable the x509 pop node attestor | `true` |
@@ -418,7 +509,7 @@ Now you can interact with the Spire agent socket from your own application. The
### Spire server parameters ### Spire server parameters
| Name | Description | Value | | Name | Description | Value |
| ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------- | | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `internal-spire-server-bottom-turtle-ha-b.nameOverride` | Overrides the name of Spire server pods | `internal-server` | | `internal-spire-server-bottom-turtle-ha-b.nameOverride` | Overrides the name of Spire server pods | `internal-server` |
| `internal-spire-server-bottom-turtle-ha-b.caKeyType` | Key type to use for the ca | `ec-p256` | | `internal-spire-server-bottom-turtle-ha-b.caKeyType` | Key type to use for the ca | `ec-p256` |
| `internal-spire-server-bottom-turtle-ha-b.experimental.enabled` | enable experimental features | `true` | | `internal-spire-server-bottom-turtle-ha-b.experimental.enabled` | enable experimental features | `true` |
@@ -431,7 +522,7 @@ Now you can interact with the Spire agent socket from your own application. The
| `internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.oidc-discovery-provider.autoPopulateDNSNames` | Auto populate dns entries | `false` | | `internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.oidc-discovery-provider.autoPopulateDNSNames` | Auto populate dns entries | `false` |
| `internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.oidc-discovery-provider.type` | The type of the entry | `oidc-discovery-provider-common` | | `internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.oidc-discovery-provider.type` | The type of the entry | `oidc-discovery-provider-common` |
| `internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.enabled` | Enables the spire-ha-agent identity | `true` | | `internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.enabled` | Enables the spire-ha-agent identity | `true` |
| `internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.spire-identity-exchange-service.federatesWith` | List of trust domains to federate with | `[]` | | `internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.spire-identity-exchange-service.federatesWith` | List of trust domains to federate with | `[]` |
| `internal-spire-server-bottom-turtle-ha-b.persistence.type` | What type to use for peristence | `emptyDir` | | `internal-spire-server-bottom-turtle-ha-b.persistence.type` | What type to use for peristence | `emptyDir` |
| `internal-spire-server-bottom-turtle-ha-b.nodeAttestor.k8sPSAT.enabled` | Enable the k8s projected access token node attestor | `false` | | `internal-spire-server-bottom-turtle-ha-b.nodeAttestor.k8sPSAT.enabled` | Enable the k8s projected access token node attestor | `false` |
| `internal-spire-server-bottom-turtle-ha-b.nodeAttestor.x509POP.enabled` | Enable the x509 pop node attestor | `true` | | `internal-spire-server-bottom-turtle-ha-b.nodeAttestor.x509POP.enabled` | Enable the x509 pop node attestor | `true` |
@@ -502,12 +593,20 @@ Now you can interact with the Spire agent socket from your own application. The
| `spire-identity-exchange-bottom-turtle-ha-a.enabled` | Enable the spire-identity-exchange | `false` | | `spire-identity-exchange-bottom-turtle-ha-a.enabled` | Enable the spire-identity-exchange | `false` |
| `spire-identity-exchange-bottom-turtle-ha-a.nameOverride` | name override | `identity-exchange` | | `spire-identity-exchange-bottom-turtle-ha-a.nameOverride` | name override | `identity-exchange` |
| `spire-identity-exchange-bottom-turtle-ha-a.csiDriverName` | CSI driver name to use | `a.csi.spiffe.io` | | `spire-identity-exchange-bottom-turtle-ha-a.csiDriverName` | CSI driver name to use | `a.csi.spiffe.io` |
| `spire-identity-exchange-bottom-turtle-ha-a.rest.ingress.host` | Hostname override for the rest ingress service | `spire-identity-exchange-a-rest` | | `spire-identity-exchange-bottom-turtle-ha-a.tls.rest.ingress.host` | Hostname override for the rest ingress service | `spire-identity-exchange-a-rest` |
| `spire-identity-exchange-bottom-turtle-ha-a.grpc.ingress.host` | Hostname override for the rest ingress service | `spire-identity-exchange-a-grpc` | | `spire-identity-exchange-bottom-turtle-ha-a.tls.grpc.ingress.host` | Hostname override for the grpc ingress service | `spire-identity-exchange-a-grpc` |
| `spire-identity-exchange-bottom-turtle-ha-a.spiffe.rest.ingress.host` | Hostname override for the SVID-served rest ingress service | `spire-identity-exchange-a-rest-spiffe` |
| `spire-identity-exchange-bottom-turtle-ha-a.spiffe.grpc.ingress.host` | Hostname override for the SVID-served grpc ingress service | `spire-identity-exchange-a-grpc-spiffe` |
| `spire-identity-exchange-bottom-turtle-ha-a.server.nameOverride` | The name override setting of the internal SPIRE server | `internal-server` | | `spire-identity-exchange-bottom-turtle-ha-a.server.nameOverride` | The name override setting of the internal SPIRE server | `internal-server` |
| `spire-identity-exchange-bottom-turtle-ha-a.auth.plugins.spiffe.csiDriverName` | The csi driver the spiffe plugin reads its trust bundle from. The shared ha-agent, since that is what mints the oidc discovery provider's serving svid. | `csi.spiffe.io` |
| `spire-identity-exchange-bottom-turtle-ha-a.auth.plugins.spiffe.config.discoveryURL` | The OIDC discovery provider to fetch keys from. This chart gives it a fullnameOverride, so the keySource convention does not apply. | `https://spiffe-oidc-discovery-provider` |
| `spire-identity-exchange-bottom-turtle-ha-b.enabled` | Enable the spire-identity-exchange | `false` | | `spire-identity-exchange-bottom-turtle-ha-b.enabled` | Enable the spire-identity-exchange | `false` |
| `spire-identity-exchange-bottom-turtle-ha-b.nameOverride` | name override | `identity-exchange` | | `spire-identity-exchange-bottom-turtle-ha-b.nameOverride` | name override | `identity-exchange` |
| `spire-identity-exchange-bottom-turtle-ha-b.csiDriverName` | CSI driver name to use | `b.csi.spiffe.io` | | `spire-identity-exchange-bottom-turtle-ha-b.csiDriverName` | CSI driver name to use | `b.csi.spiffe.io` |
| `spire-identity-exchange-bottom-turtle-ha-b.server.nameOverride` | The name override setting of the internal SPIRE server | `internal-server` | | `spire-identity-exchange-bottom-turtle-ha-b.server.nameOverride` | The name override setting of the internal SPIRE server | `internal-server` |
| `spire-identity-exchange-bottom-turtle-ha-b.rest.ingress.host` | Hostname override for the rest ingress service | `spire-identity-exchange-b-rest` | | `spire-identity-exchange-bottom-turtle-ha-b.tls.rest.ingress.host` | Hostname override for the rest ingress service | `spire-identity-exchange-b-rest` |
| `spire-identity-exchange-bottom-turtle-ha-b.grpc.ingress.host` | Hostname override for the rest ingress service | `spire-identity-exchange-b-grpc` | | `spire-identity-exchange-bottom-turtle-ha-b.tls.grpc.ingress.host` | Hostname override for the grpc ingress service | `spire-identity-exchange-b-grpc` |
| `spire-identity-exchange-bottom-turtle-ha-b.spiffe.rest.ingress.host` | Hostname override for the SVID-served rest ingress service | `spire-identity-exchange-b-rest-spiffe` |
| `spire-identity-exchange-bottom-turtle-ha-b.spiffe.grpc.ingress.host` | Hostname override for the SVID-served grpc ingress service | `spire-identity-exchange-b-grpc-spiffe` |
| `spire-identity-exchange-bottom-turtle-ha-b.auth.plugins.spiffe.csiDriverName` | The csi driver the spiffe plugin reads its trust bundle from. The shared ha-agent, since that is what mints the oidc discovery provider's serving svid. | `csi.spiffe.io` |
| `spire-identity-exchange-bottom-turtle-ha-b.auth.plugins.spiffe.config.discoveryURL` | The OIDC discovery provider to fetch keys from. This chart gives it a fullnameOverride, so the keySource convention does not apply. | `https://spiffe-oidc-discovery-provider` |
@@ -0,0 +1,64 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "spire-nested.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "spire-nested.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "spire-nested.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "spire-nested.labels" -}}
helm.sh/chart: {{ include "spire-nested.chart" . }}
app.kubernetes.io/name: {{ include "spire-nested.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
The namespace the SPIRE server side components land in. Resolved the same way as
spire-identity-exchange.namespace, so the combined exposure lands beside the exchange
pods it selects — a Service selector is namespace scoped.
*/}}
{{- define "spire-nested.server-namespace" -}}
{{- if and (dig "spire" "recommendations" "enabled" false .Values.global) (dig "spire" "recommendations" "namespaceLayout" true .Values.global) }}
{{- if ne (len (dig "spire" "namespaces" "server" "name" "" .Values.global)) 0 }}
{{- .Values.global.spire.namespaces.server.name }}
{{- else }}
{{- printf "spire-server" }}
{{- end }}
{{- else -}}
{{- .Release.Namespace -}}
{{- end -}}
{{- end -}}
{{/*
Base name for the combined identity exchange objects. Keyed on the release name so it
reads like the per-side exchanges, which the sides' own releases name spire-a-identity-
exchange / spire-b-identity-exchange — so these never collide with them either.
*/}}
{{- define "spire-nested.identity-exchange-name" -}}
{{- printf "%s-identity-exchange" .Release.Name | trunc 63 | trimSuffix "-" }}
{{- end }}
@@ -0,0 +1,3 @@
{{- if .Values.gatewayAPI.gateway.enabled }}
{{- include "spire-lib.gateway-resource" (dict "root" . "gatewayObject" .Values.gatewayAPI.gateway) }}
{{- end }}
@@ -0,0 +1,15 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.spiffe.grpc.enabled .Values.spireIdentityExchange.spiffe.grpc.gatewayAPI.enabled -}}
{{- $fullName := printf "%s-grpc-spiffe" (include "spire-nested.identity-exchange-name" .) -}}
{{/* Passthrough only. These backends serve an X509-SVID, whose only SAN is a
spiffe:// URI, so a BackendTLSPolicy hostname check could never match. */}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.spireIdentityExchange.spiffe.grpc.gatewayAPI
"name" $fullName
"namespace" (include "spire-nested.server-namespace" .)
"svcName" $fullName
"port" .Values.spireIdentityExchange.spiffe.grpc.service.port
"labels" (include "spire-nested.labels" .)
"routeKind" "TLSRoute"
"backendTLS" false) }}
{{- end }}
@@ -0,0 +1,39 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.spiffe.grpc.enabled .Values.spireIdentityExchange.spiffe.grpc.ingress.enabled -}}
{{- $port := .Values.spireIdentityExchange.spiffe.grpc.service.port }}
{{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.spireIdentityExchange.spiffe.grpc.ingress) }}
{{- $fullName := printf "%s-grpc-spiffe" (include "spire-nested.identity-exchange-name" .) }}
{{- $path := "/" }}
{{- $pathType := "Prefix" }}
{{- $tlsSection := true }}
{{- $annotations := deepCopy .Values.spireIdentityExchange.spiffe.grpc.ingress.annotations }}
{{- if eq $ingressControllerType "ingress-nginx" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }}
{{- if not .Values.spireIdentityExchange.spiffe.grpc.ingress.tlsSecret }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }}
{{- end }}
{{- else if eq $ingressControllerType "openshift" }}
{{- if .Values.spireIdentityExchange.spiffe.grpc.ingress.tlsSecret }}
{{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }}
{{- else }}
{{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }}
{{- end }}
{{- $path = "" }}
{{- $pathType = "ImplementationSpecific" }}
{{- $tlsSection = false }}
{{- end }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ include "spire-nested.server-namespace" . }}
labels:
{{ include "spire-nested.labels" . | nindent 4 }}
{{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{ include "spire-lib.ingress-spec" (dict "ingress" .Values.spireIdentityExchange.spiffe.grpc.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }}
{{- end }}
@@ -0,0 +1,25 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.spiffe.grpc.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "spire-nested.identity-exchange-name" . }}-grpc-spiffe
namespace: {{ include "spire-nested.server-namespace" . }}
labels:
{{- include "spire-nested.labels" . | nindent 4 }}
{{- with .Values.spireIdentityExchange.spiffe.grpc.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.spireIdentityExchange.spiffe.grpc.service.type }}
{{- if and (eq .Values.spireIdentityExchange.spiffe.grpc.service.type "LoadBalancer") .Values.spireIdentityExchange.spiffe.grpc.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.spireIdentityExchange.spiffe.grpc.service.loadBalancerIP }}
{{- end }}
ports:
- name: https
port: {{ .Values.spireIdentityExchange.spiffe.grpc.service.port }}
targetPort: grpc-spiffe
protocol: TCP
selector:
{{- toYaml .Values.spireIdentityExchange.podSelector | nindent 4 }}
{{- end }}
@@ -0,0 +1,15 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.spiffe.rest.enabled .Values.spireIdentityExchange.spiffe.rest.gatewayAPI.enabled -}}
{{- $fullName := printf "%s-rest-spiffe" (include "spire-nested.identity-exchange-name" .) -}}
{{/* Passthrough only. These backends serve an X509-SVID, whose only SAN is a
spiffe:// URI, so a BackendTLSPolicy hostname check could never match. */}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.spireIdentityExchange.spiffe.rest.gatewayAPI
"name" $fullName
"namespace" (include "spire-nested.server-namespace" .)
"svcName" $fullName
"port" .Values.spireIdentityExchange.spiffe.rest.service.port
"labels" (include "spire-nested.labels" .)
"routeKind" "TLSRoute"
"backendTLS" false) }}
{{- end }}
@@ -0,0 +1,39 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.spiffe.rest.enabled .Values.spireIdentityExchange.spiffe.rest.ingress.enabled -}}
{{- $port := .Values.spireIdentityExchange.spiffe.rest.service.port }}
{{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.spireIdentityExchange.spiffe.rest.ingress) }}
{{- $fullName := printf "%s-rest-spiffe" (include "spire-nested.identity-exchange-name" .) }}
{{- $path := "/" }}
{{- $pathType := "Prefix" }}
{{- $tlsSection := true }}
{{- $annotations := deepCopy .Values.spireIdentityExchange.spiffe.rest.ingress.annotations }}
{{- if eq $ingressControllerType "ingress-nginx" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }}
{{- if not .Values.spireIdentityExchange.spiffe.rest.ingress.tlsSecret }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }}
{{- end }}
{{- else if eq $ingressControllerType "openshift" }}
{{- if .Values.spireIdentityExchange.spiffe.rest.ingress.tlsSecret }}
{{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }}
{{- else }}
{{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }}
{{- end }}
{{- $path = "" }}
{{- $pathType = "ImplementationSpecific" }}
{{- $tlsSection = false }}
{{- end }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ include "spire-nested.server-namespace" . }}
labels:
{{ include "spire-nested.labels" . | nindent 4 }}
{{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{ include "spire-lib.ingress-spec" (dict "ingress" .Values.spireIdentityExchange.spiffe.rest.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }}
{{- end }}
@@ -0,0 +1,25 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.spiffe.rest.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "spire-nested.identity-exchange-name" . }}-rest-spiffe
namespace: {{ include "spire-nested.server-namespace" . }}
labels:
{{- include "spire-nested.labels" . | nindent 4 }}
{{- with .Values.spireIdentityExchange.spiffe.rest.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.spireIdentityExchange.spiffe.rest.service.type }}
{{- if and (eq .Values.spireIdentityExchange.spiffe.rest.service.type "LoadBalancer") .Values.spireIdentityExchange.spiffe.rest.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.spireIdentityExchange.spiffe.rest.service.loadBalancerIP }}
{{- end }}
ports:
- name: https
port: {{ .Values.spireIdentityExchange.spiffe.rest.service.port }}
targetPort: rest-spiffe
protocol: TCP
selector:
{{- toYaml .Values.spireIdentityExchange.podSelector | nindent 4 }}
{{- end }}
@@ -0,0 +1,14 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.tls.grpc.enabled .Values.spireIdentityExchange.tls.grpc.gatewayAPI.enabled -}}
{{- $fullName := printf "%s-grpc" (include "spire-nested.identity-exchange-name" .) -}}
{{- $routeKind := include "spire-lib.gateway-route-kind" (dict "gatewayAPI" .Values.spireIdentityExchange.tls.grpc.gatewayAPI) -}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.spireIdentityExchange.tls.grpc.gatewayAPI
"name" $fullName
"namespace" (include "spire-nested.server-namespace" .)
"svcName" $fullName
"port" .Values.spireIdentityExchange.tls.grpc.service.port
"labels" (include "spire-nested.labels" .)
"routeKind" $routeKind
"backendTLS" (eq $routeKind "HTTPRoute")) }}
{{- end }}
@@ -0,0 +1,39 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.tls.grpc.enabled .Values.spireIdentityExchange.tls.grpc.ingress.enabled -}}
{{- $port := .Values.spireIdentityExchange.tls.grpc.service.port }}
{{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.spireIdentityExchange.tls.grpc.ingress) }}
{{- $fullName := printf "%s-grpc" (include "spire-nested.identity-exchange-name" .) }}
{{- $path := "/" }}
{{- $pathType := "Prefix" }}
{{- $tlsSection := true }}
{{- $annotations := deepCopy .Values.spireIdentityExchange.tls.grpc.ingress.annotations }}
{{- if eq $ingressControllerType "ingress-nginx" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }}
{{- if not .Values.spireIdentityExchange.tls.grpc.ingress.tlsSecret }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }}
{{- end }}
{{- else if eq $ingressControllerType "openshift" }}
{{- if .Values.spireIdentityExchange.tls.grpc.ingress.tlsSecret }}
{{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }}
{{- else }}
{{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }}
{{- end }}
{{- $path = "" }}
{{- $pathType = "ImplementationSpecific" }}
{{- $tlsSection = false }}
{{- end }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ include "spire-nested.server-namespace" . }}
labels:
{{ include "spire-nested.labels" . | nindent 4 }}
{{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{ include "spire-lib.ingress-spec" (dict "ingress" .Values.spireIdentityExchange.tls.grpc.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }}
{{- end }}
@@ -0,0 +1,25 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.tls.grpc.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "spire-nested.identity-exchange-name" . }}-grpc
namespace: {{ include "spire-nested.server-namespace" . }}
labels:
{{- include "spire-nested.labels" . | nindent 4 }}
{{- with .Values.spireIdentityExchange.tls.grpc.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.spireIdentityExchange.tls.grpc.service.type }}
{{- if and (eq .Values.spireIdentityExchange.tls.grpc.service.type "LoadBalancer") .Values.spireIdentityExchange.tls.grpc.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.spireIdentityExchange.tls.grpc.service.loadBalancerIP }}
{{- end }}
ports:
- name: https
port: {{ .Values.spireIdentityExchange.tls.grpc.service.port }}
targetPort: grpc
protocol: TCP
selector:
{{- toYaml .Values.spireIdentityExchange.podSelector | nindent 4 }}
{{- end }}
@@ -0,0 +1,14 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.tls.rest.enabled .Values.spireIdentityExchange.tls.rest.gatewayAPI.enabled -}}
{{- $fullName := printf "%s-rest" (include "spire-nested.identity-exchange-name" .) -}}
{{- $routeKind := include "spire-lib.gateway-route-kind" (dict "gatewayAPI" .Values.spireIdentityExchange.tls.rest.gatewayAPI) -}}
{{- include "spire-lib.gateway-routes" (dict
"root" .
"gatewayAPI" .Values.spireIdentityExchange.tls.rest.gatewayAPI
"name" $fullName
"namespace" (include "spire-nested.server-namespace" .)
"svcName" $fullName
"port" .Values.spireIdentityExchange.tls.rest.service.port
"labels" (include "spire-nested.labels" .)
"routeKind" $routeKind
"backendTLS" (eq $routeKind "HTTPRoute")) }}
{{- end }}
@@ -0,0 +1,39 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.tls.rest.enabled .Values.spireIdentityExchange.tls.rest.ingress.enabled -}}
{{- $port := .Values.spireIdentityExchange.tls.rest.service.port }}
{{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.spireIdentityExchange.tls.rest.ingress) }}
{{- $fullName := printf "%s-rest" (include "spire-nested.identity-exchange-name" .) }}
{{- $path := "/" }}
{{- $pathType := "Prefix" }}
{{- $tlsSection := true }}
{{- $annotations := deepCopy .Values.spireIdentityExchange.tls.rest.ingress.annotations }}
{{- if eq $ingressControllerType "ingress-nginx" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/force-ssl-redirect" "true" }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/backend-protocol" "HTTPS" }}
{{- if not .Values.spireIdentityExchange.tls.rest.ingress.tlsSecret }}
{{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-passthrough" "true" }}
{{- end }}
{{- else if eq $ingressControllerType "openshift" }}
{{- if .Values.spireIdentityExchange.tls.rest.ingress.tlsSecret }}
{{- $_ := set $annotations "route.openshift.io/termination" "reencrypt" }}
{{- else }}
{{- $_ := set $annotations "route.openshift.io/termination" "passthrough" }}
{{- end }}
{{- $path = "" }}
{{- $pathType = "ImplementationSpecific" }}
{{- $tlsSection = false }}
{{- end }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ include "spire-nested.server-namespace" . }}
labels:
{{ include "spire-nested.labels" . | nindent 4 }}
{{- with $annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{ include "spire-lib.ingress-spec" (dict "ingress" .Values.spireIdentityExchange.tls.rest.ingress "svcName" $fullName "port" $port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }}
{{- end }}
@@ -0,0 +1,25 @@
{{- if and .Values.tags.haAgentCommon .Values.spireIdentityExchange.tls.rest.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "spire-nested.identity-exchange-name" . }}-rest
namespace: {{ include "spire-nested.server-namespace" . }}
labels:
{{- include "spire-nested.labels" . | nindent 4 }}
{{- with .Values.spireIdentityExchange.tls.rest.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.spireIdentityExchange.tls.rest.service.type }}
{{- if and (eq .Values.spireIdentityExchange.tls.rest.service.type "LoadBalancer") .Values.spireIdentityExchange.tls.rest.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.spireIdentityExchange.tls.rest.service.loadBalancerIP }}
{{- end }}
ports:
- name: https
port: {{ .Values.spireIdentityExchange.tls.rest.service.port }}
targetPort: rest
protocol: TCP
selector:
{{- toYaml .Values.spireIdentityExchange.podSelector | nindent 4 }}
{{- end }}
+287 -6
View File
@@ -73,6 +73,24 @@ global:
## @param global.spire.ingressControllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""]. ## @param global.spire.ingressControllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
ingressControllerType: "" ingressControllerType: ""
## Shared Gateway that routes and ListenerSets attach to. The Gateway object itself is
## rendered by the `gatewayAPI.gateway` block of this chart. Gateway API support is
## independent of ingress and can be enabled alongside it.
gatewayAPI:
## @param global.spire.gatewayAPI.manageListenerSets Default policy for whether services render a ListenerSet for their SNI listener. Each service may override via its gatewayAPI.listenerSet.enabled.
manageListenerSets: true
gateway:
## @param global.spire.gatewayAPI.gateway.name Name of the shared Gateway object that routes and ListenerSets attach to
name: spire
## The Gateway object and every route's parentRef both read this value, so they
## cannot disagree. It defaults to the server namespace so the Gateway sits with
## the workloads it fronts; a ListenerSet in another namespace still attaches, as
## the Gateway allows listeners from all namespaces by default.
## @param global.spire.gatewayAPI.gateway.namespace Namespace of the shared Gateway object. Defaults to the release namespace if blank.
namespace: spire-server
## @param global.spire.gatewayAPI.gateway.port Port the shared Gateway listens on. ListenerSet listeners must match this.
port: 443
tools: tools:
kubectl: kubectl:
## @param global.spire.tools.kubectl.tag Set to force the tag to use for all kubectl instances ## @param global.spire.tools.kubectl.tag Set to force the tag to use for all kubectl instances
@@ -108,6 +126,233 @@ tags:
## @param tags.bottomTurtleHAB Setup HA side B for use with a Bottom Turtle architecture ## @param tags.bottomTurtleHAB Setup HA side B for use with a Bottom Turtle architecture
bottomTurtleHAB: false bottomTurtleHAB: false
## The shared Gateway that routes and ListenerSets attach to. Only one release in a cluster
## should render it. name/namespace/port come from global.spire.gatewayAPI.gateway; the
## class and listener policy are local.
##
gatewayAPI:
gateway:
## @param gatewayAPI.gateway.enabled Render the shared Gateway object
enabled: false
## @param gatewayAPI.gateway.className gatewayClassName for the shared Gateway (e.g. "eg"). Required when enabled.
className: ""
## @param gatewayAPI.gateway.annotations [object] Annotations for the Gateway object
annotations: {}
## @param gatewayAPI.gateway.allowedListenersNamespaces From which namespaces ListenerSets may attach to the Gateway. One of All, Same, Selector.
allowedListenersNamespaces: All
## @param gatewayAPI.gateway.allowedRoutesNamespaces From which namespaces routes may attach directly to the base listener (used when ListenerSet management is off). One of All, Same, Selector.
allowedRoutesNamespaces: All
## @param gatewayAPI.gateway.extraListeners [array] Additional listeners to add to the Gateway
extraListeners: []
## Combined exposure fronting the spire-identity-exchange of both HA sides. Only rendered
## with tags.haAgentCommon; the per-side exposures under bottomTurtleHAA/B are untouched.
## Each endpoint gets one Service selecting both sides' exchange pods, so the Ingress and
## the Gateway API route need only a single backend. The matching listener must be enabled
## on the sides themselves; if it is not, the Service simply has no endpoints.
spireIdentityExchange:
## @param spireIdentityExchange.podSelector [object] Labels selecting the exchange pods of both sides. Narrow it (for example by adding release-namespace) when other exchanges share the namespace.
podSelector:
component: spire-identity-exchange
## Endpoints served with the certificate each side loads from disk.
tls:
rest:
## @param spireIdentityExchange.tls.rest.enabled Expose the combined REST endpoint served with the on-disk certificate
enabled: false
## @param spireIdentityExchange.tls.rest.service.type Service type
## @param spireIdentityExchange.tls.rest.service.port port for the service
## @param spireIdentityExchange.tls.rest.service.annotations Annotations for service resource
##
service:
type: ClusterIP
port: 443
annotations: {}
## @param spireIdentityExchange.tls.rest.service.loadBalancerIP IP address to assign to load balancer (if supported)
loadBalancerIP: ""
ingress:
## @param spireIdentityExchange.tls.rest.ingress.enabled Flag to enable ingress
enabled: false
## @param spireIdentityExchange.tls.rest.ingress.className Ingress class name
className: ""
## @param spireIdentityExchange.tls.rest.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
controllerType: ""
## @param spireIdentityExchange.tls.rest.ingress.annotations [object] Annotations for ingress object
annotations: {}
## @param spireIdentityExchange.tls.rest.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. Must differ from the per-side hosts.
host: "spire-identity-exchange-rest"
## @param spireIdentityExchange.tls.rest.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var.
tlsSecret: ""
## @param spireIdentityExchange.tls.rest.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var.
hosts: []
## @param spireIdentityExchange.tls.rest.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars.
tls: []
## Gateway API exposure for this endpoint. A set tlsSecret gives HTTPRoute (reencrypt); blank gives TLSRoute (SNI passthrough).
gatewayAPI:
## @param spireIdentityExchange.tls.rest.gatewayAPI.enabled Flag to expose the endpoint via Gateway API
enabled: false
## @param spireIdentityExchange.tls.rest.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended.
host: "spire-identity-exchange-rest"
## @param spireIdentityExchange.tls.rest.gatewayAPI.tlsSecret Secret with the TLS cert for edge termination. Blank keeps passthrough.
tlsSecret: ""
## @param spireIdentityExchange.tls.rest.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet)
annotations: {}
listenerSet:
## @param spireIdentityExchange.tls.rest.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets.
enabled: null
## @param spireIdentityExchange.tls.rest.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach)
parentRefs: []
## @param spireIdentityExchange.tls.rest.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway
sectionName: ""
backendTLS:
## @param spireIdentityExchange.tls.rest.gatewayAPI.backendTLS.caCertificateRefs [array] ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap.
caCertificateRefs: []
grpc:
## @param spireIdentityExchange.tls.grpc.enabled Expose the combined gRPC endpoint served with the on-disk certificate
enabled: false
## @param spireIdentityExchange.tls.grpc.service.type Service type
## @param spireIdentityExchange.tls.grpc.service.port port for the service
## @param spireIdentityExchange.tls.grpc.service.annotations Annotations for service resource
##
service:
type: ClusterIP
port: 443
annotations: {}
## @param spireIdentityExchange.tls.grpc.service.loadBalancerIP IP address to assign to load balancer (if supported)
loadBalancerIP: ""
ingress:
## @param spireIdentityExchange.tls.grpc.ingress.enabled Flag to enable ingress
enabled: false
## @param spireIdentityExchange.tls.grpc.ingress.className Ingress class name
className: ""
## @param spireIdentityExchange.tls.grpc.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
controllerType: ""
## @param spireIdentityExchange.tls.grpc.ingress.annotations [object] Annotations for ingress object
annotations: {}
## @param spireIdentityExchange.tls.grpc.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. Must differ from the per-side hosts.
host: "spire-identity-exchange-grpc"
## @param spireIdentityExchange.tls.grpc.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var.
tlsSecret: ""
## @param spireIdentityExchange.tls.grpc.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var.
hosts: []
## @param spireIdentityExchange.tls.grpc.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars.
tls: []
## Gateway API exposure for this endpoint. A set tlsSecret gives HTTPRoute (reencrypt); blank gives TLSRoute (SNI passthrough).
gatewayAPI:
## @param spireIdentityExchange.tls.grpc.gatewayAPI.enabled Flag to expose the endpoint via Gateway API
enabled: false
## @param spireIdentityExchange.tls.grpc.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended.
host: "spire-identity-exchange-grpc"
## @param spireIdentityExchange.tls.grpc.gatewayAPI.tlsSecret Secret with the TLS cert for edge termination. Blank keeps passthrough.
tlsSecret: ""
## @param spireIdentityExchange.tls.grpc.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet)
annotations: {}
listenerSet:
## @param spireIdentityExchange.tls.grpc.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets.
enabled: null
## @param spireIdentityExchange.tls.grpc.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach)
parentRefs: []
## @param spireIdentityExchange.tls.grpc.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway
sectionName: ""
backendTLS:
## @param spireIdentityExchange.tls.grpc.gatewayAPI.backendTLS.caCertificateRefs [array] ConfigMap refs holding the backend CA used to validate the re-encrypted connection. Defaults to the SPIRE bundle configmap.
caCertificateRefs: []
## Endpoints served with each side's own X509-SVID. Gateway API is always a TLSRoute
## (SNI passthrough) here: an X509-SVID has no DNS SAN, so edge termination could never
## validate these backends.
spiffe:
rest:
## @param spireIdentityExchange.spiffe.rest.enabled Expose the combined REST endpoint served with each side's own X509-SVID
enabled: false
## @param spireIdentityExchange.spiffe.rest.service.type Service type
## @param spireIdentityExchange.spiffe.rest.service.port port for the service
## @param spireIdentityExchange.spiffe.rest.service.annotations Annotations for service resource
##
service:
type: ClusterIP
port: 443
annotations: {}
## @param spireIdentityExchange.spiffe.rest.service.loadBalancerIP IP address to assign to load balancer (if supported)
loadBalancerIP: ""
ingress:
## @param spireIdentityExchange.spiffe.rest.ingress.enabled Flag to enable ingress
enabled: false
## @param spireIdentityExchange.spiffe.rest.ingress.className Ingress class name
className: ""
## @param spireIdentityExchange.spiffe.rest.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
controllerType: ""
## @param spireIdentityExchange.spiffe.rest.ingress.annotations [object] Annotations for ingress object
annotations: {}
## @param spireIdentityExchange.spiffe.rest.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. Must differ from the per-side hosts.
host: "spire-identity-exchange-rest-spiffe"
## @param spireIdentityExchange.spiffe.rest.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var.
tlsSecret: ""
## @param spireIdentityExchange.spiffe.rest.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var.
hosts: []
## @param spireIdentityExchange.spiffe.rest.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars.
tls: []
## Gateway API exposure for this endpoint. Always a TLSRoute (SNI passthrough).
gatewayAPI:
## @param spireIdentityExchange.spiffe.rest.gatewayAPI.enabled Flag to expose the endpoint via Gateway API
enabled: false
## @param spireIdentityExchange.spiffe.rest.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended.
host: "spire-identity-exchange-rest-spiffe"
## @param spireIdentityExchange.spiffe.rest.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet)
annotations: {}
listenerSet:
## @param spireIdentityExchange.spiffe.rest.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets.
enabled: null
## @param spireIdentityExchange.spiffe.rest.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach)
parentRefs: []
## @param spireIdentityExchange.spiffe.rest.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway
sectionName: ""
grpc:
## @param spireIdentityExchange.spiffe.grpc.enabled Expose the combined gRPC endpoint served with each side's own X509-SVID
enabled: false
## @param spireIdentityExchange.spiffe.grpc.service.type Service type
## @param spireIdentityExchange.spiffe.grpc.service.port port for the service
## @param spireIdentityExchange.spiffe.grpc.service.annotations Annotations for service resource
##
service:
type: ClusterIP
port: 443
annotations: {}
## @param spireIdentityExchange.spiffe.grpc.service.loadBalancerIP IP address to assign to load balancer (if supported)
loadBalancerIP: ""
ingress:
## @param spireIdentityExchange.spiffe.grpc.ingress.enabled Flag to enable ingress
enabled: false
## @param spireIdentityExchange.spiffe.grpc.ingress.className Ingress class name
className: ""
## @param spireIdentityExchange.spiffe.grpc.ingress.controllerType Specify what type of ingress controller you're using to add the necessary annotations accordingly. If blank, autodetection is attempted. If other, no annotations will be added. Must be one of [ingress-nginx, openshift, other, ""].
controllerType: ""
## @param spireIdentityExchange.spiffe.grpc.ingress.annotations [object] Annotations for ingress object
annotations: {}
## @param spireIdentityExchange.spiffe.grpc.ingress.host Host name for the ingress. If no '.' in host, trustDomain is automatically appended. Must differ from the per-side hosts.
host: "spire-identity-exchange-grpc-spiffe"
## @param spireIdentityExchange.spiffe.grpc.ingress.tlsSecret Secret that has the certs. If blank will use default certs. Used with host var.
tlsSecret: ""
## @param spireIdentityExchange.spiffe.grpc.ingress.hosts [array] Host paths for ingress object. If emtpy, rules will be built based on the host var.
hosts: []
## @param spireIdentityExchange.spiffe.grpc.ingress.tls [array] Secrets containining TLS certs to enable https on ingress. If emtpy, rules will be built based on the host and tlsSecret vars.
tls: []
## Gateway API exposure for this endpoint. Always a TLSRoute (SNI passthrough).
gatewayAPI:
## @param spireIdentityExchange.spiffe.grpc.gatewayAPI.enabled Flag to expose the endpoint via Gateway API
enabled: false
## @param spireIdentityExchange.spiffe.grpc.gatewayAPI.host Host name for the route. If no '.' in host, trustDomain is automatically appended.
host: "spire-identity-exchange-grpc-spiffe"
## @param spireIdentityExchange.spiffe.grpc.gatewayAPI.annotations [object] Annotations for the route (and its ListenerSet)
annotations: {}
listenerSet:
## @param spireIdentityExchange.spiffe.grpc.gatewayAPI.listenerSet.enabled Manage a ListenerSet for this service's SNI listener. Null inherits global.spire.gatewayAPI.manageListenerSets.
enabled: null
## @param spireIdentityExchange.spiffe.grpc.gatewayAPI.parentRefs [array] parentRefs used when ListenerSet management is disabled (direct attach)
parentRefs: []
## @param spireIdentityExchange.spiffe.grpc.gatewayAPI.sectionName Listener sectionName override when attaching directly to a Gateway
sectionName: ""
## subcharts ## subcharts
## @section Spire agent parameters ## @section Spire agent parameters
@@ -498,7 +743,7 @@ internal-spire-server-bottom-turtle-ha-a:
## @param internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.enabled Enables the spire-ha-agent identity ## @param internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.enabled Enables the spire-ha-agent identity
enabled: true enabled: true
spire-identity-exchange-service: spire-identity-exchange-service:
## @param internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.spire-identity-exchange-service.federatesWith [array] List of trust domains to federate with ## @param internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.spire-identity-exchange-service.federatesWith [array] List of trust domains to federate with
federatesWith: federatesWith:
- spire-ha - spire-ha
persistence: persistence:
@@ -580,7 +825,7 @@ internal-spire-server-bottom-turtle-ha-b:
## @param internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.enabled Enables the spire-ha-agent identity ## @param internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.enabled Enables the spire-ha-agent identity
enabled: true enabled: true
spire-identity-exchange-service: spire-identity-exchange-service:
## @param internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.spire-identity-exchange-service.federatesWith [array] List of trust domains to federate with ## @param internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.spire-identity-exchange-service.federatesWith [array] List of trust domains to federate with
federatesWith: federatesWith:
- spire-ha - spire-ha
persistence: persistence:
@@ -799,17 +1044,35 @@ spire-identity-exchange-bottom-turtle-ha-a:
nameOverride: identity-exchange nameOverride: identity-exchange
## @param spire-identity-exchange-bottom-turtle-ha-a.csiDriverName CSI driver name to use ## @param spire-identity-exchange-bottom-turtle-ha-a.csiDriverName CSI driver name to use
csiDriverName: a.csi.spiffe.io csiDriverName: a.csi.spiffe.io
tls:
rest: rest:
ingress: ingress:
## @param spire-identity-exchange-bottom-turtle-ha-a.rest.ingress.host Hostname override for the rest ingress service ## @param spire-identity-exchange-bottom-turtle-ha-a.tls.rest.ingress.host Hostname override for the rest ingress service
host: "spire-identity-exchange-a-rest" host: "spire-identity-exchange-a-rest"
grpc: grpc:
ingress: ingress:
## @param spire-identity-exchange-bottom-turtle-ha-a.grpc.ingress.host Hostname override for the rest ingress service ## @param spire-identity-exchange-bottom-turtle-ha-a.tls.grpc.ingress.host Hostname override for the grpc ingress service
host: "spire-identity-exchange-a-grpc" host: "spire-identity-exchange-a-grpc"
spiffe:
rest:
ingress:
## @param spire-identity-exchange-bottom-turtle-ha-a.spiffe.rest.ingress.host Hostname override for the SVID-served rest ingress service
host: "spire-identity-exchange-a-rest-spiffe"
grpc:
ingress:
## @param spire-identity-exchange-bottom-turtle-ha-a.spiffe.grpc.ingress.host Hostname override for the SVID-served grpc ingress service
host: "spire-identity-exchange-a-grpc-spiffe"
server: server:
## @param spire-identity-exchange-bottom-turtle-ha-a.server.nameOverride The name override setting of the internal SPIRE server ## @param spire-identity-exchange-bottom-turtle-ha-a.server.nameOverride The name override setting of the internal SPIRE server
nameOverride: internal-server nameOverride: internal-server
auth:
plugins:
spiffe:
## @param spire-identity-exchange-bottom-turtle-ha-a.auth.plugins.spiffe.csiDriverName The csi driver the spiffe plugin reads its trust bundle from. The shared ha-agent, since that is what mints the oidc discovery provider's serving svid.
csiDriverName: csi.spiffe.io
config:
## @param spire-identity-exchange-bottom-turtle-ha-a.auth.plugins.spiffe.config.discoveryURL The OIDC discovery provider to fetch keys from. This chart gives it a fullnameOverride, so the keySource convention does not apply.
discoveryURL: https://spiffe-oidc-discovery-provider
spire-identity-exchange-bottom-turtle-ha-b: spire-identity-exchange-bottom-turtle-ha-b:
## @param spire-identity-exchange-bottom-turtle-ha-b.enabled Enable the spire-identity-exchange ## @param spire-identity-exchange-bottom-turtle-ha-b.enabled Enable the spire-identity-exchange
@@ -821,11 +1084,29 @@ spire-identity-exchange-bottom-turtle-ha-b:
server: server:
## @param spire-identity-exchange-bottom-turtle-ha-b.server.nameOverride The name override setting of the internal SPIRE server ## @param spire-identity-exchange-bottom-turtle-ha-b.server.nameOverride The name override setting of the internal SPIRE server
nameOverride: internal-server nameOverride: internal-server
tls:
rest: rest:
ingress: ingress:
## @param spire-identity-exchange-bottom-turtle-ha-b.rest.ingress.host Hostname override for the rest ingress service ## @param spire-identity-exchange-bottom-turtle-ha-b.tls.rest.ingress.host Hostname override for the rest ingress service
host: "spire-identity-exchange-b-rest" host: "spire-identity-exchange-b-rest"
grpc: grpc:
ingress: ingress:
## @param spire-identity-exchange-bottom-turtle-ha-b.grpc.ingress.host Hostname override for the rest ingress service ## @param spire-identity-exchange-bottom-turtle-ha-b.tls.grpc.ingress.host Hostname override for the grpc ingress service
host: "spire-identity-exchange-b-grpc" host: "spire-identity-exchange-b-grpc"
spiffe:
rest:
ingress:
## @param spire-identity-exchange-bottom-turtle-ha-b.spiffe.rest.ingress.host Hostname override for the SVID-served rest ingress service
host: "spire-identity-exchange-b-rest-spiffe"
grpc:
ingress:
## @param spire-identity-exchange-bottom-turtle-ha-b.spiffe.grpc.ingress.host Hostname override for the SVID-served grpc ingress service
host: "spire-identity-exchange-b-grpc-spiffe"
auth:
plugins:
spiffe:
## @param spire-identity-exchange-bottom-turtle-ha-b.auth.plugins.spiffe.csiDriverName The csi driver the spiffe plugin reads its trust bundle from. The shared ha-agent, since that is what mints the oidc discovery provider's serving svid.
csiDriverName: csi.spiffe.io
config:
## @param spire-identity-exchange-bottom-turtle-ha-b.auth.plugins.spiffe.config.discoveryURL The OIDC discovery provider to fetch keys from. This chart gives it a fullnameOverride, so the keySource convention does not apply.
discoveryURL: https://spiffe-oidc-discovery-provider
@@ -36,10 +36,10 @@ spec:
i=0 i=0
while [ "$i" -lt 60 ]; do while [ "$i" -lt 60 ]; do
if XOUT=$(/opt/spire/bin/spire-agent api fetch x509 -socketPath "$SOCK" -write /data -timeout 5s 2>&1) && if XOUT=$(/opt/spire/bin/spire-agent api fetch x509 -socketPath "$SOCK" -write /data -timeout 5s 2>&1) &&
echo "$XOUT" | /data/busybox grep -q "for trust domain other.org" && echo "$XOUT" | /data/busybox grep -q "for trust domain other.invalid" &&
JOUT=$(/opt/spire/bin/spire-agent api fetch jwt -audience test -socketPath "$SOCK" -timeout 5s 2>&1) && JOUT=$(/opt/spire/bin/spire-agent api fetch jwt -audience test -socketPath "$SOCK" -timeout 5s 2>&1) &&
echo "$JOUT" | /data/busybox grep -q "bundle(other.org)"; then echo "$JOUT" | /data/busybox grep -q "bundle(other.invalid)"; then
# The other.org bundle was statically set to the same single CA on both sides, # Both sides were seeded with the same single-CA other.invalid bundle at install,
# so every federated bundle delivered must contain exactly one certificate. # so every federated bundle delivered must contain exactly one certificate.
for f in /data/federated_bundle.*.pem; do for f in /data/federated_bundle.*.pem; do
COUNT=$(/data/busybox grep -c "BEGIN CERTIFICATE" "$f") COUNT=$(/data/busybox grep -c "BEGIN CERTIFICATE" "$f")
+48 -27
View File
@@ -31,8 +31,13 @@ done
# With -b, test the spire-ha-agent broker api instead of the delegated api. # With -b, test the spire-ha-agent broker api instead of the delegated api.
# Broker mode also supports federated trust bundles, so federate the ha-agent's own entry and a # Broker mode also supports federated trust bundles, so federate the ha-agent's own entry and a
# dedicated federation-test workload entry with the other.org trust domain on both sides. Delegated # dedicated federation-test workload entry with the other.invalid trust domain on both sides. Delegated
# mode only tolerates the local and spire-ha bundles, so none of this may apply without -b. # mode only tolerates the local and spire-ha bundles, so none of this may apply without -b.
# Placeholder bundle endpoint for other.invalid. Its ClusterFederatedTrustDomain carries the bundle
# verbatim, but the CRD requires an endpoint alongside it. This name is never meant to answer, it
# just has to be ours: .invalid can never be registered, and coredns pins it to 127.0.0.1 below.
FEDERATION_ENDPOINT_HOST=spire-server-federation.other.invalid
BROKER_MODE_ARGS=() BROKER_MODE_ARGS=()
BROKER_SOCKET_ARGS_A=() BROKER_SOCKET_ARGS_A=()
BROKER_SOCKET_ARGS_B=() BROKER_SOCKET_ARGS_B=()
@@ -41,15 +46,15 @@ if [ "${BROKER}" -eq 1 ]; then
BROKER_SOCKET_ARGS_A=( BROKER_SOCKET_ARGS_A=(
--set downstream-spire-agent-bottom-turtle-ha-a.sockets.broker.enabled=true --set downstream-spire-agent-bottom-turtle-ha-a.sockets.broker.enabled=true
--set downstream-spire-agent-bottom-turtle-ha-a.sockets.broker.mountOnHost=true --set downstream-spire-agent-bottom-turtle-ha-a.sockets.broker.mountOnHost=true
--set 'internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.federatesWith={spire-ha,other.org}' --set 'internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.federatesWith={spire-ha,other.invalid}'
--set 'internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.federation-test.federatesWith={other.org}' --set 'internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.federation-test.federatesWith={other.invalid}'
--set 'internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.federation-test.podSelector.matchLabels.app=federation-test' --set 'internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterSPIFFEIDs.federation-test.podSelector.matchLabels.app=federation-test'
) )
BROKER_SOCKET_ARGS_B=( BROKER_SOCKET_ARGS_B=(
--set downstream-spire-agent-bottom-turtle-ha-b.sockets.broker.enabled=true --set downstream-spire-agent-bottom-turtle-ha-b.sockets.broker.enabled=true
--set downstream-spire-agent-bottom-turtle-ha-b.sockets.broker.mountOnHost=true --set downstream-spire-agent-bottom-turtle-ha-b.sockets.broker.mountOnHost=true
--set 'internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.federatesWith={spire-ha,other.org}' --set 'internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.spire-ha-agent.federatesWith={spire-ha,other.invalid}'
--set 'internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.federation-test.federatesWith={other.org}' --set 'internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.federation-test.federatesWith={other.invalid}'
--set 'internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.federation-test.podSelector.matchLabels.app=federation-test' --set 'internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterSPIFFEIDs.federation-test.podSelector.matchLabels.app=federation-test'
) )
fi fi
@@ -95,6 +100,7 @@ teardown() {
kubectl describe daemonset pods -n spire-system || true kubectl describe daemonset pods -n spire-system || true
kubectl get configmap -n spire-system || true kubectl get configmap -n spire-system || true
kubectl get configmap -n spire-system spire-a-agent-downstream -o yaml || true kubectl get configmap -n spire-system spire-a-agent-downstream -o yaml || true
kubectl get endpoints -n spire-server -o yaml || true
print_helm_releases print_helm_releases
@@ -204,17 +210,38 @@ if [ "${BROKER}" -eq 1 ]; then
BUSYBOX_IMAGE=$(helm template t charts/spire -s charts/spiffe-oidc-discovery-provider/templates/tests/test-keys.yaml --values "${COMMON_TEST_YOUR_VALUES}" --set spiffe-oidc-discovery-provider.enabled=true | yq e 'select(.kind=="Pod") | .spec.initContainers[] | select(.name=="static-busybox") | .image' -) BUSYBOX_IMAGE=$(helm template t charts/spire -s charts/spiffe-oidc-discovery-provider/templates/tests/test-keys.yaml --values "${COMMON_TEST_YOUR_VALUES}" --set spiffe-oidc-discovery-provider.enabled=true | yq e 'select(.kind=="Pod") | .spec.initContainers[] | select(.name=="static-busybox") | .image' -)
echo "federation test job images: ${AGENT_IMAGE} ${BUSYBOX_IMAGE}" echo "federation test job images: ${AGENT_IMAGE} ${BUSYBOX_IMAGE}"
# Mint a trust bundle for a foreign trust domain (other.org) to test federated trust bundle # Mint a trust bundle for a foreign trust domain (other.invalid) to test federated trust bundle
# support. A throwaway third spire-server instance produces a genuine spiffe format bundle # support. A throwaway third spire-server instance produces a genuine spiffe format bundle
# carrying both x509 and jwt authorities. The instance env file overrides the global trust # carrying both x509 and jwt authorities. The instance env file overrides the global trust
# domain since systemd applies later EnvironmentFiles last. # domain since systemd applies later EnvironmentFiles last.
sudo /bin/bash -c '(echo SPIFFE_TRUST_DOMAIN=other.org; echo SPIRE_BIND_PORT=8083) > /etc/spire/server/other.env' sudo /bin/bash -c '(echo SPIFFE_TRUST_DOMAIN=other.invalid; echo SPIRE_BIND_PORT=8083) > /etc/spire/server/other.env'
sudo systemctl start spire-server@other sudo systemctl start spire-server@other
wait_for_healthcheck spire-server /run/spire/server/sockets/other/private/api.sock wait_for_healthcheck spire-server /run/spire/server/sockets/other/private/api.sock
sudo spire-server bundle show -format spiffe -socketPath /run/spire/server/sockets/other/private/api.sock | sudo tee /tmp/other-org-bundle.json > /dev/null sudo spire-server bundle show -format spiffe -socketPath /run/spire/server/sockets/other/private/api.sock | sudo tee /tmp/other-invalid-bundle.json > /dev/null
sudo systemctl stop spire-server@other sudo systemctl stop spire-server@other
grep -q '"x509-svid"' /tmp/other-org-bundle.json grep -q '"x509-svid"' /tmp/other-invalid-bundle.json
grep -q '"jwt-svid"' /tmp/other-org-bundle.json grep -q '"jwt-svid"' /tmp/other-invalid-bundle.json
# Seed the bundle into each server's ClusterFederatedTrustDomain so the controller manager can
# create the entries that federate with other.invalid on its first reconcile. Loading it after
# the install instead leaves the ha-agent without an SVID for the whole helm --wait window.
# The CRD requires an endpoint even when the bundle is supplied verbatim; .invalid can never be
# registered and coredns pins the name locally, so the endpoint never answers. That is fine,
# spire keeps a federated bundle when a refresh fails.
FTD_A=internal-spire-server-bottom-turtle-ha-a.controllerManager.identities.clusterFederatedTrustDomains.other
FTD_B=internal-spire-server-bottom-turtle-ha-b.controllerManager.identities.clusterFederatedTrustDomains.other
BROKER_SOCKET_ARGS_A+=(
--set "${FTD_A}.trustDomain=other.invalid"
--set "${FTD_A}.bundleEndpointProfile.type=https_web"
--set "${FTD_A}.bundleEndpointURL=https://${FEDERATION_ENDPOINT_HOST}"
--set-file "${FTD_A}.trustDomainBundle=/tmp/other-invalid-bundle.json"
)
BROKER_SOCKET_ARGS_B+=(
--set "${FTD_B}.trustDomain=other.invalid"
--set "${FTD_B}.bundleEndpointProfile.type=https_web"
--set "${FTD_B}.bundleEndpointURL=https://${FEDERATION_ENDPOINT_HOST}"
--set-file "${FTD_B}.trustDomainBundle=/tmp/other-invalid-bundle.json"
)
fi fi
# register some workloads with the spire server using manifests # register some workloads with the spire server using manifests
@@ -305,7 +332,7 @@ common_test_url "$IP"
# Get the host IP And add spire-server-[ab].${trust_domain} records to it so the spire-servers can talk back to root servers running on the host # Get the host IP And add spire-server-[ab].${trust_domain} records to it so the spire-servers can talk back to root servers running on the host
HOSTIP=$(ip addr show docker0 | grep 'inet ' | awk '{print $2}' | cut -d/ -f1) HOSTIP=$(ip addr show docker0 | grep 'inet ' | awk '{print $2}' | cut -d/ -f1)
kubectl get configmap -n kube-system coredns -o yaml | grep hosts || kubectl get configmap -n kube-system coredns -o yaml | sed "/ready/a\ hosts {\n fallthrough\n }" | kubectl apply -f - kubectl get configmap -n kube-system coredns -o yaml | grep hosts || kubectl get configmap -n kube-system coredns -o yaml | sed "/ready/a\ hosts {\n fallthrough\n }" | kubectl apply -f -
kubectl get configmap -n kube-system coredns -o yaml | grep production.other || kubectl get configmap -n kube-system coredns -o yaml | sed "/hosts/a\ $HOSTIP spire-server-a.production.other\n $HOSTIP oidc-discovery.production.other\n $HOSTIP spire-server-b.production.other\n" | kubectl apply -f - kubectl get configmap -n kube-system coredns -o yaml | grep production.other || kubectl get configmap -n kube-system coredns -o yaml | sed "/hosts/a\ $HOSTIP spire-server-a.production.other\n $IP oidc-discovery.production.other\n $HOSTIP spire-server-b.production.other\n 127.0.0.1 $FEDERATION_ENDPOINT_HOST\n" | kubectl apply -f -
kubectl rollout restart -n kube-system deployment/coredns kubectl rollout restart -n kube-system deployment/coredns
kubectl rollout status -n kube-system -w --timeout=1m deploy/coredns kubectl rollout status -n kube-system -w --timeout=1m deploy/coredns
@@ -330,19 +357,13 @@ kubectl create secret tls -n spire-server spire-identity-exchange --key=certs/se
# Install server side a # Install server side a
helm upgrade --install --namespace spire-mgmt --values "${COMMON_TEST_YOUR_VALUES},${SCRIPTPATH}/spire-values.yaml" \ helm upgrade --install --namespace spire-mgmt --values "${COMMON_TEST_YOUR_VALUES},${SCRIPTPATH}/spire-values.yaml" \
--wait spire-a charts/spire-nested \ --wait --timeout 7m spire-a charts/spire-nested \
--set tags.bottomTurtleHAA=true \ --set tags.bottomTurtleHAA=true \
--values "${SCRIPTPATH}/spire-identity-exchange-values.yaml" \ --values "${SCRIPTPATH}/spire-identity-exchange-values.yaml" \
--set "spire-identity-exchange-bottom-turtle-ha-a.enabled=true" \ --set "spire-identity-exchange-bottom-turtle-ha-a.enabled=true" \
--set "global.spire.ingressControllerType=ingress-nginx" \ --set "global.spire.ingressControllerType=ingress-nginx" \
"${BROKER_SOCKET_ARGS_A[@]}" "${BROKER_SOCKET_ARGS_A[@]}"
if [ "${BROKER}" -eq 1 ]; then
# Install the other.org bundle so the controller manager can create the entries that federate
# with it. It retries any entries that failed with "unable to find federated bundle".
kubectl exec -i -n spire-server spire-a-internal-server-0 -- spire-server bundle set -format spiffe -id spiffe://other.org < /tmp/other-org-bundle.json
fi
docker exec -i chart-testing-worker /bin/bash -c "more /var/lib/kubelet/pods/*/volumes/kubernetes.io~empty-dir/disk-keymanager/keys.json /var/lib/kubelet/pods/*/volumes/kubernetes.io~empty-dir/spire-agent-persistence/agent-data.json | cat" docker exec -i chart-testing-worker /bin/bash -c "more /var/lib/kubelet/pods/*/volumes/kubernetes.io~empty-dir/disk-keymanager/keys.json /var/lib/kubelet/pods/*/volumes/kubernetes.io~empty-dir/spire-agent-persistence/agent-data.json | cat"
# Rollout just to sped up the tests # Rollout just to sped up the tests
@@ -356,7 +377,7 @@ curl -k --resolve "oidc-discovery.production.other:443:$IP" "https://oidc-discov
# Install server side b # Install server side b
helm upgrade --install --namespace spire-mgmt --values "${COMMON_TEST_YOUR_VALUES},${SCRIPTPATH}/spire-values.yaml" \ helm upgrade --install --namespace spire-mgmt --values "${COMMON_TEST_YOUR_VALUES},${SCRIPTPATH}/spire-values.yaml" \
--wait spire-b charts/spire-nested \ --wait --timeout 7m spire-b charts/spire-nested \
--set tags.bottomTurtleHAB=true \ --set tags.bottomTurtleHAB=true \
--set internal-spire-server-bottom-turtle-ha-b.upstreamAuthority.spire.server.port=8082 \ --set internal-spire-server-bottom-turtle-ha-b.upstreamAuthority.spire.server.port=8082 \
--values "${SCRIPTPATH}/spire-identity-exchange-values.yaml" \ --values "${SCRIPTPATH}/spire-identity-exchange-values.yaml" \
@@ -365,10 +386,10 @@ helm upgrade --install --namespace spire-mgmt --values "${COMMON_TEST_YOUR_VALUE
"${BROKER_SOCKET_ARGS_B[@]}" "${BROKER_SOCKET_ARGS_B[@]}"
if [ "${BROKER}" -eq 1 ]; then if [ "${BROKER}" -eq 1 ]; then
kubectl exec -i -n spire-server spire-b-internal-server-0 -- spire-server bundle set -format spiffe -id spiffe://other.org < /tmp/other-org-bundle.json # Both sides' spire-ha-agent entries must federate with other.invalid before the workload test.
# Both sides' spire-ha-agent entries must federate with other.org before the workload test. # The bundle came in with the install, so this should already be true rather than waited on.
wait_for_entry_federation spire-a-internal-server-0 other.org wait_for_entry_federation spire-a-internal-server-0 other.invalid
wait_for_entry_federation spire-b-internal-server-0 other.org wait_for_entry_federation spire-b-internal-server-0 other.invalid
fi fi
docker ps docker ps
@@ -398,11 +419,11 @@ curl -k --resolve "oidc-discovery.production.other:443:$IP" "https://oidc-discov
kubectl apply -f "${SCRIPTPATH}/test-job.yaml" kubectl apply -f "${SCRIPTPATH}/test-job.yaml"
kubectl wait --for=condition=complete --timeout=60s job/test && \ kubectl wait --for=condition=complete --timeout=60s job/test && \
TOKEN=$(kubectl logs job/test) TOKEN=$(kubectl logs job/test)
curl -f -H "Authorization: Bearer ${TOKEN}" -X POST --resolve "spire-identity-exchange-a-rest.production.other:443:$IP" "https://spire-identity-exchange-a-rest.production.other/api/v1/svid/k8s_psat/x509" -k -sS -q curl --fail-with-body -H "Authorization: Bearer ${TOKEN}" -X POST --resolve "spire-identity-exchange-a-rest.production.other:443:$IP" "https://spire-identity-exchange-a-rest.production.other/api/v1/svid/k8s_psat/x509" -k -sS -q
curl -f -H "Authorization: Bearer ${TOKEN}" -X POST --resolve "spire-identity-exchange-b-rest.production.other:443:$IP" "https://spire-identity-exchange-b-rest.production.other/api/v1/svid/k8s_psat/x509" -k -sS -q curl --fail-with-body -H "Authorization: Bearer ${TOKEN}" -X POST --resolve "spire-identity-exchange-b-rest.production.other:443:$IP" "https://spire-identity-exchange-b-rest.production.other/api/v1/svid/k8s_psat/x509" -k -sS -q
if [ "${BROKER}" -eq 1 ]; then if [ "${BROKER}" -eq 1 ]; then
# Verify a workload on the ha-agent socket receives the other.org federated trust bundles, # Verify a workload on the ha-agent socket receives the other.invalid federated trust bundles,
# x509 and jwt, merged from both sides. # x509 and jwt, merged from both sides.
run_federation_test_job run_federation_test_job
fi fi
@@ -416,7 +437,7 @@ kubectl rollout status deployment -n spire-server spiffe-oidc-discovery-provider
curl -k --resolve "oidc-discovery.production.other:443:$IP" "https://oidc-discovery.production.other/.well-known/openid-configuration" -s --fail curl -k --resolve "oidc-discovery.production.other:443:$IP" "https://oidc-discovery.production.other/.well-known/openid-configuration" -s --fail
if [ "${BROKER}" -eq 1 ]; then if [ "${BROKER}" -eq 1 ]; then
# Verify the other.org federated trust bundles still serve with only side b running. # Verify the other.invalid federated trust bundles still serve with only side b running.
run_federation_test_job run_federation_test_job
fi fi
@@ -1,4 +1,4 @@
internal-spire-server-bottom-turtle-ha-a: internal-spire-server-bottom-turtle-ha-a: &server
controllerManager: controllerManager:
identities: identities:
clusterStaticEntries: clusterStaticEntries:
@@ -11,49 +11,25 @@ internal-spire-server-bottom-turtle-ha-a:
spireIdentityExchange: spireIdentityExchange:
enabled: true enabled: true
internal-spire-server-bottom-turtle-ha-b: #Set the same settings on the B side
controllerManager: internal-spire-server-bottom-turtle-ha-b: *server
identities:
clusterStaticEntries:
test:
parentID: spiffe://production.other/spire-identity-exchange
spiffeID: spiffe://production.other/k8s-psat/test
selectors:
- k8s_psat:namespace:default
- k8s_psat:service_account_name:default
spireIdentityExchange:
enabled: true
spire-identity-exchange-bottom-turtle-ha-a: spire-identity-exchange-bottom-turtle-ha-a: &six
rest:
ingress:
enabled: true
tls: tls:
externalSecret: externalSecret:
enabled: true enabled: true
secretName: spire-identity-exchange secretName: spire-identity-exchange
rest:
enabled: true
ingress:
enabled: true
auth: auth:
passthroughPlugins: true
plugins: plugins:
- plugin: k8s_psat k8s_psat:
config: config:
audiences:
- spire-identity-exchange
allowedServiceAccounts: allowedServiceAccounts:
- default/default - default/default
spire-identity-exchange-bottom-turtle-ha-b: #Set the same settings on the B side
rest: spire-identity-exchange-bottom-turtle-ha-b: *six
ingress:
enabled: true
tls:
externalSecret:
enabled: true
secretName: spire-identity-exchange
auth:
plugins:
- plugin: k8s_psat
config:
audiences:
- spire-identity-exchange
allowedServiceAccounts:
- default/default