diff --git a/.github/tests/charts.json b/.github/tests/charts.json index 36ca24d..0aa00f7 100644 --- a/.github/tests/charts.json +++ b/.github/tests/charts.json @@ -2,26 +2,26 @@ { "name": "kube-prometheus-stack", "repo": "https://prometheus-community.github.io/helm-charts", - "version": "56.6.2" + "version": "56.20.0" }, { "name": "cert-manager", "repo": "https://charts.jetstack.io", - "version": "v1.14.1" + "version": "v1.14.3" }, { "name": "ingress-nginx", "repo": "https://kubernetes.github.io/ingress-nginx", - "version": "4.9.1" + "version": "4.10.0" }, { "name": "mysql", "repo": "https://charts.bitnami.com/bitnami", - "version": "9.19.1" + "version": "9.22.0" }, { "name": "postgresql", "repo": "https://charts.bitnami.com/bitnami", - "version": "14.0.1" + "version": "14.2.3" } ] diff --git a/.github/workflows/check-versions.yaml b/.github/workflows/check-versions.yaml index 433f1ce..47338ae 100644 --- a/.github/workflows/check-versions.yaml +++ b/.github/workflows/check-versions.yaml @@ -61,7 +61,7 @@ jobs: - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@v6.0.0 + uses: peter-evans/create-pull-request@v6.0.1 with: token: ${{ secrets.GITHUB_TOKEN }} title: Bump test chart dependencies diff --git a/.github/workflows/helm-chart-ci-ignore.yaml b/.github/workflows/helm-chart-ci-ignore.yaml index 2a098e3..1ba17fd 100644 --- a/.github/workflows/helm-chart-ci-ignore.yaml +++ b/.github/workflows/helm-chart-ci-ignore.yaml @@ -45,7 +45,7 @@ jobs: - name: Checkout uses: actions/checkout@v4.1.1 - - id: set-matrix + - id: set-matrix-example name: Collect all examples run: | examples="$(find examples -maxdepth 2 -type f -name run-tests.sh | xargs -I % dirname %)" @@ -53,8 +53,17 @@ jobs: echo "${examples_json}" echo "examples=$examples_json" >>"$GITHUB_OUTPUT" + - id: set-matrix-integration + name: Collect all integration tests + run: | + integrationtests="$(find tests/integration -maxdepth 2 -type f -name run-tests.sh | xargs -I % dirname %)" + integrationtests_json="$(echo "$integrationtests" | jq -c --slurp --raw-input 'split("\n") | map(select(. != ""))')" + echo "${integrationtests_json}" + echo "integrationtests=$integrationtests_json" >>"$GITHUB_OUTPUT" + outputs: - examples: ${{ steps.set-matrix.outputs.examples }} + examples: ${{ steps.set-matrix-example.outputs.examples }} + integrationtests: ${{ steps.set-matrix-integration.outputs.integrationtests }} example-test: runs-on: ubuntu-22.04 @@ -74,6 +83,24 @@ jobs: steps: - run: 'echo "Skipping example-test"' + integration-test: + runs-on: ubuntu-22.04 + + needs: + - build-matrix + + strategy: + matrix: + k8s: + - v1.28.0 + - v1.27.3 + - v1.26.6 + example: + - ${{ fromJson(needs.build-matrix.outputs.integrationtests) }} + + steps: + - run: 'echo "Skipping integration-test"' + upgrade-test: runs-on: ubuntu-22.04 diff --git a/.github/workflows/helm-chart-ci.yaml b/.github/workflows/helm-chart-ci.yaml index a0d8659..d4e3492 100644 --- a/.github/workflows/helm-chart-ci.yaml +++ b/.github/workflows/helm-chart-ci.yaml @@ -156,7 +156,7 @@ jobs: version: ${{ env.CHART_TESTING_VERSION }} - name: Create kind ${{ matrix.k8s }} cluster - uses: helm/kind-action@v1.8.0 + uses: helm/kind-action@v1.9.0 # Only build a kind cluster if there are chart changes to test. with: version: ${{ env.KIND_VERSION }} @@ -187,7 +187,7 @@ jobs: - name: Checkout uses: actions/checkout@v4.1.1 - - id: set-matrix + - id: set-matrix-example name: Collect all examples run: | examples="$(find examples -maxdepth 2 -type f -name run-tests.sh | xargs -I % dirname %)" @@ -195,8 +195,17 @@ jobs: echo "${examples_json}" echo "examples=$examples_json" >>"$GITHUB_OUTPUT" + - id: set-matrix-integration + name: Collect all integration tests + run: | + integrationtests="$(find tests/integration -maxdepth 2 -type f -name run-tests.sh | xargs -I % dirname %)" + integrationtests_json="$(echo "$integrationtests" | jq -c --slurp --raw-input 'split("\n") | map(select(. != ""))')" + echo "${integrationtests_json}" + echo "integrationtests=$integrationtests_json" >>"$GITHUB_OUTPUT" + outputs: - examples: ${{ steps.set-matrix.outputs.examples }} + examples: ${{ steps.set-matrix-example.outputs.examples }} + integrationtests: ${{ steps.set-matrix-integration.outputs.integrationtests }} example-test: runs-on: ubuntu-22.04 @@ -230,7 +239,7 @@ jobs: python-version: ${{ env.PYTHON_VERSION }} - name: Create kind cluster - uses: helm/kind-action@v1.8.0 + uses: helm/kind-action@v1.9.0 # Only build a kind cluster if there are chart changes to test. with: version: ${{ env.KIND_VERSION }} @@ -249,6 +258,52 @@ jobs: fi ${{ matrix.example }}/run-tests.sh + integration-test: + runs-on: ubuntu-22.04 + + needs: + - lint-chart + - build-matrix + + strategy: + fail-fast: false + matrix: + k8s: + - v1.28.0 + - v1.27.3 + - v1.26.6 + integrationtest: + - ${{ fromJson(needs.build-matrix.outputs.integrationtests) }} + + steps: + - name: Checkout + uses: actions/checkout@v4.1.1 + + - name: Set up Helm + uses: azure/setup-helm@v3.5 + with: + version: ${{ env.HELM_VERSION }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Create kind cluster + uses: helm/kind-action@v1.9.0 + # Only build a kind cluster if there are chart changes to test. + with: + version: ${{ env.KIND_VERSION }} + node_image: kindest/node:v1.26.4 + config: .github/kind/conf/kind-config.yaml + verbosity: 1 + + - name: Install and test integration + run: | + kubectl create namespace spire-server + helm install -n spire-server spire-crds charts/spire-crds + ${{ matrix.integrationtest }}/run-tests.sh + upgrade-test: runs-on: ubuntu-22.04 @@ -279,7 +334,7 @@ jobs: python-version: ${{ env.PYTHON_VERSION }} - name: Create kind cluster - uses: helm/kind-action@v1.8.0 + uses: helm/kind-action@v1.9.0 # Only build a kind cluster if there are chart changes to test. with: version: ${{ env.KIND_VERSION }} diff --git a/charts/spire/Chart.yaml b/charts/spire/Chart.yaml index f036385..b6d1075 100644 --- a/charts/spire/Chart.yaml +++ b/charts/spire/Chart.yaml @@ -3,8 +3,8 @@ name: spire description: > A Helm chart for deploying the complete Spire stack including: spire-server, spire-agent, spiffe-csi-driver, spiffe-oidc-discovery-provider and spire-controller-manager. type: application -version: 0.17.2 -appVersion: "1.8.7" +version: 0.18.0 +appVersion: "1.9.0" keywords: ["spiffe", "spire", "spire-server", "spire-agent", "oidc", "spire-controller-manager"] home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire sources: diff --git a/charts/spire/README.md b/charts/spire/README.md index 99861fd..c663bc5 100644 --- a/charts/spire/README.md +++ b/charts/spire/README.md @@ -1,6 +1,6 @@ # spire -![Version: 0.17.2](https://img.shields.io/badge/Version-0.17.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.8.7](https://img.shields.io/badge/AppVersion-1.8.7-informational?style=flat-square) +![Version: 0.18.0](https://img.shields.io/badge/Version-0.18.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.9.0](https://img.shields.io/badge/AppVersion-1.9.0-informational?style=flat-square) [![Development Phase](https://github.com/spiffe/spiffe/blob/main/.img/maturity/dev.svg)](https://github.com/spiffe/spiffe/blob/main/MATURITY.md#development) A Helm chart for deploying the complete Spire stack including: spire-server, spire-agent, spiffe-csi-driver, spiffe-oidc-discovery-provider and spire-controller-manager. @@ -34,12 +34,10 @@ global: # Update these clusterName: example-cluster trustDomain: example.org -spire-server: - ca_subject: - # Update these - country: ARPA - organization: Example - common_name: example.org + caSubject: + country: ARPA + organization: Example + commonName: example.org ``` 2. If you need a non default storageClass, append the following to the spire-server section and update: @@ -77,6 +75,11 @@ kubectl delete crds clusterfederatedtrustdomains.spire.spiffe.io clusterspiffeid We only support upgrading one major version at a time. Version skipping isn't supported. +### 0.18.x + +- SPIRE no longer emits x509UniqueIdentifiers in x509-SVIDS by default. The old behavior can be reenabled with spire-server.credentialComposer.uniqueID.enabled=true. See https://github.com/spiffe/spire/pull/4862 for details. +- SPIRE agents will now automatically reattest when they can. The old behavior can be reenabled with spire-agent.disableReattestToRenew=true. See https://github.com/spiffe/spire/pull/4791 for details. + ### 0.17.X - If you set spire-server.replicaCount > 1, update it to 1 before upgrading and after upgrade you can set it back to its previous value. @@ -209,6 +212,9 @@ Now you can interact with the Spire agent socket from your own application. The | `global.spire.jwtIssuer` | The issuer for Spire JWT tokens. Defaults to oidc-discovery.$trustDomain if unset | `""` | | `global.spire.trustDomain` | The trust domain for Spire install | `example.org` | | `global.spire.upstreamServerAddress` | Set what address to use for the upstream server when using nested spire | `""` | +| `global.spire.caSubject.country` | Country for Spire server CA | `""` | +| `global.spire.caSubject.organization` | Organization for Spire server CA | `""` | +| `global.spire.caSubject.commonName` | Common Name for Spire server CA | `""` | | `global.spire.recommendations.enabled` | Use recommended settings for production deployments. Default is off. | `false` | | `global.spire.recommendations.namespaceLayout` | Set to true to use recommended values for installing across namespaces | `true` | | `global.spire.recommendations.namespacePSS` | When chart namespace creation is enabled, label them with preffered Pod Security Standard labels | `true` | @@ -228,6 +234,7 @@ 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.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.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.deleteHooks.enabled` | Enable Helm hooks to autofix common delete issues (should be disabled when using `helm template`) | `true` | diff --git a/charts/spire/charts/spiffe-csi-driver/README.md b/charts/spire/charts/spiffe-csi-driver/README.md index 92322dd..f527f9d 100644 --- a/charts/spire/charts/spiffe-csi-driver/README.md +++ b/charts/spire/charts/spiffe-csi-driver/README.md @@ -25,47 +25,50 @@ A Helm chart to install the SPIFFE CSI driver. ### SPIFFE CSI Driver Chart parameters -| Name | Description | Value | -| ---------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -| `pluginName` | Set the csi driver name deployed to Kubernetes. | `csi.spiffe.io` | -| `image.registry` | The OCI registry to pull the image from | `ghcr.io` | -| `image.repository` | The repository within the registry | `spiffe/spiffe-csi-driver` | -| `image.pullPolicy` | The image pull policy | `IfNotPresent` | -| `image.tag` | Overrides the image tag whose default is the chart appVersion | `""` | -| `resources` | Resource requests and limits for spiffe-csi-driver | `{}` | -| `healthChecks.port` | The healthcheck port for spiffe-csi-driver | `9809` | -| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | -| `livenessProbe.timeoutSeconds` | Timeout value in seconds for livenessProbe | `5` | -| `imagePullSecrets` | Image pull secret details for spiffe-csi-driver | `[]` | -| `nameOverride` | Name override for spiffe-csi-driver | `""` | -| `namespaceOverride` | Namespace to install spiffe-csi-driver | `""` | -| `fullnameOverride` | Full name override for spiffe-csi-driver | `""` | -| `csiDriverLabels` | Labels to apply to the CSIDriver | `{}` | -| `initContainers` | Init Containers to apply to the CSI Driver DaemonSet | `[]` | -| `serviceAccount.create` | Specifies whether a service account should be created | `true` | -| `serviceAccount.annotations` | Annotations to add to the service account | `{}` | -| `serviceAccount.name` | The name of the service account to use. If not set and create is true, a name is generated. | `""` | -| `podAnnotations` | Pod annotations for spiffe-csi-driver | `{}` | -| `podSecurityContext` | Security context for CSI driver pods | `{}` | -| `securityContext.readOnlyRootFilesystem` | Flag for read only root filesystem | `true` | -| `securityContext.privileged` | Flag for specifying privileged mode | `true` | -| `nodeSelector` | Node selector for CSI driver pods | `{}` | -| `tolerations` | Tolerations for CSI driver pods | `[]` | -| `affinity` | Node affinity | `{}` | -| `nodeDriverRegistrar.image.registry` | The OCI registry to pull the image from | `registry.k8s.io` | -| `nodeDriverRegistrar.image.repository` | The repository within the registry | `sig-storage/csi-node-driver-registrar` | -| `nodeDriverRegistrar.image.pullPolicy` | The image pull policy | `IfNotPresent` | -| `nodeDriverRegistrar.image.tag` | Overrides the image tag | `v2.9.3` | -| `nodeDriverRegistrar.resources` | Resource requests and limits for CSI driver pods | `{}` | -| `agentSocketPath` | The unix socket path to the spire-agent | `/run/spire/agent-sockets/spire-agent.sock` | -| `kubeletPath` | Path to kubelet file | `/var/lib/kubelet` | -| `priorityClassName` | Priority class assigned to daemonset pods. Can be auto set with global.recommendations.priorityClassName. | `""` | -| `restrictedScc.enabled` | Enables the creation of a SecurityContextConstraint based on the restricted SCC with CSI volume support | `false` | -| `restrictedScc.name` | Set the name of the restricted SCC with CSI support | `""` | -| `restrictedScc.version` | Version of the restricted SCC | `2` | -| `selinux.enabled` | Enable selinux support | `false` | -| `selinux.context` | Which selinux context to use | `container_file_t` | -| `selinux.image.registry` | The OCI registry to pull the image from | `registry.access.redhat.com` | -| `selinux.image.repository` | The repository within the registry | `ubi9` | -| `selinux.image.pullPolicy` | The image pull policy | `Always` | -| `selinux.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest` | +| Name | Description | Value | +| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | +| `pluginName` | Set the csi driver name deployed to Kubernetes. | `csi.spiffe.io` | +| `image.registry` | The OCI registry to pull the image from | `ghcr.io` | +| `image.repository` | The repository within the registry | `spiffe/spiffe-csi-driver` | +| `image.pullPolicy` | The image pull policy | `IfNotPresent` | +| `image.tag` | Overrides the image tag whose default is the chart appVersion | `""` | +| `resources` | Resource requests and limits for spiffe-csi-driver | `{}` | +| `healthChecks.port` | The healthcheck port for spiffe-csi-driver | `9809` | +| `updateStrategy.type` | The update strategy to use to replace existing DaemonSet pods with new pods. Can be RollingUpdate or OnDelete. | `RollingUpdate` | +| `updateStrategy.rollingUpdate.maxUnavailable` | Max unavailable pods during update. Can be a number or a percentage. | `1` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `livenessProbe.timeoutSeconds` | Timeout value in seconds for livenessProbe | `5` | +| `imagePullSecrets` | Image pull secret details for spiffe-csi-driver | `[]` | +| `nameOverride` | Name override for spiffe-csi-driver | `""` | +| `namespaceOverride` | Namespace to install spiffe-csi-driver | `""` | +| `fullnameOverride` | Full name override for spiffe-csi-driver | `""` | +| `csiDriverLabels` | Labels to apply to the CSIDriver | `{}` | +| `initContainers` | Init Containers to apply to the CSI Driver DaemonSet | `[]` | +| `serviceAccount.create` | Specifies whether a service account should be created | `true` | +| `serviceAccount.annotations` | Annotations to add to the service account | `{}` | +| `serviceAccount.name` | The name of the service account to use. If not set and create is true, a name is generated. | `""` | +| `podAnnotations` | Pod annotations for spiffe-csi-driver | `{}` | +| `podSecurityContext` | Security context for CSI driver pods | `{}` | +| `securityContext.readOnlyRootFilesystem` | Flag for read only root filesystem | `true` | +| `securityContext.privileged` | Flag for specifying privileged mode | `true` | +| `nodeSelector` | Node selector for CSI driver pods | `{}` | +| `tolerations` | Tolerations for CSI driver pods | `[]` | +| `affinity` | Node affinity | `{}` | +| `nodeDriverRegistrar.image.registry` | The OCI registry to pull the image from | `registry.k8s.io` | +| `nodeDriverRegistrar.image.repository` | The repository within the registry | `sig-storage/csi-node-driver-registrar` | +| `nodeDriverRegistrar.image.pullPolicy` | The image pull policy | `IfNotPresent` | +| `nodeDriverRegistrar.image.tag` | Overrides the image tag | `v2.9.3` | +| `nodeDriverRegistrar.resources` | Resource requests and limits for CSI driver pods | `{}` | +| `agentSocketPath` | The unix socket path to the spire-agent | `/run/spire/agent-sockets/spire-agent.sock` | +| `kubeletPath` | Path to kubelet file | `/var/lib/kubelet` | +| `priorityClassName` | Priority class assigned to daemonset pods. Can be auto set with global.recommendations.priorityClassName. | `""` | +| `restrictedScc.enabled` | Enables the creation of a SecurityContextConstraint based on the restricted SCC with CSI volume support | `false` | +| `restrictedScc.name` | Set the name of the restricted SCC with CSI support | `""` | +| `restrictedScc.version` | Version of the restricted SCC | `2` | +| `selinux.enabled` | Enable selinux support | `false` | +| `selinux.context` | Which selinux context to use | `container_file_t` | +| `selinux.image.registry` | The OCI registry to pull the image from | `registry.access.redhat.com` | +| `selinux.image.repository` | The repository within the registry | `ubi9` | +| `selinux.image.pullPolicy` | The image pull policy | `Always` | +| `selinux.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest` | + diff --git a/charts/spire/charts/spiffe-csi-driver/templates/daemonset.yaml b/charts/spire/charts/spiffe-csi-driver/templates/daemonset.yaml index 3044ac4..754d900 100644 --- a/charts/spire/charts/spiffe-csi-driver/templates/daemonset.yaml +++ b/charts/spire/charts/spiffe-csi-driver/templates/daemonset.yaml @@ -9,8 +9,17 @@ spec: selector: matchLabels: {{- include "spiffe-csi-driver.selectorLabels" . | nindent 6 }} + {{- with .Values.updateStrategy }} updateStrategy: - type: RollingUpdate + {{- if not (has .type (list "RollingUpdate" "OnDelete")) }} + {{- fail "updateStrategy.type can only be RollingUpdate or OnDelete"}} + {{- end }} + type: {{ .type }} + {{- if eq .type "RollingUpdate" }} + rollingUpdate: + maxUnavailable: {{ .rollingUpdate.maxUnavailable }} + {{- end }} + {{- end }} template: metadata: {{- with .Values.podAnnotations }} diff --git a/charts/spire/charts/spiffe-csi-driver/values.yaml b/charts/spire/charts/spiffe-csi-driver/values.yaml index 4f1afaf..a1ebe65 100644 --- a/charts/spire/charts/spiffe-csi-driver/values.yaml +++ b/charts/spire/charts/spiffe-csi-driver/values.yaml @@ -37,6 +37,13 @@ healthChecks: ## @param healthChecks.port The healthcheck port for spiffe-csi-driver port: 9809 +## @param updateStrategy.type The update strategy to use to replace existing DaemonSet pods with new pods. Can be RollingUpdate or OnDelete. +## @param updateStrategy.rollingUpdate.maxUnavailable Max unavailable pods during update. Can be a number or a percentage. +updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + ## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe ## @param livenessProbe.timeoutSeconds Timeout value in seconds for livenessProbe ## diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/Chart.yaml b/charts/spire/charts/spiffe-oidc-discovery-provider/Chart.yaml index 3f29481..98f430e 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/Chart.yaml +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/Chart.yaml @@ -3,7 +3,7 @@ name: spiffe-oidc-discovery-provider description: A Helm chart to install the SPIFFE OIDC discovery provider. type: application version: 0.1.0 -appVersion: "1.8.7" +appVersion: "1.9.0" keywords: ["spiffe", "oidc"] home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire sources: diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/README.md b/charts/spire/charts/spiffe-oidc-discovery-provider/README.md index a78314c..0dc9cd0 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/README.md +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/README.md @@ -69,7 +69,7 @@ A Helm chart to install the SPIFFE OIDC discovery provider. | `insecureScheme.nginx.image.registry` | The OCI registry to pull the image from. Only used when TLS is disabled. | `docker.io` | | `insecureScheme.nginx.image.repository` | The repository within the registry. Only used when TLS is disabled. | `nginxinc/nginx-unprivileged` | | `insecureScheme.nginx.image.pullPolicy` | The image pull policy. Only used when TLS is disabled. | `IfNotPresent` | -| `insecureScheme.nginx.image.tag` | Overrides the image tag whose default is the chart appVersion. Only used when TLS is disabled. | `1.25.3-alpine` | +| `insecureScheme.nginx.image.tag` | Overrides the image tag whose default is the chart appVersion. Only used when TLS is disabled. | `1.25.4-alpine` | | `insecureScheme.nginx.resources` | Resource requests and limits | `{}` | | `jwtIssuer` | Path to JWT issuer. Defaults to oidc-discovery.$trustDomain if unset | `""` | | `config.logLevel` | The log level, valid values are "debug", "info", "warn", and "error" | `info` | @@ -115,11 +115,11 @@ A Helm chart to install the SPIFFE OIDC discovery provider. | `tests.bash.image.registry` | The OCI registry to pull the image from | `cgr.dev` | | `tests.bash.image.repository` | The repository within the registry | `chainguard/bash` | | `tests.bash.image.pullPolicy` | The image pull policy | `IfNotPresent` | -| `tests.bash.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:1b4e8389d2582d0b013fad55d7ad799a67bbdcbfbae0a053258ae24c8b03a19f` | +| `tests.bash.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669` | | `tests.toolkit.image.registry` | The OCI registry to pull the image from | `cgr.dev` | | `tests.toolkit.image.repository` | The repository within the registry | `chainguard/slim-toolkit-debug` | | `tests.toolkit.image.pullPolicy` | The image pull policy | `IfNotPresent` | -| `tests.toolkit.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:9198d9e7e83ab4078df6f53dfa3e8e1e8f60d5718cc21fefa2ccb6604283e049` | +| `tests.toolkit.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:606810cf1076a226dfb85fa4102ee0ed2d8e2b7c7a8a2a53f9788c65501ecca8` | | `tests.step.image.registry` | The OCI registry to pull the image from | `docker.io` | | `tests.step.image.repository` | The repository within the registry | `smallstep/step-cli` | | `tests.step.image.pullPolicy` | The image pull policy | `IfNotPresent` | diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/values.yaml b/charts/spire/charts/spiffe-oidc-discovery-provider/values.yaml index 6df7829..a7dfd10 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/values.yaml +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/values.yaml @@ -164,7 +164,7 @@ insecureScheme: registry: docker.io repository: nginxinc/nginx-unprivileged pullPolicy: IfNotPresent - tag: 1.25.3-alpine + tag: 1.25.4-alpine ## @param insecureScheme.nginx.resources Resource requests and limits resources: {} # We usually recommend not to specify default resources and to leave this as a conscious @@ -328,7 +328,7 @@ tests: registry: cgr.dev repository: chainguard/bash pullPolicy: IfNotPresent - tag: latest@sha256:1b4e8389d2582d0b013fad55d7ad799a67bbdcbfbae0a053258ae24c8b03a19f + tag: latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669 toolkit: ## @param tests.toolkit.image.registry The OCI registry to pull the image from @@ -340,7 +340,7 @@ tests: registry: cgr.dev repository: chainguard/slim-toolkit-debug pullPolicy: IfNotPresent - tag: latest@sha256:9198d9e7e83ab4078df6f53dfa3e8e1e8f60d5718cc21fefa2ccb6604283e049 + tag: latest@sha256:606810cf1076a226dfb85fa4102ee0ed2d8e2b7c7a8a2a53f9788c65501ecca8 step: ## @param tests.step.image.registry The OCI registry to pull the image from diff --git a/charts/spire/charts/spire-agent/Chart.yaml b/charts/spire/charts/spire-agent/Chart.yaml index 1fc821a..6082f02 100644 --- a/charts/spire/charts/spire-agent/Chart.yaml +++ b/charts/spire/charts/spire-agent/Chart.yaml @@ -3,7 +3,7 @@ name: spire-agent description: A Helm chart to install the SPIRE agent. type: application version: 0.1.0 -appVersion: "1.8.7" +appVersion: "1.9.0" keywords: ["spiffe", "spire-agent"] home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire sources: diff --git a/charts/spire/charts/spire-agent/README.md b/charts/spire/charts/spire-agent/README.md index c059bcf..c4b10d2 100644 --- a/charts/spire/charts/spire-agent/README.md +++ b/charts/spire/charts/spire-agent/README.md @@ -40,12 +40,14 @@ A Helm chart to install the SPIRE agent. | `serviceAccount.name` | The name of the service account to use. | `""` | | `configMap.annotations` | Annotations to add to the SPIRE Agent ConfigMap | `{}` | | `podAnnotations` | Annotations to add to pods | `{}` | +| `podLabels` | Labels to add to pods | `{}` | | `podSecurityContext` | Pod security context | `{}` | | `securityContext` | Security context | `{}` | | `resources` | Resource requests and limits | `{}` | | `nodeSelector` | Node selector | `{}` | | `tolerations` | List of tolerations | `[]` | | `affinity` | Node affinity | `{}` | +| `authorizedDelegates` | A list of the authorized delegates SPIFFE IDs. See Delegated Identity API for more information. | `[]` | | `logLevel` | The log level, valid values are "debug", "info", "warn", and "error" | `info` | | `clusterName` | The name of the Kubernetes cluster (`kubeadm init --service-dns-domain`) | `example-cluster` | | `trustDomain` | The trust domain to be used for the SPIFFE identifiers | `example.org` | @@ -53,10 +55,13 @@ A Helm chart to install the SPIRE agent. | `trustBundleFormat` | If using trustBundleURL, what format is the url. Choices are "pem" and "spiffe" | `pem` | | `bundleConfigMap` | Configmap name for Spire bundle | `spire-bundle` | | `availabilityTarget` | The minimum amount of time desired to gracefully handle SPIRE Server or Agent downtime. This configurable influences how aggressively X509 SVIDs should be rotated. If set, must be at least 24h. | `""` | +| `disableReattestToRenew` | Deprecated: Allow agent to renew certificate when it expires rather than reattest | `false` | | `server.address` | Address for Spire server | `""` | | `server.port` | Port number for Spire server | `8081` | | `server.namespaceOverride` | Override the namespace for Spire server | `""` | | `healthChecks.port` | override the host port used for health checking | `9982` | +| `updateStrategy.type` | The update strategy to use to replace existing DaemonSet pods with new pods. Can be RollingUpdate or OnDelete. | `RollingUpdate` | +| `updateStrategy.rollingUpdate.maxUnavailable` | Max unavailable pods during update. Can be a number or a percentage. | `1` | | `livenessProbe.initialDelaySeconds` | Initial delay seconds for probe | `15` | | `livenessProbe.periodSeconds` | Period seconds for probe | `60` | | `readinessProbe.initialDelaySeconds` | Initial delay seconds for probe | `10` | @@ -64,15 +69,27 @@ A Helm chart to install the SPIRE agent. | `waitForIt.image.registry` | The OCI registry to pull the image from | `cgr.dev` | | `waitForIt.image.repository` | The repository within the registry | `chainguard/wait-for-it` | | `waitForIt.image.pullPolicy` | The image pull policy | `IfNotPresent` | -| `waitForIt.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:64ba1b49313924643dec6a03e15a1c6cfc24046cff96b0b3c0003cabbad2f60d` | +| `waitForIt.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:caead414307e81dbdd86d30662fdfe1b999dd4ce8a10fa667dab3438d0eed193` | | `waitForIt.resources` | Resource requests and limits | `{}` | | `fsGroupFix.image.registry` | The OCI registry to pull the image from | `cgr.dev` | | `fsGroupFix.image.repository` | The repository within the registry | `chainguard/bash` | | `fsGroupFix.image.pullPolicy` | The image pull policy | `Always` | -| `fsGroupFix.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:1b4e8389d2582d0b013fad55d7ad799a67bbdcbfbae0a053258ae24c8b03a19f` | +| `fsGroupFix.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669` | | `fsGroupFix.resources` | Specify resource needs as per https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | `{}` | | `keyManager.memory.enabled` | Enable the memory based Key Manager | `true` | | `nodeAttestor.k8sPsat.enabled` | Enable Psat k8s Node Attestor | `true` | +| `nodeAttestor.tpmDirect.enabled` | Enable the direct TPM node attestor, a 3rd party plugin by Boxboat. This plugin is experimental. | `false` | +| `nodeAttestor.tpmDirect.plugin.image.registry` | The OCI registry to pull the image from | `docker.io` | +| `nodeAttestor.tpmDirect.plugin.image.repository` | The repository within the registry | `boxboat/spire-tpm-plugin-tpm-attestor-agent` | +| `nodeAttestor.tpmDirect.plugin.image.pullPolicy` | The image pull policy | `IfNotPresent` | +| `nodeAttestor.tpmDirect.plugin.image.tag` | Overrides the image tag | `v1.8.7` | +| `nodeAttestor.tpmDirect.plugin.checksum` | The sha256 checksum of the plugin binary | `1d7c73ccac948ee86cbd78ddde2d30128a1838b403f7bb2100d38d916a252244` | +| `nodeAttestor.tpmDirect.plugin.path` | The filename in the container of the plugin | `/app/tpm_attestor_agent` | +| `nodeAttestor.tpmDirect.pubHash.enabled` | Enable Psat k8s nodeattestor | `true` | +| `nodeAttestor.tpmDirect.pubHash.image.registry` | The OCI registry to pull the image from | `docker.io` | +| `nodeAttestor.tpmDirect.pubHash.image.repository` | The repository within the registry | `boxboat/spire-tpm-plugin-get-tpm-pubhash` | +| `nodeAttestor.tpmDirect.pubHash.image.pullPolicy` | The image pull policy | `IfNotPresent` | +| `nodeAttestor.tpmDirect.pubHash.image.tag` | Overrides the image tag | `v1.8.7` | | `workloadAttestors.unix.enabled` | Enables the Unix workload attestor | `false` | | `workloadAttestors.k8s.enabled` | Enables the Kubernetes workload attestor | `true` | | `workloadAttestors.k8s.skipKubeletVerification` | If true, kubelet certificate verification is skipped | `true` | @@ -93,7 +110,7 @@ A Helm chart to install the SPIRE agent. | `socketAlternate.image.registry` | The OCI registry to pull the image from | `cgr.dev` | | `socketAlternate.image.repository` | The repository within the registry | `chainguard/bash` | | `socketAlternate.image.pullPolicy` | The image pull policy | `Always` | -| `socketAlternate.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:07d2662ef699e9ceafab3f39624083193dfcb7b768ee86860dbdd5cb4473dcea` | +| `socketAlternate.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669` | | `socketAlternate.resources` | Specify resource needs as per https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | `{}` | | `priorityClassName` | Priority class assigned to daemonset pods. Can be auto set with global.recommendations.priorityClassName. | `""` | | `extraEnvVars` | Extra environment variables to be added to the Spire Agent container | `[]` | @@ -109,3 +126,6 @@ A Helm chart to install the SPIRE agent. | `experimental.enabled` | Allow configuration of experimental features | `false` | | `experimental.syncInterval` | Sync interval with SPIRE server with exponential backoff | `5s` | | `experimental.featureFlags` | List of developer feature flags | `[]` | +| `sockets.hostBasePath` | Path on which the agent socket is made available when admin.mountOnHost is true | `/run/spire/agent/sockets` | +| `sockets.admin.enabled` | Enable the admin socket. Useful for admin tasks or the Delegated Identity API. | `false` | +| `sockets.admin.mountOnHost` | Enable the admin socket to be visible on the host. | `false` | diff --git a/charts/spire/charts/spire-agent/templates/configmap.yaml b/charts/spire/charts/spire-agent/templates/configmap.yaml index 1270be6..1fb312b 100644 --- a/charts/spire/charts/spire-agent/templates/configmap.yaml +++ b/charts/spire/charts/spire-agent/templates/configmap.yaml @@ -18,8 +18,21 @@ {{- end }} {{- end }} {{- end }} +{{- if hasPrefix (.Values.socketPath | dir | clean) (.Values.sockets.hostBasePath | clean) }} +{{- fail "The sockets.hostBasePath can not be located under the socketPath direcotry" }} +{{- end }} {{- define "spire-agent.yaml-config" -}} agent: + {{- if .Values.disableReattestToRenew }} + disable_reattest_to_renew: true + {{- end }} + {{- if .Values.sockets.admin.enabled }} + admin_socket_dir: /tmp/spire-agent/private/admin.sock + {{- end }} + {{- with .Values.authorizedDelegates }} + authorized_delegates: + {{- toYaml . | nindent 4 }} + {{- end }} data_dir: "/run/spire" log_level: {{ .Values.logLevel | quote }} server_address: {{ include "spire-agent.server-address" . | trim | quote }} @@ -66,6 +79,15 @@ plugins: cluster: {{ include "spire-lib.cluster-name" . | quote }} {{- $nodeAttestorUsed = add1 $nodeAttestorUsed }} {{- end }} + {{- with .Values.nodeAttestor.tpmDirect }} + {{- if eq (.enabled | toString) "true" }} + tpm: + plugin_cmd: "/tpm/tpm_attestor_agent" + plugin_checksum: {{ .plugin.checksum }} + plugin_data: {} + {{- $nodeAttestorUsed = add1 $nodeAttestorUsed }} + {{- end }} + {{- end }} {{- if ne $nodeAttestorUsed 1 }} {{- fail (printf "You have to enable exactly one Node Attestor. There are %d enabled." $nodeAttestorUsed) }} {{- end }} diff --git a/charts/spire/charts/spire-agent/templates/daemonset.yaml b/charts/spire/charts/spire-agent/templates/daemonset.yaml index 279f56c..4e23f28 100644 --- a/charts/spire/charts/spire-agent/templates/daemonset.yaml +++ b/charts/spire/charts/spire-agent/templates/daemonset.yaml @@ -1,5 +1,10 @@ {{- $configSum := (include (print $.Template.BasePath "/configmap.yaml") . | sha256sum) }} {{- $podSecurityContext := fromYaml (include "spire-lib.podsecuritycontext" .) }} +{{- $mainSecurityContext := deepCopy .Values.securityContext }} +{{- if .Values.nodeAttestor.tpmDirect.enabled }} +{{- $podSecurityContext = mergeOverwrite (dict "runAsUser" 0 "runAsGroup" 0) .Values.podSecurityContext }} +{{- $_ := set $mainSecurityContext "privileged" true }} +{{- end }} {{- $cbh := eq (include "spire-agent.connect-by-hostname" .) "true" }} {{- $socketAlternateNames := index (include "spire-agent.socket-alternate-names" . | fromYaml) "names" }} {{- $socketPath := include "spire-agent.socket-path" . }} @@ -14,6 +19,17 @@ spec: selector: matchLabels: {{- include "spire-agent.selectorLabels" . | nindent 6 }} + {{- with .Values.updateStrategy }} + updateStrategy: + {{- if not (has .type (list "RollingUpdate" "OnDelete")) }} + {{- fail "updateStrategy.type can only be RollingUpdate or OnDelete"}} + {{- end }} + type: {{ .type }} + {{- if eq .type "RollingUpdate" }} + rollingUpdate: + maxUnavailable: {{ .rollingUpdate.maxUnavailable }} + {{- end }} + {{- end }} template: metadata: annotations: @@ -24,6 +40,9 @@ spec: {{- end }} labels: {{- include "spire-agent.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: @@ -41,6 +60,47 @@ spec: {{- toYaml .Values.hostAliases | nindent 8 }} {{- end }} initContainers: + {{- if .Values.nodeAttestor.tpmDirect.enabled }} + {{- if .Values.nodeAttestor.tpmDirect.pubHash.enabled }} + - name: fingerprint-tpm + securityContext: + {{- $mainSecurityContext | toYaml | nindent 12 }} + image: {{ template "spire-lib.image" (dict "appVersion" $.Chart.AppVersion "image" .Values.nodeAttestor.tpmDirect.pubHash.image "global" .Values.global) }} + command: + - sh + - -c + - | + # Fetch the TPM's fingerprint from the TPM and output it on the Computers Console. This enables secure bootstrapping of the Node with the Server. + TPM=`/app/get_tpm_pubhash 2> /dev/null` + if [ $? -eq 0 ]; then + echo "TPM Fingerprint: $TPM" + (echo -n '<1>'; echo "TPM Fingerprint: $TPM") | tee /dev/kmsg + else + /app/get_tpm_pubhash + fi + volumeMounts: + - name: tpm + mountPath: /dev/tpmrm0 + readOnly: true + - name: kmsg + mountPath: /dev/kmsg + imagePullPolicy: {{ .Values.nodeAttestor.tpmDirect.pubHash.image.pullPolicy }} + {{- end }} + - name: init-tpm-direct + securityContext: + {{- .Values.securityContext | toYaml | nindent 12 }} + image: {{ template "spire-lib.image" (dict "appVersion" $.Chart.AppVersion "image" .Values.nodeAttestor.tpmDirect.plugin.image "global" .Values.global) }} + command: + - sh + - -ec + - | + # SPIRE must be able to fork the plugin directly within its container. Copy the plugin into a volume that can be mounted where SPIRE can execute it. + cp -a {{ .Values.nodeAttestor.tpmDirect.plugin.path }} /tpm/tpm_attestor_agent + volumeMounts: + - name: tpm-direct + mountPath: /tpm + imagePullPolicy: {{ .Values.nodeAttestor.tpmDirect.plugin.image.pullPolicy }} + {{- end }} - name: init # This is a small image with wait-for-it, choose whatever image # you prefer that waits for a service to be up. This image is built @@ -48,16 +108,18 @@ spec: image: {{ template "spire-lib.image" (dict "image" .Values.waitForIt.image "global" .Values.global) }} imagePullPolicy: {{ .Values.waitForIt.image.pullPolicy }} args: ["-t", "30", "-h", "{{ include "spire-agent.server-address" . | trim }}", "-p", {{ .Values.server.port | quote }}] + securityContext: + {{- .Values.securityContext | toYaml | nindent 12 }} resources: {{- toYaml .Values.waitForIt.resources | nindent 12 }} securityContext: - {{ toYaml .Values.securityContext | nindent 12 }} + {{- toYaml .Values.securityContext | nindent 12 }} {{- if gt (len $socketAlternateNames) 0 }} - name: ensure-alternate-names image: {{ template "spire-lib.image" (dict "image" .Values.socketAlternate.image "global" .Values.global) }} imagePullPolicy: {{ .Values.socketAlternate.image.pullPolicy }} command: ["bash", "-xc"] - {{/* 1. Look for symlinks pointing at the wrong place and remove them. 2. Make symlinks that don't exist. 3. If new socket is pointing at an existing symlink, remove old symlink. */}} + {{- /* 1. Look for symlinks pointing at the wrong place and remove them. 2. Make symlinks that don't exist. 3. If new socket is pointing at an existing symlink, remove old symlink. */}} args: - | cd {{ $socketPath | dir }} @@ -83,12 +145,14 @@ spec: imagePullPolicy: {{ .Values.fsGroupFix.image.pullPolicy }} command: ["bash", "-c"] args: - - "chown -R {{ $podSecurityContext.runAsUser }}:{{ $podSecurityContext.fsGroup }} {{ $socketPath | dir }}" + - "chown -R {{ $podSecurityContext.runAsUser }}:{{ $podSecurityContext.fsGroup }} {{ $socketPath | dir }} /tmp/spire-agent/private" resources: {{- toYaml .Values.fsGroupFix.resources | nindent 12 }} volumeMounts: - name: spire-agent-socket-dir mountPath: {{ $socketPath | dir }} + - name: spire-agent-admin-socket-dir + mountPath: /tmp/spire-agent/private securityContext: runAsUser: 0 runAsGroup: 0 @@ -102,7 +166,7 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} args: ["-config", "/opt/spire/conf/agent/agent.conf"] securityContext: - {{ toYaml .Values.securityContext | nindent 12 }} + {{- $mainSecurityContext | toYaml | nindent 12 }} env: - name: PATH value: "/opt/spire/bin:/bin" @@ -126,11 +190,24 @@ spec: - name: spire-config mountPath: /opt/spire/conf/agent readOnly: true + {{- if .Values.sockets.admin.enabled }} + - name: spire-agent-admin-socket-dir + mountPath: /tmp/spire-agent/private + readOnly: false + {{- end }} {{- if eq (len .Values.trustBundleURL) 0 }} - name: spire-bundle mountPath: /run/spire/bundle readOnly: true {{- end }} + {{- if .Values.nodeAttestor.tpmDirect.enabled }} + - name: tpm-direct + mountPath: /tpm + readOnly: true + - name: tpm + mountPath: /dev/tpmrm0 + readOnly: true + {{- end }} - name: spire-agent-socket-dir mountPath: /tmp/spire-agent/public readOnly: false @@ -170,11 +247,24 @@ spec: - name: spire-config configMap: name: {{ include "spire-agent.fullname" . }} + {{- if .Values.sockets.admin.mountOnHost }} + - name: spire-agent-admin-socket-dir + hostPath: + hostPath: {{ .Values.sockets.hostBasePath }}/{{ if .Values.upstream }}upstream.csi.spiffe.io{{ else }}csi.spiffe.io{{ end }}/admin + type: DirectoryOrCreate + {{- else }} + - name: spire-agent-admin-socket-dir + emptyDir: {} + {{- end }} {{- if eq (len .Values.trustBundleURL) 0 }} - name: spire-bundle configMap: name: {{ include "spire-lib.bundle-configmap" . }} {{- end }} + {{- if .Values.nodeAttestor.tpmDirect.enabled }} + - name: tpm-direct + emptyDir: {} + {{- end }} - name: spire-token projected: sources: @@ -186,6 +276,16 @@ spec: hostPath: path: {{ $socketPath | dir }} type: DirectoryOrCreate + {{- if .Values.nodeAttestor.tpmDirect.enabled }} + - name: tpm + hostPath: + path: /dev/tpmrm0 + type: CharDevice + - name: kmsg + hostPath: + path: /dev/kmsg + type: CharDevice + {{- end }} {{- if gt (len .Values.extraVolumes) 0 }} {{- toYaml .Values.extraVolumes | nindent 8 }} {{- end }} diff --git a/charts/spire/charts/spire-agent/templates/scc-spire-agent.yaml b/charts/spire/charts/spire-agent/templates/scc-spire-agent.yaml index b92549b..d43b4fe 100644 --- a/charts/spire/charts/spire-agent/templates/scc-spire-agent.yaml +++ b/charts/spire/charts/spire-agent/templates/scc-spire-agent.yaml @@ -17,6 +17,7 @@ volumes: - hostPath - projected - secret + - emptyDir allowHostDirVolumePlugin: true allowHostIPC: true allowHostNetwork: true diff --git a/charts/spire/charts/spire-agent/values.yaml b/charts/spire/charts/spire-agent/values.yaml index b2be153..b0ddd5b 100644 --- a/charts/spire/charts/spire-agent/values.yaml +++ b/charts/spire/charts/spire-agent/values.yaml @@ -45,6 +45,9 @@ configMap: ## @param podAnnotations [object] Annotations to add to pods podAnnotations: {} +## @param podLabels [object] Labels to add to pods +podLabels: {} + ## @param podSecurityContext [object] Pod security context podSecurityContext: {} # fsGroup: 2000 @@ -80,6 +83,8 @@ tolerations: [] ## @param affinity [object] Node affinity affinity: {} +## @param authorizedDelegates A list of the authorized delegates SPIFFE IDs. See Delegated Identity API for more information. +authorizedDelegates: [] ## @param logLevel The log level, valid values are "debug", "info", "warn", and "error" logLevel: info ## @param clusterName The name of the Kubernetes cluster (`kubeadm init --service-dns-domain`) @@ -95,6 +100,9 @@ bundleConfigMap: spire-bundle ## @param availabilityTarget The minimum amount of time desired to gracefully handle SPIRE Server or Agent downtime. This configurable influences how aggressively X509 SVIDs should be rotated. If set, must be at least 24h. availabilityTarget: "" +## @param disableReattestToRenew Deprecated: Allow agent to renew certificate when it expires rather than reattest +disableReattestToRenew: false + ## @skip upstream upstream: false @@ -111,6 +119,13 @@ healthChecks: ## @param healthChecks.port override the host port used for health checking port: 9982 +## @param updateStrategy.type The update strategy to use to replace existing DaemonSet pods with new pods. Can be RollingUpdate or OnDelete. +## @param updateStrategy.rollingUpdate.maxUnavailable Max unavailable pods during update. Can be a number or a percentage. +updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + ## @param livenessProbe.initialDelaySeconds Initial delay seconds for probe ## @param livenessProbe.periodSeconds Period seconds for probe ## @@ -135,7 +150,7 @@ waitForIt: registry: cgr.dev repository: chainguard/wait-for-it pullPolicy: IfNotPresent - tag: latest@sha256:64ba1b49313924643dec6a03e15a1c6cfc24046cff96b0b3c0003cabbad2f60d + tag: latest@sha256:caead414307e81dbdd86d30662fdfe1b999dd4ce8a10fa667dab3438d0eed193 ## @param waitForIt.resources [object] Resource requests and limits resources: {} @@ -152,7 +167,7 @@ fsGroupFix: registry: cgr.dev repository: chainguard/bash pullPolicy: Always - tag: latest@sha256:1b4e8389d2582d0b013fad55d7ad799a67bbdcbfbae0a053258ae24c8b03a19f + tag: latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669 ## @param fsGroupFix.resources Specify resource needs as per https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources: {} @@ -166,6 +181,37 @@ nodeAttestor: k8sPsat: ## @param nodeAttestor.k8sPsat.enabled Enable Psat k8s Node Attestor enabled: true + tpmDirect: + ## @param nodeAttestor.tpmDirect.enabled Enable the direct TPM node attestor, a 3rd party plugin by Boxboat. This plugin is experimental. + enabled: false + plugin: + ## @param nodeAttestor.tpmDirect.plugin.image.registry The OCI registry to pull the image from + ## @param nodeAttestor.tpmDirect.plugin.image.repository The repository within the registry + ## @param nodeAttestor.tpmDirect.plugin.image.pullPolicy The image pull policy + ## @param nodeAttestor.tpmDirect.plugin.image.tag Overrides the image tag + ## + image: + registry: docker.io + repository: boxboat/spire-tpm-plugin-tpm-attestor-agent + pullPolicy: IfNotPresent + tag: "v1.8.7" + ## @param nodeAttestor.tpmDirect.plugin.checksum The sha256 checksum of the plugin binary + checksum: 1d7c73ccac948ee86cbd78ddde2d30128a1838b403f7bb2100d38d916a252244 + ## @param nodeAttestor.tpmDirect.plugin.path The filename in the container of the plugin + path: /app/tpm_attestor_agent + pubHash: + ## @param nodeAttestor.tpmDirect.pubHash.enabled Enable Psat k8s nodeattestor + enabled: true + ## @param nodeAttestor.tpmDirect.pubHash.image.registry The OCI registry to pull the image from + ## @param nodeAttestor.tpmDirect.pubHash.image.repository The repository within the registry + ## @param nodeAttestor.tpmDirect.pubHash.image.pullPolicy The image pull policy + ## @param nodeAttestor.tpmDirect.pubHash.image.tag Overrides the image tag + ## + image: + registry: docker.io + repository: boxboat/spire-tpm-plugin-get-tpm-pubhash + pullPolicy: IfNotPresent + tag: "v1.8.7" # workloadAttestors determine a workload's properties and then generate a set of selectors associated with it. workloadAttestors: @@ -229,7 +275,7 @@ socketAlternate: registry: cgr.dev repository: chainguard/bash pullPolicy: Always - tag: latest@sha256:07d2662ef699e9ceafab3f39624083193dfcb7b768ee86860dbdd5cb4473dcea + tag: latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669 ## @param socketAlternate.resources Specify resource needs as per https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources: {} @@ -281,3 +327,12 @@ experimental: syncInterval: 5s ## @param experimental.featureFlags [array] List of developer feature flags featureFlags: [] + +sockets: + ## @param sockets.hostBasePath Path on which the agent socket is made available when admin.mountOnHost is true + hostBasePath: /run/spire/agent/sockets + ## @param sockets.admin.enabled Enable the admin socket. Useful for admin tasks or the Delegated Identity API. + ## @param sockets.admin.mountOnHost Enable the admin socket to be visible on the host. + admin: + enabled: false + mountOnHost: false diff --git a/charts/spire/charts/spire-server/Chart.yaml b/charts/spire/charts/spire-server/Chart.yaml index 2118144..f992a29 100644 --- a/charts/spire/charts/spire-server/Chart.yaml +++ b/charts/spire/charts/spire-server/Chart.yaml @@ -3,7 +3,7 @@ name: spire-server description: A Helm chart to install the SPIRE server. type: application version: 0.1.0 -appVersion: "1.8.7" +appVersion: "1.9.0" keywords: ["spiffe", "spire-server", "spire-controller-manager"] home: https://github.com/spiffe/helm-charts-hardened/tree/main/charts/spire sources: diff --git a/charts/spire/charts/spire-server/README.md b/charts/spire/charts/spire-server/README.md index 7cafb56..64b0e02 100644 --- a/charts/spire/charts/spire-server/README.md +++ b/charts/spire/charts/spire-server/README.md @@ -95,6 +95,7 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr | `serviceAccount.annotations` | Annotations to add to the service account | `{}` | | `serviceAccount.name` | The name of the service account to use. If not set and create is true, a name is generated. | `""` | | `podAnnotations` | Annotations to add to pods | `{}` | +| `podLabels` | Labels to add to pods | `{}` | | `podSecurityContext` | Pod security context | `{}` | | `securityContext` | Security context | `{}` | | `priorityClassName` | Priority class assigned to statefulset pods. Can be auto set with global.recommendations.priorityClassName. | `""` | @@ -133,6 +134,8 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr | `dataStore.sql.externalSecret.enabled` | Enable external secret for datastore creds | `false` | | `dataStore.sql.externalSecret.name` | The name of the secret object | `""` | | `dataStore.sql.externalSecret.key` | The key of the secret object whose value is the dataStore.sql password | `""` | +| `adminIDs` | SPIFFE IDs that, when present in a caller’s X509-SVID, grant that caller admin privileges. | `[]` | +| `auditLogEnabled` | If true, enables audit logging | `false` | | `logLevel` | The log level, valid values are "debug", "info", "warn", and "error" | `info` | | `jwtIssuer` | The JWT issuer domain. Defaults to oidc-discovery.$trustDomain if unset | `""` | | `clusterName` | Set the name of the Kubernetes cluster. (`kubeadm init --service-dns-domain`) | `example-cluster` | @@ -165,6 +168,7 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr | `ca_subject.country` | Country for Spire server CA | `ARPA` | | `ca_subject.organization` | Organization for Spire server CA | `Example` | | `ca_subject.common_name` | Common Name for Spire server CA | `example.org` | +| `credentialComposer.uniqueID.enabled` | Add the x509UniqueIdentifier attribute to workload X509-SVIDs | `false` | | `keyManager.disk.enabled` | Flag to enable keyManager on disk | `true` | | `keyManager.memory.enabled` | Flag to enable keyManager in memory | `false` | | `keyManager.awsKMS.enabled` | Flag to enable keyManager in memory | `false` | @@ -231,7 +235,7 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr | `controllerManager.image.registry` | The OCI registry to pull the image from | `ghcr.io` | | `controllerManager.image.repository` | The repository within the registry | `spiffe/spire-controller-manager` | | `controllerManager.image.pullPolicy` | The image pull policy | `IfNotPresent` | -| `controllerManager.image.tag` | Overrides the image tag whose default is the chart appVersion | `0.4.2` | +| `controllerManager.image.tag` | Overrides the image tag whose default is the chart appVersion | `0.4.3` | | `controllerManager.resources` | Resource requests and limits for controller manager | `{}` | | `controllerManager.securityContext` | Security context | `{}` | | `controllerManager.service.type` | Service type for controller manager | `ClusterIP` | @@ -239,6 +243,9 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr | `controllerManager.service.annotations` | Annotations for service resource | `{}` | | `controllerManager.configMap.annotations` | Annotations to add to the Controller Manager ConfigMap | `{}` | | `controllerManager.ignoreNamespaces` | These namespaces are ignored by controller manager | `[]` | +| `controllerManager.reconcile.clusterSPIFFEIDs` | Enable reconciliation of clusterSPIFFEIDs from K8s to the SPIRE server | `true` | +| `controllerManager.reconcile.clusterStaticEntries` | Enable reconciliation of clusterStaticEntries from K8s to the SPIRE server | `true` | +| `controllerManager.reconcile.clusterFederatedTrustDomains` | Enable reconciliation of clusterFederatedTrustDomains from K8s to the SPIRE server | `true` | | `controllerManager.identities.clusterSPIFFEIDs.default.enabled` | Enable this identity for controller manager | `true` | | `controllerManager.identities.clusterSPIFFEIDs.default.spiffeIDTemplate` | Spiffe ID template for identities | `spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}` | | `controllerManager.identities.clusterSPIFFEIDs.default.podSelector` | Selector for pods to issue identity | `{}` | @@ -290,6 +297,15 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr | `nodeAttestor.k8sPsat.enabled` | Enable Psat k8s nodeattestor | `true` | | `nodeAttestor.k8sPsat.serviceAccountAllowList` | Allowed service accounts for Psat nodeattestor | `[]` | | `nodeAttestor.joinToken.enabled` | Enable the join_token nodeattestor | `false` | +| `nodeAttestor.tpmDirect.enabled` | Enable the direct TPM node attestor, a 3rd party plugin by Boxboat. This plugin is experimental. | `false` | +| `nodeAttestor.tpmDirect.image.registry` | The OCI registry to pull the image from | `docker.io` | +| `nodeAttestor.tpmDirect.image.repository` | The repository within the registry | `boxboat/spire-tpm-plugin-tpm-attestor-server` | +| `nodeAttestor.tpmDirect.image.pullPolicy` | The image pull policy | `IfNotPresent` | +| `nodeAttestor.tpmDirect.image.tag` | Overrides the image tag | `v1.8.7` | +| `nodeAttestor.tpmDirect.checksum` | The sha256 checksum of the plugin binary | `f39ef9cdd2b3dd74112bfe827b79d6721c59215d0d5f4c2e34fa09bbc60d36d2` | +| `nodeAttestor.tpmDirect.pluginPath` | The filename in the container of the plugin | `/app/tpm_attestor_server` | +| `nodeAttestor.tpmDirect.cas` | A dictionary of TPM CA PEM or DER files that are allowed to connect. | `{}` | +| `nodeAttestor.tpmDirect.hashes` | A list of TPM hashes that are allowed to connect. | `[]` | ### Tornjak @@ -327,6 +343,7 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr | `tornjak.resources` | Resource requests and limits | `{}` | | `tornjak.securityContext` | Security Context to use | `{}` | | `customPlugins.bundlePublisher` | Custom plugins of type BundlePublisher are configured here | `{}` | +| `customPlugins.credentialComposer` | Custom plugins of type CredentialComposer are configured here | `{}` | | `customPlugins.keyManager` | Custom plugins of type KeyManager are configured here | `{}` | | `customPlugins.nodeAttestor` | Custom plugins of type NodeAttestor are configured here | `{}` | | `customPlugins.upstreamAuthority` | Custom plugins of type upstreamAuthority are configured here | `{}` | @@ -340,4 +357,4 @@ In order to run Tornjak with simple HTTP Connection only, make sure you don't cr | `tests.bash.image.registry` | The OCI registry to pull the image from | `cgr.dev` | | `tests.bash.image.repository` | The repository within the registry | `chainguard/bash` | | `tests.bash.image.pullPolicy` | The image pull policy | `IfNotPresent` | -| `tests.bash.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:1b4e8389d2582d0b013fad55d7ad799a67bbdcbfbae0a053258ae24c8b03a19f` | +| `tests.bash.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669` | diff --git a/charts/spire/charts/spire-server/templates/_helpers.tpl b/charts/spire/charts/spire-server/templates/_helpers.tpl index d2ecb39..cd81b6a 100644 --- a/charts/spire/charts/spire-server/templates/_helpers.tpl +++ b/charts/spire/charts/spire-server/templates/_helpers.tpl @@ -264,3 +264,18 @@ The code below determines what connection type should be used. {{- .Release.Namespace }}-{{ default .Release.Name .Values.crNameOverride }} {{- end -}} {{- end -}} + +{{- define "spire-server.ca-subject-country" }} +{{- $g := dig "spire" "caSubject" "country" "" .Values.global }} +{{- default .Values.ca_subject.country $g }} +{{- end }} + +{{- define "spire-server.ca-subject-organization" }} +{{- $g := dig "spire" "caSubject" "organization" "" .Values.global }} +{{- default .Values.ca_subject.organization $g }} +{{- end }} + +{{- define "spire-server.ca-subject-common-name" }} +{{- $g := dig "spire" "caSubject" "commonName" "" .Values.global }} +{{- default .Values.ca_subject.common_name $g }} +{{- end }} diff --git a/charts/spire/charts/spire-server/templates/configmap.yaml b/charts/spire/charts/spire-server/templates/configmap.yaml index 37e369b..db81491 100644 --- a/charts/spire/charts/spire-server/templates/configmap.yaml +++ b/charts/spire/charts/spire-server/templates/configmap.yaml @@ -1,11 +1,11 @@ {{- include "spire-lib.check-strict-mode" (list . "clusterName must be set" (eq (include "spire-lib.cluster-name" .) "example-cluster"))}} {{- include "spire-lib.check-strict-mode" (list . "trustDomain must be set" (eq (include "spire-lib.trust-domain" .) "example.org"))}} {{- include "spire-lib.check-strict-mode" (list . "jwtIssuer must be set" (eq (include "spire-lib.jwt-issuer" .) "https://oidc-discovery.example.org"))}} -{{- include "spire-lib.check-strict-mode" (list . "ca_subject.county must be set" (eq .Values.ca_subject.country "ARPA"))}} -{{- include "spire-lib.check-strict-mode" (list . "ca_subject.organization must be set" (eq .Values.ca_subject.organization "Example"))}} -{{- include "spire-lib.check-strict-mode" (list . "ca_subject.common_name must be set" (eq .Values.ca_subject.common_name "example.org"))}} +{{- include "spire-lib.check-strict-mode" (list . "ca_subject.county must be set" (eq (include "spire-server.ca-subject-country" .) "ARPA"))}} +{{- include "spire-lib.check-strict-mode" (list . "ca_subject.organization must be set" (eq (include "spire-server.ca-subject-organization" .) "Example"))}} +{{- include "spire-lib.check-strict-mode" (list . "ca_subject.common_name must be set" (eq (include "spire-server.ca-subject-common-name" .) "example.org"))}} {{- range $type, $tvals := .Values.customPlugins }} -{{- if not (has $type (list "bundlePublisher" "keyManager" "nodeAttestor" "upstreamAuthority" "notifier")) }} +{{- if not (has $type (list "bundlePublisher" "credentialComposer" "keyManager" "nodeAttestor" "upstreamAuthority" "notifier")) }} {{- fail (printf "Unknown plugin type specified: %s" $type) }} {{- end }} {{- range $name, $nval := $tvals }} @@ -40,12 +40,17 @@ {{- $keyManagerUsed := 0 }} {{- $root := . }} server: +{{- with .Values.adminIDs }} + admin_ids: + {{- toYaml . | nindent 4}} +{{- end }} bind_address: "0.0.0.0" bind_port: "8081" trust_domain: {{ include "spire-lib.trust-domain" . | quote }} data_dir: "/run/spire/data" log_level: {{ .Values.logLevel | quote }} jwt_issuer: {{ include "spire-lib.jwt-issuer" . | quote }} + audit_log_enabled: {{ .Values.auditLogEnabled }} ca_key_type: {{ .Values.caKeyType | quote }} ca_ttl: {{ .Values.caTTL | quote }} @@ -54,11 +59,9 @@ server: default_jwt_svid_ttl: {{ .Values.defaultJwtSvidTTL | quote }} ca_subject: - {{- with .Values.ca_subject }} - - country: [{{ .country | quote }}] - organization: [{{ .organization | quote }}] - common_name: {{ .common_name | quote }} - {{- end }} + - country: [{{ include "spire-server.ca-subject-country" . | quote }}] + organization: [{{ include "spire-server.ca-subject-organization" . | quote }}] + common_name: {{ include "spire-server.ca-subject-common-name" . | quote }} {{- with .Values.federation }} {{- if eq (.enabled | toString) "true" }} @@ -82,12 +85,17 @@ server: {{- end }} plugins: + {{- if .Values.credentialComposer.uniqueID.enabled }} + CredentialComposer: + uniqueid: {} + {{- end }} + DataStore: sql: plugin_data: {{ include "spire-server.datastore-config" . | nindent 10 }} - {{- if or .Values.nodeAttestor.k8sPsat.enabled .Values.nodeAttestor.joinToken.enabled }} + {{- if or .Values.nodeAttestor.k8sPsat.enabled .Values.nodeAttestor.joinToken.enabled .Values.nodeAttestor.tpmDirect.enabled }} NodeAttestor: {{- with .Values.nodeAttestor.k8sPsat }} {{- if eq (.enabled | toString) "true" }} @@ -104,6 +112,24 @@ plugins: plugin_data: {} {{- end }} {{- end }} + {{- with .Values.nodeAttestor.tpmDirect }} + {{- if eq (.enabled | toString) "true" }} + tpm: + plugin_cmd: "/tpm/tpm_attestor_server" + plugin_checksum: {{ .checksum }} + plugin_data: + {{- if ne (len .cas) 0 }} + ca_path: /tpm-direct-cas + {{- else }} + ca_path: /run/spire/data/tpm-direct/certs + {{- end }} + {{- if ne (len .hashes) 0 }} + hash_path: /tmp-direct-hashes + {{- else }} + hash_path: /run/spire/data/tpm-direct/hashes + {{- end }} + {{- end }} + {{- end }} {{- end }} {{- with .Values.keyManager.disk }} diff --git a/charts/spire/charts/spire-server/templates/controller-manager-configmap.yaml b/charts/spire/charts/spire-server/templates/controller-manager-configmap.yaml index 6cba49c..e5abd92 100644 --- a/charts/spire/charts/spire-server/templates/controller-manager-configmap.yaml +++ b/charts/spire/charts/spire-server/templates/controller-manager-configmap.yaml @@ -42,4 +42,8 @@ data: className: {{ include "spire-server.controller-manager-class-name" . | quote}} watchClassless: {{ .Values.controllerManager.watchClassless | toYaml }} parentIDTemplate: {{ .Values.controllerManager.parentIDTemplate | quote }} + {{- with .Values.reconcile }} + reconcile: + {{- toYaml . | nindent 6 }} + {{- end }} {{- end }} diff --git a/charts/spire/charts/spire-server/templates/federation-ingress.yaml b/charts/spire/charts/spire-server/templates/federation-ingress.yaml index c61bb88..2eb8979 100644 --- a/charts/spire/charts/spire-server/templates/federation-ingress.yaml +++ b/charts/spire/charts/spire-server/templates/federation-ingress.yaml @@ -1,6 +1,9 @@ {{- if .Values.federation.enabled }} {{- if .Values.federation.ingress.enabled -}} {{- $svcName := include "spire-server.fullname" . }} +{{- $path := "/"}} +{{- $pathType := "Prefix" }} +{{- $tlsSection := true }} {{/* Until https://github.com/spiffe/spire/issues/2202 is resolved, use ingress to implement cert-manager and externalSecret support. */}} {{- $federationIngress := deepCopy .Values.federation.ingress }} {{- if .Values.federation.tls.certManager.enabled }} @@ -11,7 +14,6 @@ {{- $_ := set $federationIngress "tlsSecret" .Values.federation.tls.externalSecret.secretName }} {{- end }} {{- $ingressControllerType := include "spire-lib.ingress-controller-type" (dict "global" .Values.global "ingress" .Values.federation.ingress) }} -{{- $tlsSection := true }} {{- $annotations := deepCopy .Values.federation.ingress.annotations }} {{- if eq $ingressControllerType "ingress-nginx" }} {{- $_ := set $annotations "nginx.ingress.kubernetes.io/ssl-redirect" "true" }} @@ -42,6 +44,6 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - {{ include "spire-lib.ingress-spec" (dict "ingress" $federationIngress "svcName" $svcName "port" .Values.federation.bundleEndpoint.port "path" "/" "pathType" "Prefix" "tlsSection" $tlsSection "Values" .Values) | nindent 2 }} + {{ include "spire-lib.ingress-spec" (dict "ingress" $federationIngress "svcName" $svcName "port" .Values.federation.bundleEndpoint.port "path" $path "pathType" $pathType "tlsSection" $tlsSection "Values" .Values) | nindent 2 }} {{- end }} {{- end }} diff --git a/charts/spire/charts/spire-server/templates/statefulset.yaml b/charts/spire/charts/spire-server/templates/statefulset.yaml index a792e82..47f073a 100644 --- a/charts/spire/charts/spire-server/templates/statefulset.yaml +++ b/charts/spire/charts/spire-server/templates/statefulset.yaml @@ -43,6 +43,9 @@ spec: component: server release: {{ .Release.Name }} release-namespace: {{ .Release.Namespace }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: @@ -53,8 +56,28 @@ spec: securityContext: {{- include "spire-lib.podsecuritycontext" . | nindent 8 }} {{- include "spire-lib.default_cluster_priority_class_name" . | nindent 6 }} - {{- if or (gt (len .Values.initContainers) 0) (and .Values.upstreamAuthority.certManager.enabled .Values.upstreamAuthority.certManager.ca.create) }} + {{- if or (gt (len .Values.initContainers) 0) (and .Values.upstreamAuthority.certManager.enabled .Values.upstreamAuthority.certManager.ca.create) .Values.nodeAttestor.tpmDirect.enabled }} initContainers: + {{- if .Values.nodeAttestor.tpmDirect.enabled }} + - name: init-tpm-direct + securityContext: + {{- include "spire-lib.securitycontext" . | nindent 12 }} + image: {{ template "spire-lib.image" (dict "appVersion" $.Chart.AppVersion "image" .Values.nodeAttestor.tpmDirect.image "global" .Values.global) }} + command: + - sh + - -ec + - | + # SPIRE must be able to fork the plugin directly within its container. Copy the plugin into a volume that can be mounted where SPIRE can execute it. + cp -a {{ .Values.nodeAttestor.tpmDirect.pluginPath }} /tpm/tpm_attestor_server + mkdir -p /run/spire/data/tpm-direct/certs + mkdir -p /run/spire/data/tpm-direct/hashes + volumeMounts: + - name: tpm-direct + mountPath: /tpm + - name: spire-data + mountPath: /run/spire/data + imagePullPolicy: {{ .Values.nodeAttestor.tpmDirect.image.pullPolicy }} + {{- end }} {{- if and .Values.upstreamAuthority.certManager.enabled .Values.upstreamAuthority.certManager.ca.create }} - name: wait securityContext: @@ -158,6 +181,19 @@ spec: - name: spire-data mountPath: /run/spire/data readOnly: false + {{- if .Values.nodeAttestor.tpmDirect.enabled }} + - name: tpm-direct + mountPath: /tpm + readOnly: true + {{- if ne (len .Values.nodeAttestor.tpmDirect.cas) 0 }} + - name: tpm-direct-cas + mountPath: /tpm-direct-cas + {{- end }} + {{- if ne (len .Values.nodeAttestor.tpmDirect.hashes) 0 }} + - name: tpm-direct-hashes + mountPath: /tmp-direct-hashes + {{- end }} + {{- end }} {{- if eq (.Values.upstreamAuthority.disk.enabled | toString) "true" }} - name: upstream-ca mountPath: /run/spire/upstream_ca @@ -191,6 +227,9 @@ spec: {{- if gt (len .Values.extraVolumeMounts) 0 }} {{- toYaml .Values.extraVolumeMounts | nindent 12 }} {{- end }} + - name: server-tmp + mountPath: /tmp + readOnly: false {{- if eq (.Values.controllerManager.enabled | toString) "true" }} - name: spire-controller-manager securityContext: @@ -314,6 +353,8 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} volumes: + - name: server-tmp + emptyDir: {} - name: spire-config configMap: name: {{ include "spire-server.fullname" . }} @@ -321,6 +362,20 @@ spec: emptyDir: {} - name: spire-controller-manager-tmp emptyDir: {} + {{- if .Values.nodeAttestor.tpmDirect.enabled }} + - name: tpm-direct + emptyDir: {} + {{- if ne (len .Values.nodeAttestor.tpmDirect.cas) 0 }} + - name: tpm-direct-cas + configMap: + name: {{ include "spire-server.fullname" . }}-tpm-direct-ca + {{- end }} + {{- if ne (len .Values.nodeAttestor.tpmDirect.hashes) 0 }} + - name: tpm-direct-hashes + configMap: + name: {{ include "spire-server.fullname" . }}-tpm-direct-hash + {{- end }} + {{- end }} {{- if or (eq (include "spire-tornjak.connectionType" .) "tls") (eq (include "spire-tornjak.connectionType" .) "mtls") }} - name: server-cert secret: diff --git a/charts/spire/charts/spire-server/templates/tpm-configmap.yaml b/charts/spire/charts/spire-server/templates/tpm-configmap.yaml new file mode 100644 index 0000000..fab38b6 --- /dev/null +++ b/charts/spire/charts/spire-server/templates/tpm-configmap.yaml @@ -0,0 +1,24 @@ +{{- if ne (len .Values.nodeAttestor.tpmDirect.cas) 0 }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "spire-server.fullname" . }}-tpm-direct-ca + namespace: {{ include "spire-server.namespace" . }} +data: + {{- range $key, $value := .Values.nodeAttestor.tpmDirect.cas }} + {{ $key }}: | + {{ $value | nindent 4 }} + {{- end }} +{{- end }} +--- +{{- if ne (len .Values.nodeAttestor.tpmDirect.hashes) 0 }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "spire-server.fullname" . }}-tpm-direct-hash + namespace: {{ include "spire-server.namespace" . }} +data: + {{- range .Values.nodeAttestor.tpmDirect.hashes }} + {{ . }}: "" + {{- end }} +{{- end }} diff --git a/charts/spire/charts/spire-server/values.yaml b/charts/spire/charts/spire-server/values.yaml index d254eab..2029082 100644 --- a/charts/spire/charts/spire-server/values.yaml +++ b/charts/spire/charts/spire-server/values.yaml @@ -47,6 +47,9 @@ serviceAccount: ## @param podAnnotations [object] Annotations to add to pods podAnnotations: {} +## @param podLabels [object] Labels to add to pods +podLabels: {} + ## @param podSecurityContext [object] Pod security context podSecurityContext: {} # fsGroup: 2000 @@ -173,6 +176,10 @@ dataStore: ## @param dataStore.sql.externalSecret.key The key of the secret object whose value is the dataStore.sql password key: "" +## @param adminIDs SPIFFE IDs that, when present in a caller’s X509-SVID, grant that caller admin privileges. +adminIDs: [] +## @param auditLogEnabled If true, enables audit logging +auditLogEnabled: false ## @param logLevel The log level, valid values are "debug", "info", "warn", and "error" logLevel: info ## @param jwtIssuer The JWT issuer domain. Defaults to oidc-discovery.$trustDomain if unset @@ -280,6 +287,11 @@ ca_subject: ## @param ca_subject.common_name Common Name for Spire server CA common_name: example.org +credentialComposer: + uniqueID: + ## @param credentialComposer.uniqueID.enabled Add the x509UniqueIdentifier attribute to workload X509-SVIDs + enabled: false + keyManager: disk: ## @param keyManager.disk.enabled Flag to enable keyManager on disk @@ -448,7 +460,7 @@ controllerManager: registry: ghcr.io repository: spiffe/spire-controller-manager pullPolicy: IfNotPresent - tag: "0.4.2" + tag: "0.4.3" ## @param controllerManager.resources [object] Resource requests and limits for controller manager resources: {} @@ -491,6 +503,13 @@ controllerManager: - kube-public - local-path-storage + ## @param controllerManager.reconcile.clusterSPIFFEIDs Enable reconciliation of clusterSPIFFEIDs from K8s to the SPIRE server + ## @param controllerManager.reconcile.clusterStaticEntries Enable reconciliation of clusterStaticEntries from K8s to the SPIRE server + ## @param controllerManager.reconcile.clusterFederatedTrustDomains Enable reconciliation of clusterFederatedTrustDomains from K8s to the SPIRE server + reconcile: + clusterSPIFFEIDs: true + clusterStaticEntries: true + clusterFederatedTrustDomains: true identities: clusterSPIFFEIDs: # NOTE you can add multiple uniquely named entries to create multiple ClusterSPIFFEID objects. See example below. @@ -684,6 +703,27 @@ nodeAttestor: joinToken: ## @param nodeAttestor.joinToken.enabled Enable the join_token nodeattestor enabled: false + tpmDirect: + ## @param nodeAttestor.tpmDirect.enabled Enable the direct TPM node attestor, a 3rd party plugin by Boxboat. This plugin is experimental. + enabled: false + ## @param nodeAttestor.tpmDirect.image.registry The OCI registry to pull the image from + ## @param nodeAttestor.tpmDirect.image.repository The repository within the registry + ## @param nodeAttestor.tpmDirect.image.pullPolicy The image pull policy + ## @param nodeAttestor.tpmDirect.image.tag Overrides the image tag + ## + image: + registry: docker.io + repository: boxboat/spire-tpm-plugin-tpm-attestor-server + pullPolicy: IfNotPresent + tag: "v1.8.7" + ## @param nodeAttestor.tpmDirect.checksum The sha256 checksum of the plugin binary + checksum: f39ef9cdd2b3dd74112bfe827b79d6721c59215d0d5f4c2e34fa09bbc60d36d2 + ## @param nodeAttestor.tpmDirect.pluginPath The filename in the container of the plugin + pluginPath: /app/tpm_attestor_server + ## @param nodeAttestor.tpmDirect.cas A dictionary of TPM CA PEM or DER files that are allowed to connect. + cas: {} + ## @param nodeAttestor.tpmDirect.hashes A list of TPM hashes that are allowed to connect. + hashes: [] ## @section Tornjak tornjak: @@ -800,18 +840,21 @@ tornjak: ## @skip unsupportedBuiltInPlugins unsupportedBuiltInPlugins: bundlePublisher: {} + credentialComposer: {} keyManager: {} nodeAttestor: {} upstreamAuthority: {} notifier: {} ## @param customPlugins.bundlePublisher Custom plugins of type BundlePublisher are configured here +## @param customPlugins.credentialComposer Custom plugins of type CredentialComposer are configured here ## @param customPlugins.keyManager Custom plugins of type KeyManager are configured here ## @param customPlugins.nodeAttestor Custom plugins of type NodeAttestor are configured here ## @param customPlugins.upstreamAuthority Custom plugins of type upstreamAuthority are configured here ## @param customPlugins.notifier Custom plugins of type notifier are configured here customPlugins: bundlePublisher: {} + credentialComposer: {} keyManager: {} nodeAttestor: {} upstreamAuthority: {} @@ -843,4 +886,4 @@ tests: registry: cgr.dev repository: chainguard/bash pullPolicy: IfNotPresent - tag: latest@sha256:1b4e8389d2582d0b013fad55d7ad799a67bbdcbfbae0a053258ae24c8b03a19f + tag: latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669 diff --git a/charts/spire/charts/tornjak-frontend/README.md b/charts/spire/charts/tornjak-frontend/README.md index b59cda8..94e61ea 100644 --- a/charts/spire/charts/tornjak-frontend/README.md +++ b/charts/spire/charts/tornjak-frontend/README.md @@ -98,4 +98,4 @@ port forwarding. See the chart NOTES output for more details. | `tests.bash.image.registry` | The OCI registry to pull the image from | `cgr.dev` | | `tests.bash.image.repository` | The repository within the registry | `chainguard/bash` | | `tests.bash.image.pullPolicy` | The image pull policy | `IfNotPresent` | -| `tests.bash.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:1b4e8389d2582d0b013fad55d7ad799a67bbdcbfbae0a053258ae24c8b03a19f` | +| `tests.bash.image.tag` | Overrides the image tag whose default is the chart appVersion | `latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669` | diff --git a/charts/spire/charts/tornjak-frontend/values.yaml b/charts/spire/charts/tornjak-frontend/values.yaml index d4100fc..7e16f95 100644 --- a/charts/spire/charts/tornjak-frontend/values.yaml +++ b/charts/spire/charts/tornjak-frontend/values.yaml @@ -154,4 +154,4 @@ tests: registry: cgr.dev repository: chainguard/bash pullPolicy: IfNotPresent - tag: latest@sha256:1b4e8389d2582d0b013fad55d7ad799a67bbdcbfbae0a053258ae24c8b03a19f + tag: latest@sha256:81f0b434b297453ff101de0b5f4f5cd8d4af1c015a1d34162e9ae9a4a9f38669 diff --git a/charts/spire/templates/_spire-lib.tpl b/charts/spire/templates/_spire-lib.tpl index 5ecde0a..239efc1 100644 --- a/charts/spire/templates/_spire-lib.tpl +++ b/charts/spire/templates/_spire-lib.tpl @@ -168,12 +168,16 @@ rules: {{- end }} {{- define "spire-lib.kubectl-image" }} -{{- $root := deepCopy . }} -{{- $tag := $root.image.tag | toString }} -{{- if eq (len $tag) 0 }} -{{- $_ := set $root.image "tag" (regexReplaceAll "^(v?\\d+\\.\\d+\\.\\d+).*" $root.KubeVersion "${1}") }} -{{- end }} -{{- include "spire-lib.image" $root }} +{{- $root := deepCopy . }} +{{- $tag := $root.image.tag | toString }} +{{- if eq (len $tag) 0 }} +{{- if dig "spire" "tools" "kubectl" "tag" "" $root.global }} +{{- $_ := set $root.image "tag" $root.global.spire.tools.kubectl.tag }} +{{- else }} +{{- $_ := set $root.image "tag" (regexReplaceAll "^(v?\\d+\\.\\d+\\.\\d+).*" $root.KubeVersion "${1}") }} +{{- end }} +{{- end }} +{{- include "spire-lib.image" $root }} {{- end }} {{/* diff --git a/charts/spire/values.yaml b/charts/spire/values.yaml index 1255884..e5de054 100644 --- a/charts/spire/values.yaml +++ b/charts/spire/values.yaml @@ -21,6 +21,14 @@ global: ## @param global.spire.upstreamServerAddress Set what address to use for the upstream server when using nested spire upstreamServerAddress: "" + ## @param global.spire.caSubject.country Country for Spire server CA + ## @param global.spire.caSubject.organization Organization for Spire server CA + ## @param global.spire.caSubject.commonName Common Name for Spire server CA + caSubject: + country: "" + organization: "" + commonName: "" + ## @param global.spire.recommendations.enabled Use recommended settings for production deployments. Default is off. ## @param global.spire.recommendations.namespaceLayout Set to true to use recommended values for installing across namespaces ## @param global.spire.recommendations.namespacePSS When chart namespace creation is enabled, label them with preffered Pod Security Standard labels @@ -69,6 +77,11 @@ 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, ""]. ingressControllerType: "" + tools: + kubectl: + ## @param global.spire.tools.kubectl.tag Set to force the tag to use for all kubectl instances + tag: "" + installAndUpgradeHooks: ## @param global.installAndUpgradeHooks.enabled Enable Helm hooks to autofix common install/upgrade issues (should be disabled when using `helm template`) enabled: true diff --git a/examples/keycloak-config-cli-using-spire/README.md b/examples/keycloak-config-cli-using-spire/README.md new file mode 100644 index 0000000..ca18cda --- /dev/null +++ b/examples/keycloak-config-cli-using-spire/README.md @@ -0,0 +1,67 @@ +# keycloak-config-cli using spire + +> [!WARNING] +> This example uses +> the [`SidecarContainers`](https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/#enabling-sidecar-containers) +> feature. This is only enabled by default in Kubernetes 1.29+. + +This example shows how to leverage SPIRE in establishing an mTLS connection +between [Keycloak](https://www.keycloak.org/) and [keycloak-config-cli](https://github.com/adorsys/keycloak-config-cli), +a tool to configure Keycloak. + +## Setup + +1. Create a local cluster for testing + +```shell +kind create cluster --image kindest/node:v1.29.0 +``` + +2. Install CRDs + +```shell +helm upgrade --install -n spire-server spire-crds ../../charts/spire-crds --create-namespace +``` + +3. Install `spire-server` + +```shell +helm upgrade --install -n spire-server spire ../../charts/spire --create-namespace -f spire-values.yaml +``` + +4. Install `keycloak` (this also configures Keycloak for client certificate authentication) + +```shell +helm upgrade --install keycloak oci://registry-1.docker.io/bitnamicharts/keycloak -f keycloak-values.yaml +``` + +5. Install `keycloak-config-cli` + +```shell +kubectl apply -f keycloak-config-cli.yaml +``` + +6. Verify the realm config at the bottom of [keycloak-config-cli.yaml](./keycloak-config-cli.yaml) has been created! +7. Cleanup + +```shell +kind delete cluster +``` + +## Notes + +### java-spiffe-helper as Keycloak initContainer + +This example uses [java-spiffe-helper](https://github.com/spiffe/java-spiffe/tree/main/java-spiffe-helper) as an +initContainer for Keycloak. It fetches the certificates from the `spire-agent` and conveniently provides them to +Keycloak in `pkcs12` format. + +> [!IMPORTANT] +> Keycloak does not rotate the certificates like SPIRE does. If you want to run the `keycloak-config-cli` +> job again, you need to make sure Keycloak is also restarted/provided with non-expired certificates. + +### Common name as username + +This example is configured to read the username from the common name (`CN`) from the client certificate. Keycloak has +some options there, this looked like the easiest one. SPIRE joins the values from `dnsNameTemplates` in the +common name section of the certificate, so make sure you can somehow extract the username from it. diff --git a/examples/keycloak-config-cli-using-spire/keycloak-config-cli.yaml b/examples/keycloak-config-cli-using-spire/keycloak-config-cli.yaml new file mode 100644 index 0000000..bce260d --- /dev/null +++ b/examples/keycloak-config-cli-using-spire/keycloak-config-cli.yaml @@ -0,0 +1,84 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: keycloak-config-cli + labels: + app: keycloak-config-cli +spec: + backoffLimit: 1 + template: + metadata: + labels: + app: keycloak-config-cli + app.kubernetes.io/instance: keycloak-config-cli # This needs to match the podSelector for the SpiffeID + spec: + initContainers: + - name: ghostunnel + image: ghostunnel/ghostunnel:v1.7.3 + imagePullPolicy: IfNotPresent + restartPolicy: Always + args: + - client + - --use-workload-api-addr + - unix:///run/spire/agent-sockets/spire-agent.sock # The filename depends on what the spire-agent uses + - --listen + - localhost:8080 # Listen on local http + - --target + - keycloak:8443 # Tunnel via https + - --status + - http://0.0.0.0:6060 + ports: + - containerPort: 8080 + name: listen + protocol: TCP + - containerPort: 6060 + name: readiness + protocol: TCP + readinessProbe: + httpGet: + path: /_status + port: readiness + volumeMounts: + - name: spire-sockets + mountPath: /run/spire/agent-sockets + readOnly: true + containers: + - name: keycloak-config-cli + image: adorsys/keycloak-config-cli:latest + imagePullPolicy: IfNotPresent + env: + - name: KEYCLOAK_URL + value: "http://127.0.0.1:8080" + - name: KEYCLOAK_USER + value: "keycloak-config-cli" + - name: KEYCLOAK_PASSWORD + value: "doesn't matter, since we are authenticated via the client certificate" + - name: KEYCLOAK_CLIENTID + value: "keycloak-config-cli" # This is the client created on bootstrapping Keycloak via the keycloak-config-cli sidecar + volumeMounts: + - name: realm + mountPath: /config + restartPolicy: OnFailure + volumes: + - name: realm + configMap: + name: keycloak-config-cli + - name: spire-sockets + hostPath: + path: /run/spire/agent-sockets # This needs to match the path mounted by the spire-agent + type: DirectoryOrCreate +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: keycloak-config-cli + labels: + app: keycloak-config-cli +data: + keycloak-config-cli.json: | + { + "id": "keycloak-config-cli", + "realm": "keycloak-config-cli", + "enabled": true + } diff --git a/examples/keycloak-config-cli-using-spire/keycloak-values.yaml b/examples/keycloak-config-cli-using-spire/keycloak-values.yaml new file mode 100644 index 0000000..6fb83e8 --- /dev/null +++ b/examples/keycloak-config-cli-using-spire/keycloak-values.yaml @@ -0,0 +1,134 @@ +extraDeploy: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: java-spiffe-helper-properties + data: + java-spiffe-helper.properties: | + keyStorePath=/certs/keystore.p12 + keyStorePass=password + keyPass=password + trustStorePath=/certs/truststore.p12 + trustStorePass=password + keyStoreType=pkcs12 + keyAlias=spiffe + spiffeSocketPath=unix:/run/spire/agent-sockets/spire-agent.sock +service: + extraPorts: + - name: https + port: 8443 + targetPort: 8443 +extraEnvVars: + - name: KC_HTTPS_CLIENT_AUTH + value: "request" + - name: KC_HTTPS_KEY_STORE_FILE + value: "/certs/keystore.p12" + - name: KC_HTTPS_KEY_STORE_PASSWORD + value: "password" + - name: KC_HTTPS_KEY_STORE_TYPE + value: "pkcs12" + - name: KC_HTTPS_TRUST_STORE_FILE + value: "/certs/truststore.p12" + - name: KC_HTTPS_TRUST_STORE_PASSWORD + value: "password" + - name: KC_HTTPS_TRUST_STORE_TYPE + value: "pkcs12" +initContainers: + - name: java-spiffe-helper + image: ghcr.io/spiffe/java-spiffe-helper:0.8.5 + imagePullPolicy: IfNotPresent + restartPolicy: Always + readinessProbe: + exec: + command: + - ls + - /certs/truststore.p12 + volumeMounts: + - name: java-spiffe-helper-properties + mountPath: /app/java-spiffe-helper.properties + subPath: java-spiffe-helper.properties + - name: spire-sockets + mountPath: /run/spire/agent-sockets + readOnly: true + - name: certs + mountPath: /certs +extraVolumeMounts: + - name: certs + mountPath: /certs +extraVolumes: + - name: java-spiffe-helper-properties + configMap: + name: java-spiffe-helper-properties + - name: spire-sockets + hostPath: + path: /run/spire/agent-sockets + type: DirectoryOrCreate + - name: certs + emptyDir: {} +auth: + adminPassword: "password" +keycloakConfigCli: + enabled: true + configuration: + master.json: | + { + "id": "master", + "realm": "master", + "enabled": true, + "users": [ + { + "username": "keycloak-config-cli", + "enabled": true, + "realmRoles": [ + "admin" + ], + "credentials": [ + { + "type": "password", + "value": "it-really-doesn't-matter-what-you-put-here" + } + ] + } + ], + "authenticationFlows": [ + { + "alias": "direct grant x509", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticatorConfig": "username", + "authenticator": "direct-grant-auth-x509-username", + "requirement": "REQUIRED", + "priority": 0 + } + ] + } + ], + "authenticatorConfig": [ + { + "alias": "username", + "config": { + "x509-cert-auth.regular-expression": "CN=(keycloak-config-cli)", + "x509-cert-auth.mapper-selection": "Username or Email", + "x509-cert-auth.mapping-source-selection": "Match SubjectDN using regular expression" + } + } + ], + "clients": [ + { + "clientId": "keycloak-config-cli", + "name": "keycloak-config-cli", + "enabled": true, + "standardFlowEnabled": false, + "directAccessGrantsEnabled": true, + "publicClient": true, + "authenticationFlowBindingOverrides": { + "direct_grant": "direct grant x509" + }, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0 + } + ] + } diff --git a/examples/keycloak-config-cli-using-spire/spire-values.yaml b/examples/keycloak-config-cli-using-spire/spire-values.yaml new file mode 100644 index 0000000..b1f401d --- /dev/null +++ b/examples/keycloak-config-cli-using-spire/spire-values.yaml @@ -0,0 +1,26 @@ +spire-server: + controllerManager: + identities: + clusterSPIFFEIDs: + default: + enabled: false + keycloak: + spiffeIDTemplate: spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }} + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: default + podSelector: + matchLabels: + app.kubernetes.io/instance: keycloak + dnsNameTemplates: + - keycloak + keycloak-config-cli: + spiffeIDTemplate: spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }} + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: default + podSelector: + matchLabels: + app.kubernetes.io/instance: keycloak-config-cli + dnsNameTemplates: + - keycloak-config-cli # This is the common name used for the certificate. In this case, the username diff --git a/examples/tpm-direct/values.yaml b/examples/tpm-direct/values.yaml new file mode 100644 index 0000000..ab53a82 --- /dev/null +++ b/examples/tpm-direct/values.yaml @@ -0,0 +1,15 @@ +spire-agent: + nodeAttestor: + k8sPsat: + enabled: false + tpmDirect: + enabled: true + +spire-server: + controllerManager: + # K8s labels have a 63 character limit. TPM hashes are 64 chars. So you need to label the node with two labels with half of the tpm's hash each. The 'node-restriction.kubernetes.io/' prefix is so that the + # nodes can't update the hash themselves, an important security constraint. + parentIDTemplate: 'spiffe://{{ .TrustDomain }}/spire/agent/tpm/{{ index .NodeMeta.Labels "node-restriction.kubernetes.io/tpm-pubhash" }}{{ index .NodeMeta.Labels "node-restriction.kubernetes.io/tpm-pubhash2" }}' + nodeAttestor: + tpmDirect: + enabled: true diff --git a/tests/go.mod b/tests/go.mod index 883753d..508a476 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -1,11 +1,13 @@ module github.com/spiffe/helm-charts/tests -go 1.20 +go 1.21 + +toolchain go1.21.5 require ( github.com/onsi/ginkgo/v2 v2.15.0 github.com/onsi/gomega v1.31.1 - helm.sh/helm/v3 v3.14.0 + helm.sh/helm/v3 v3.14.2 ) require ( diff --git a/tests/go.sum b/tests/go.sum index e697dae..779a9c2 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -19,7 +19,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= +github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -67,6 +69,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -95,6 +98,7 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -102,6 +106,7 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -113,6 +118,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -205,8 +211,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -helm.sh/helm/v3 v3.14.0 h1:TaZIH6uOchn7L27ptwnnuHJiFrT/BsD4dFdp/HLT2nM= -helm.sh/helm/v3 v3.14.0/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424= +helm.sh/helm/v3 v3.14.2 h1:V71fv+NGZv0icBlr+in1MJXuUIHCiPG1hW9gEBISTIA= +helm.sh/helm/v3 v3.14.2/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424= k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A= k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA= k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0= diff --git a/tests/unit/spire_test.go b/tests/unit/spire_test.go index f356636..7e6e1f0 100644 --- a/tests/unit/spire_test.go +++ b/tests/unit/spire_test.go @@ -144,6 +144,19 @@ spire-agent: objs, err := ValueStringRender(chart, ` spire-server: enabled: false +`) + Expect(err).Should(Succeed()) + notes := objs["spire/templates/NOTES.txt"] + Expect(notes).Should(ContainSubstring("Installed")) + }) + }) + Describe("spire-server.credentialComposer.uniqueID", func() { + It("spire server uniqueid credential composer", func() { + objs, err := ValueStringRender(chart, ` +spire-server: + credentialComposer: + uniqueID: + enabled: true `) Expect(err).Should(Succeed()) notes := objs["spire/templates/NOTES.txt"]