diff --git a/.editorconfig b/.editorconfig index bbf1aba..4499563 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ tab_width = 2 trim_trailing_whitespace = true insert_final_newline = true -[Makefile] +[Makefile,*.go,*.mod] indent_style = tab indent_size = 4 tab_width = 4 diff --git a/.github/kind/conf/kind-config.yaml b/.github/kind/conf/kind-config.yaml index 6c900fe..7c0cd3f 100644 --- a/.github/kind/conf/kind-config.yaml +++ b/.github/kind/conf/kind-config.yaml @@ -15,3 +15,4 @@ kubeadmConfigPatches: # admission-control-config-file: /etc/kubernetes/pki/admctrl/admission-control.yaml nodes: - role: control-plane + - role: worker diff --git a/.github/scripts/parse-versions.sh b/.github/scripts/parse-versions.sh new file mode 100644 index 0000000..eca9881 --- /dev/null +++ b/.github/scripts/parse-versions.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +TESTS_PATH="$(dirname "${BASH_SOURCE[0]}")/../tests" + +# Set repo and version env variables +REPOS=$(jq -r '.[] | "export " + ("HELM_REPO_" + .name | ascii_upcase | gsub("-";"_")) + "=" + .repo' "${TESTS_PATH}/charts.json") +VERSIONS=$(jq -r '.[] | "export " + ("VERSION_" + .name | ascii_upcase | gsub("-";"_")) + "=" + .version' "${TESTS_PATH}/charts.json") +eval "$REPOS" +eval "$VERSIONS" diff --git a/.github/tests/charts.json b/.github/tests/charts.json index b1bd471..9fabf85 100644 --- a/.github/tests/charts.json +++ b/.github/tests/charts.json @@ -2,7 +2,7 @@ { "name": "kube-prometheus-stack", "repo": "https://prometheus-community.github.io/helm-charts", - "version": "47.0.0" + "version": "48.1.1" }, { "name": "cert-manager", @@ -12,16 +12,16 @@ { "name": "ingress-nginx", "repo": "https://kubernetes.github.io/ingress-nginx", - "version": "4.7.0" + "version": "4.7.1" }, { "name": "mysql", "repo": "https://charts.bitnami.com/bitnami", - "version": "9.10.4" + "version": "9.10.6" }, { "name": "postgresql", "repo": "https://charts.bitnami.com/bitnami", - "version": "12.5.8" + "version": "12.6.6" } ] diff --git a/.github/tests/charts.sh b/.github/tests/charts.sh deleted file mode 100644 index d83af09..0000000 --- a/.github/tests/charts.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -REPOS=$(jq -r '.[] | "export " + ("HELM_REPO_" + .name | ascii_upcase | gsub("-";"_")) + "=" + .repo' .github/tests/charts.json) -VERSIONS=$(jq -r '.[] | "export " + ("VERSION_" + .name | ascii_upcase | gsub("-";"_")) + "=" + .version' .github/tests/charts.json) -eval "$REPOS" -eval "$VERSIONS" diff --git a/.github/tests/upstream-authority-disk/create-cert.sh b/.github/tests/create-cert.sh similarity index 100% rename from .github/tests/upstream-authority-disk/create-cert.sh rename to .github/tests/create-cert.sh diff --git a/.github/tests/production-external-mysql/mysql-values.yaml b/.github/tests/dependencies/mysql.yaml similarity index 59% rename from .github/tests/production-external-mysql/mysql-values.yaml rename to .github/tests/dependencies/mysql.yaml index 62f27e2..bd5e621 100644 --- a/.github/tests/production-external-mysql/mysql-values.yaml +++ b/.github/tests/dependencies/mysql.yaml @@ -5,3 +5,8 @@ primary: drop: [ALL] seccompProfile: type: RuntimeDefault +auth: + database: spire-server + username: spire + password: sp1ff3Test + rootPassword: sp1ff3TestPassword diff --git a/.github/tests/production-external-postgresql/postgresql-values.yaml b/.github/tests/dependencies/postgresql.yaml similarity index 61% rename from .github/tests/production-external-postgresql/postgresql-values.yaml rename to .github/tests/dependencies/postgresql.yaml index ea34425..fb906c1 100644 --- a/.github/tests/production-external-postgresql/postgresql-values.yaml +++ b/.github/tests/dependencies/postgresql.yaml @@ -6,3 +6,8 @@ primary: drop: [ALL] seccompProfile: type: RuntimeDefault +auth: + database: spire-server + username: spire + password: sp1ff3Test + postgresPassword: sp1ff3TestPassword diff --git a/.github/tests/upstream-authority-disk/example-org.key b/.github/tests/example-org.key similarity index 100% rename from .github/tests/upstream-authority-disk/example-org.key rename to .github/tests/example-org.key diff --git a/.github/tests/upstream-authority-disk/example-org.pem b/.github/tests/example-org.pem similarity index 100% rename from .github/tests/upstream-authority-disk/example-org.pem rename to .github/tests/example-org.pem diff --git a/.github/tests/extras/post-install.sh b/.github/tests/extras/post-install.sh deleted file mode 100644 index 1278f29..0000000 --- a/.github/tests/extras/post-install.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -x - -SCRIPT="$(readlink -f "$0")" -SCRIPTPATH="$(dirname "${SCRIPT}")" -scenario="${scenario:-$(basename "${SCRIPTPATH}")}" - -# shellcheck source=/dev/null -source "${SCRIPTPATH}/../common.sh" - -print_helm_releases -print_spire_workload_status "${scenario}" - -if [[ "$1" -ne 0 ]]; then - get_namespace_details "${scenario}" -fi diff --git a/.github/tests/federation-bundle-endpoint/post-install.sh b/.github/tests/federation-bundle-endpoint/post-install.sh deleted file mode 100644 index 1278f29..0000000 --- a/.github/tests/federation-bundle-endpoint/post-install.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -x - -SCRIPT="$(readlink -f "$0")" -SCRIPTPATH="$(dirname "${SCRIPT}")" -scenario="${scenario:-$(basename "${SCRIPTPATH}")}" - -# shellcheck source=/dev/null -source "${SCRIPTPATH}/../common.sh" - -print_helm_releases -print_spire_workload_status "${scenario}" - -if [[ "$1" -ne 0 ]]; then - get_namespace_details "${scenario}" -fi diff --git a/.github/tests/namespace-override/post-install.sh b/.github/tests/namespace-override/post-install.sh deleted file mode 100755 index 7fbaf11..0000000 --- a/.github/tests/namespace-override/post-install.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -set -x - -SCRIPT="$(readlink -f "$0")" -SCRIPTPATH="$(dirname "${SCRIPT}")" -scenario="${scenario:-$(basename "${SCRIPTPATH}")}" - -# shellcheck source=/dev/null -source "${SCRIPTPATH}/../common.sh" - -print_helm_releases -print_spire_workload_status spire-server spire-system - -if [[ "$1" -ne 0 ]]; then - get_namespace_details spire-server - get_namespace_details spire-systen -fi - diff --git a/.github/tests/namespace-override/pre-install.sh b/.github/tests/namespace-override/pre-install.sh deleted file mode 100755 index 3d778a6..0000000 --- a/.github/tests/namespace-override/pre-install.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - -kubectl create namespace "spire-system" -kubectl create namespace "spire-server" diff --git a/.github/tests/no-spire-controller-manager/post-install.sh b/.github/tests/no-spire-controller-manager/post-install.sh deleted file mode 100644 index 1278f29..0000000 --- a/.github/tests/no-spire-controller-manager/post-install.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -x - -SCRIPT="$(readlink -f "$0")" -SCRIPTPATH="$(dirname "${SCRIPT}")" -scenario="${scenario:-$(basename "${SCRIPTPATH}")}" - -# shellcheck source=/dev/null -source "${SCRIPTPATH}/../common.sh" - -print_helm_releases -print_spire_workload_status "${scenario}" - -if [[ "$1" -ne 0 ]]; then - get_namespace_details "${scenario}" -fi diff --git a/.github/tests/post-install.sh b/.github/tests/post-install.sh new file mode 100755 index 0000000..1981868 --- /dev/null +++ b/.github/tests/post-install.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -x + +SCRIPT="$(readlink -f "$0")" +SCRIPTPATH="$(dirname "${SCRIPT}")" + +# shellcheck source=/dev/null +source "${SCRIPTPATH}/common.sh" + +print_helm_releases diff --git a/.github/tests/pre-install.sh b/.github/tests/pre-install.sh new file mode 100755 index 0000000..bed4f1d --- /dev/null +++ b/.github/tests/pre-install.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +set -xe + +SCRIPT="$(readlink -f "$0")" +SCRIPTPATH="$(dirname "${SCRIPT}")" +DEPS="${SCRIPTPATH}/dependencies" + +# shellcheck source=/dev/null +source "${SCRIPTPATH}/../scripts/parse-versions.sh" + +helm_install=(helm upgrade --install --create-namespace) + +# namespace override +kubectl create namespace spire-system || true +kubectl create namespace spire-server || true + +# nginx ingress +"${helm_install[@]}" ingress-nginx ingress-nginx --version "${VERSION_INGRESS_NGINX}" --repo "${HELM_REPO_INGRESS_NGINX}" \ + --namespace ingress-nginx \ + --set controller.extraArgs.enable-ssl-passthrough= +kubectl wait --namespace ingress-nginx --for=condition=ready --timeout 60s pod --selector=app.kubernetes.io/component=controller + +# prometheus +"${helm_install[@]}" kube-prometheus-stack kube-prometheus-stack \ + --namespace prometheus \ + --version "${VERSION_KUBE_PROMETHEUS_STACK}" \ + --repo "${HELM_REPO_KUBE_PROMETHEUS_STACK}" \ + --wait + +# cert-manager +"${helm_install[@]}" cert-manager cert-manager --version "$VERSION_CERT_MANAGER" --repo "$HELM_REPO_CERT_MANAGER" \ + --namespace cert-manager \ + --set installCRDs=true \ + --wait + +# external database + +# mysql +"${helm_install[@]}" mysql mysql --version "$VERSION_MYSQL" --repo "$HELM_REPO_MYSQL" \ + --namespace mysql \ + --values "${DEPS}/mysql.yaml" \ + --wait + +# postgres +"${helm_install[@]}" postgresql postgresql --version "$VERSION_POSTGRESQL" --repo "$HELM_REPO_POSTGRESQL" \ + --namespace postgresql \ + --values "${DEPS}/postgresql.yaml" \ + --wait diff --git a/.github/tests/production-example/install.sh b/.github/tests/production-example/install.sh deleted file mode 100755 index c2b5cfe..0000000 --- a/.github/tests/production-example/install.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -xe - -SCRIPT="$(readlink -f "$0")" -SCRIPTPATH="$(dirname "${SCRIPT}")" - -helm install \ - --namespace spire-server \ - --values "${SCRIPTPATH}/../../../examples/production/values.yaml" \ - spire charts/spire --wait - -helm test spire --namespace spire-server diff --git a/.github/tests/production-example/post-install.sh b/.github/tests/production-example/post-install.sh deleted file mode 100755 index 29335e6..0000000 --- a/.github/tests/production-example/post-install.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -set -x - -SCRIPT="$(readlink -f "$0")" -SCRIPTPATH="$(dirname "${SCRIPT}")" -scenario="${scenario:-$(basename "${SCRIPTPATH}")}" - -# shellcheck source=/dev/null -source "${SCRIPTPATH}/../common.sh" - -print_helm_releases -print_spire_workload_status spire-server spire-system - -if [[ "$1" -ne 0 ]]; then - get_namespace_details spire-server - get_namespace_details spire-system -fi diff --git a/.github/tests/production-example/pre-install.sh b/.github/tests/production-example/pre-install.sh deleted file mode 100755 index b33d1ed..0000000 --- a/.github/tests/production-example/pre-install.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -kubectl create namespace spire-system -kubectl label namespace spire-system pod-security.kubernetes.io/enforce=privileged -kubectl create namespace spire-server -kubectl label namespace spire-server pod-security.kubernetes.io/enforce=restricted diff --git a/.github/tests/production-external-mysql/install.sh b/.github/tests/production-external-mysql/install.sh deleted file mode 100755 index 7bb5d63..0000000 --- a/.github/tests/production-external-mysql/install.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -set -xe - -SCRIPT=$(readlink -f "$0") -SCRIPTPATH=$(dirname "$SCRIPT") - -DB=spire -DBUSER=spire -DBPW=$(uuidgen) -DBROOTPW=$(uuidgen) - -# Generate random settings to make sure things come up with random settings. -cat < /tmp/$$-db-values.yaml -auth: - database: ${DB} - username: ${DBUSER} - password: ${DBPW} - rootPassword: ${DBROOTPW} -EOF - -cat < /tmp/$$-spire-values.yaml -spire-server: - dataStore: - sql: - databaseType: mysql - databaseName: ${DB} - username: ${DBUSER} - password: ${DBPW} - host: mysql - port: 3306 -EOF - -helm install mysql mysql --namespace "spire-server" --version "$VERSION_MYSQL" --repo "$HELM_REPO_MYSQL" \ - --values "${SCRIPTPATH}/mysql-values.yaml" \ - --values /tmp/$$-db-values.yaml --wait - -helm install \ - --namespace "spire-server" \ - --values /tmp/$$-spire-values.yaml \ - --values "${SCRIPTPATH}/../../../examples/production/values.yaml" \ - spire charts/spire --wait - -helm test spire --namespace "spire-server" diff --git a/.github/tests/production-external-mysql/post-install.sh b/.github/tests/production-external-mysql/post-install.sh deleted file mode 100755 index 29335e6..0000000 --- a/.github/tests/production-external-mysql/post-install.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -set -x - -SCRIPT="$(readlink -f "$0")" -SCRIPTPATH="$(dirname "${SCRIPT}")" -scenario="${scenario:-$(basename "${SCRIPTPATH}")}" - -# shellcheck source=/dev/null -source "${SCRIPTPATH}/../common.sh" - -print_helm_releases -print_spire_workload_status spire-server spire-system - -if [[ "$1" -ne 0 ]]; then - get_namespace_details spire-server - get_namespace_details spire-system -fi diff --git a/.github/tests/production-external-mysql/pre-install.sh b/.github/tests/production-external-mysql/pre-install.sh deleted file mode 100755 index b33d1ed..0000000 --- a/.github/tests/production-external-mysql/pre-install.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -kubectl create namespace spire-system -kubectl label namespace spire-system pod-security.kubernetes.io/enforce=privileged -kubectl create namespace spire-server -kubectl label namespace spire-server pod-security.kubernetes.io/enforce=restricted diff --git a/.github/tests/production-external-postgresql/install.sh b/.github/tests/production-external-postgresql/install.sh deleted file mode 100755 index 38b56c4..0000000 --- a/.github/tests/production-external-postgresql/install.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash - -set -xe - -SCRIPT=$(readlink -f "$0") -SCRIPTPATH=$(dirname "$SCRIPT") - -DB=$(uuidgen) -DBUSER=$(uuidgen) -DBPW=$(uuidgen) -DBPGPW=$(uuidgen) - -# Generate random settings to make sure things come up with random settings. -cat > /tmp/$$-db-values.yaml < /tmp/$$-spire-values.yaml <> $GITHUB_OUTPUT - - outputs: - tests: ${{ steps.set-matrix.outputs.tests }} - test: runs-on: ubuntu-22.04 - needs: - - build-matrix strategy: matrix: @@ -53,8 +33,6 @@ jobs: - v1.27.2 - v1.26.4 - v1.25.9 - values: - - ${{ fromJson(needs.build-matrix.outputs.tests) }} steps: - run: 'echo "Skipping tests"' diff --git a/.github/workflows/helm-chart-ci.yaml b/.github/workflows/helm-chart-ci.yaml index 3210c99..f573bc9 100644 --- a/.github/workflows/helm-chart-ci.yaml +++ b/.github/workflows/helm-chart-ci.yaml @@ -12,6 +12,8 @@ on: - '.github/tests/**/*.sh' - '.github/tests/**/*.json' - 'examples/**/*.yaml' + - 'examples/**/*.sh' + - 'tests/**/*' - 'helm-docs.sh' concurrency: @@ -21,6 +23,7 @@ concurrency: env: HELM_VERSION: v3.12.0 PYTHON_VERSION: 3.11.3 + KIND_VERSION: v0.19.0 CHART_TESTING_VERSION: v3.8.0 jobs: @@ -69,6 +72,23 @@ jobs: exit 1 fi + - name: Setup Go + uses: actions/setup-go@v4.0.1 + with: + go-version-file: tests/go.mod + cache-dependency-path: tests/go.sum + check-latest: true + + - name: Install do dependencies + run: | + go mod download + go install github.com/onsi/ginkgo/v2/ginkgo@latest + working-directory: ./tests/unit + + - name: Run Unit Tests + run: ginkgo + working-directory: ./tests/unit + lint-chart: runs-on: ubuntu-22.04 @@ -96,35 +116,11 @@ jobs: - name: Run chart-testing (lint) run: TARGET_BRANCH=${{ github.base_ref }} make lint${{ github.base_ref == 'release' && '-release' || '' }} - outputs: - changed: ${{ steps.list-changed.outputs.changed }} - - build-matrix: - name: Build matrix - runs-on: ubuntu-22.04 - - needs: [lint-chart] - - steps: - - name: Checkout - uses: actions/checkout@v3.5.3 - - - id: set-matrix - name: Collect all tests - run: | - tests="$(echo -e "default\n$(find .github/tests -maxdepth 1 -type d | grep -Ev 'tests$' | xargs -I % basename % | sort | uniq)")" - tests_json="$(echo "$tests" | jq -c --slurp --raw-input 'split("\n") | map(select(. != ""))')" - echo "tests=$tests_json" >> $GITHUB_OUTPUT - - outputs: - tests: ${{ steps.set-matrix.outputs.tests }} - test: runs-on: ubuntu-22.04 needs: - lint-chart - - build-matrix strategy: fail-fast: false @@ -137,8 +133,6 @@ jobs: - v1.27.2 - v1.26.4 - v1.25.9 - values: - - ${{ fromJson(needs.build-matrix.outputs.tests) }} steps: - name: Checkout @@ -162,42 +156,86 @@ jobs: version: ${{ env.CHART_TESTING_VERSION }} - name: Create kind ${{ matrix.k8s }} cluster - uses: helm/kind-action@v1.7.0 + uses: helm/kind-action@v1.8.0 # Only build a kind cluster if there are chart changes to test. with: - version: v0.19.0 + version: ${{ env.KIND_VERSION }} node_image: kindest/node:${{ matrix.k8s }} config: .github/kind/conf/kind-config.yaml verbosity: 1 + - name: Setup Test dependencies + run: ./pre-install.sh + working-directory: .github/tests + - name: Run chart-testing (install) run: | - post-install() { - [ -x "${TEST_DIR}/post-install.sh" ] && "${TEST_DIR}/post-install.sh" $1 - exit $1 - } + ct install --config ct.yaml \ + --target-branch ${{ github.base_ref }} - trap 'post-install $? $LINENO' EXIT + - name: Test summary + if: always() + run: ./post-install.sh + working-directory: .github/tests - export scenario="$(basename "${TEST_DIR}")" - export EXTRA_HELM_ARGS="" + build-matrix: + name: Build matrix + runs-on: ubuntu-22.04 - source .github/tests/charts.sh + steps: + - name: Checkout + uses: actions/checkout@v3.5.2 - [ "${scenario}" != "default" ] && kubectl create namespace "${scenario}" - [ -x "${TEST_DIR}/pre-install.sh" ] && "${TEST_DIR}/pre-install.sh" - [ -f "${TEST_DIR}/.env" ] && source "${TEST_DIR}/.env" + - id: set-matrix + name: Collect all examples + run: | + examples="$(find examples -maxdepth 2 -type f -name run-tests.sh | xargs -I % dirname %)" + examples_json="$(echo "$examples" | jq -c --slurp --raw-input 'split("\n") | map(select(. != ""))')" + echo "${examples_json}" + echo "examples=$examples_json" >>"$GITHUB_OUTPUT" - if [ -x "${TEST_DIR}/install.sh" ]; then - "${TEST_DIR}/install.sh" - else - ct install --debug \ - --charts "charts/spire" \ - --namespace "${scenario}" \ - --target-branch ${{ github.base_ref }} \ - --exclude-deprecated \ - --skip-clean-up \ - ${{ (matrix.values != 'default' && '--helm-extra-set-args "--values=${TEST_DIR}/values.yaml ${EXTRA_HELM_ARGS}"') || '' }} - fi - env: - TEST_DIR: .github/tests/${{ matrix.values }} + outputs: + examples: ${{ steps.set-matrix.outputs.examples }} + + example-test: + runs-on: ubuntu-22.04 + + needs: + - lint-chart + - build-matrix + + strategy: + fail-fast: false + matrix: + k8s: + - v1.27.2 + - v1.26.4 + - v1.25.9 + example: + - ${{ fromJson(needs.build-matrix.outputs.examples) }} + + steps: + - name: Checkout + uses: actions/checkout@v3.5.2 + + - name: Set up Helm + uses: azure/setup-helm@v3.5 + with: + version: ${{ env.HELM_VERSION }} + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Create kind cluster + uses: helm/kind-action@v1.7.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 example + run: ${{ matrix.example }}/run-tests.sh diff --git a/Makefile b/Makefile index 6b550d5..c3ad2d6 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,7 @@ TARGET_BRANCH ?= main .PHONY: help help: ## Display this help. - @$(MAKE) help - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) ##@ Linting: @@ -16,10 +15,10 @@ lint-release: ## Lint the charts using chart-testing for release @echo Linting charts… @ct lint --config ct.yaml --target-branch $(TARGET_BRANCH) -##@ Testing: +##@ Testing: (ensure to run on dedicated test cluster) -.PHONY: clean-lingering-resources -clean-lingering-resources: +.PHONY: clean-test-leftovers +clean-test-leftovers: ## Cleans up any lingering resources in case tests fail massively @echo Cleanup potential leftovers… @-kubectl delete csidrivers.storage.k8s.io csi.spiffe.io \ &>/dev/null || true @@ -31,7 +30,36 @@ clean-lingering-resources: &>/dev/null || true .PHONY: test -test: ## Run tests using Helm chart-testing (ensure to run on dedicated test cluster) +test: install-test-deps test-charts test-examples ## Run all chart tests and example tests + +.PHONY: install-test-deps +install-test-deps: ## Install test dependency resources + @echo Installing test dependencies… + @.github/tests/pre-install.sh + +.PHONY: test-charts +test-charts: ## Run tests on charts using Helm chart-testing @echo Running tests… - @ct install --debug \ - --charts charts/spire + @ct install --config ct.yaml + +.PHONY: cleanup-test-deps +cleanup-test-deps: ## Cleans up all test dependencies resources + @echo Uninstalling test dependencies… + @helm uninstall -n cert-manager cert-manager 2>/dev/null || true + @kubectl delete ns cert-manager 2>/dev/null || true + @helm uninstall -n prometheus kube-prometheus-stack 2>/dev/null || true + @kubectl delete ns prometheus 2>/dev/null || true + @helm uninstall -n mysql mysql 2>/dev/null|| true + @kubectl delete ns mysql 2>/dev/null || true + @helm uninstall -n postgresql postgresql 2>/dev/null || true + @kubectl delete ns postgresql 2>/dev/null || true + @helm uninstall -n ingress-nginx ingress-nginx 2>/dev/null || true + @kubectl delete ns ingress-nginx 2>/dev/null || true + +test-example-%: + @echo Running tests for $* example… + @examples/$*/run-tests.sh + @echo + +.PHONY: test-examples +test-examples: $(patsubst examples/%/values.yaml,test-example-%,$(wildcard examples/*/values.yaml)) ## Run `helm install` and `helm test` for all the examples containing `run-tests.sh` diff --git a/charts/spire/.helmignore b/charts/spire/.helmignore index 0e8a0eb..5bdaa3e 100644 --- a/charts/spire/.helmignore +++ b/charts/spire/.helmignore @@ -21,3 +21,4 @@ .idea/ *.tmproj .vscode/ +ci/ diff --git a/charts/spire/Chart.lock b/charts/spire/Chart.lock new file mode 100644 index 0000000..88436fe --- /dev/null +++ b/charts/spire/Chart.lock @@ -0,0 +1,18 @@ +dependencies: +- name: spire-server + repository: file://./charts/spire-server + version: 0.1.0 +- name: spire-agent + repository: file://./charts/spire-agent + version: 0.1.0 +- name: spiffe-csi-driver + repository: file://./charts/spiffe-csi-driver + version: 0.1.0 +- name: spiffe-oidc-discovery-provider + repository: file://./charts/spiffe-oidc-discovery-provider + version: 0.1.0 +- name: tornjak-frontend + repository: file://./charts/tornjak-frontend + version: 0.1.0 +digest: sha256:0119361a3dd54d1cf088f299ce9adbee55a96c832cb675f57e5e115acf7b17c7 +generated: "2023-07-19T19:13:59.722106+02:00" diff --git a/charts/spire/Chart.yaml b/charts/spire/Chart.yaml index 737db6e..46a2532 100644 --- a/charts/spire/Chart.yaml +++ b/charts/spire/Chart.yaml @@ -3,7 +3,7 @@ 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.10.1 +version: 0.11.0 appVersion: "1.7.0" keywords: ["spiffe", "spire", "spire-server", "spire-agent", "oidc", "spire-controller-manager"] home: https://github.com/spiffe/helm-charts/tree/main/charts/spire diff --git a/charts/spire/README.md b/charts/spire/README.md index aa37c6f..98ba717 100644 --- a/charts/spire/README.md +++ b/charts/spire/README.md @@ -2,7 +2,7 @@ -![Version: 0.10.1](https://img.shields.io/badge/Version-0.10.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.7.0](https://img.shields.io/badge/AppVersion-1.7.0-informational?style=flat-square) +![Version: 0.11.0](https://img.shields.io/badge/Version-0.11.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.7.0](https://img.shields.io/badge/AppVersion-1.7.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. @@ -112,6 +112,7 @@ Now you can interact with the Spire agent socket from your own application. The | global.spire.bundleConfigMap | string | `""` | Override all instances of bundleConfigMap | | global.spire.clusterName | string | `"example-cluster"` | | | global.spire.image.registry | string | `""` | Override all Spire image registries at once | +| global.spire.jwtIssuer | string | `"oidc-discovery.example.org"` | Set the jwt issuer | | global.spire.trustDomain | string | `"example.org"` | The trust domain to be used for the SPIFFE identifiers | | spiffe-csi-driver.enabled | bool | `true` | Enables deployment of CSI driver | | spiffe-oidc-discovery-provider.enabled | bool | `false` | Enables deployment of OIDC discovery provider | @@ -152,6 +153,7 @@ Now you can interact with the Spire agent socket from your own application. The | spiffe-csi-driver.serviceAccount.annotations | object | `{}` | Annotations to add to the service account | | spiffe-csi-driver.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | | spiffe-csi-driver.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| spiffe-csi-driver.tolerations | list | `[]` | | | spiffe-oidc-discovery-provider.affinity | object | `{}` | | | spiffe-oidc-discovery-provider.agentSocketName | string | `"spire-agent.sock"` | The name of the spire-agent unix socket | | spiffe-oidc-discovery-provider.autoscaling.enabled | bool | `false` | | @@ -164,8 +166,7 @@ Now you can interact with the Spire agent socket from your own application. The | spiffe-oidc-discovery-provider.config.acme.directoryUrl | string | `"https://acme-v02.api.letsencrypt.org/directory"` | | | spiffe-oidc-discovery-provider.config.acme.emailAddress | string | `"letsencrypt@example.org"` | | | spiffe-oidc-discovery-provider.config.acme.tosAccepted | bool | `false` | | -| spiffe-oidc-discovery-provider.config.domains[0] | string | `"localhost"` | | -| spiffe-oidc-discovery-provider.config.domains[1] | string | `"oidc-discovery.example.org"` | | +| spiffe-oidc-discovery-provider.config.additionalDomains | list | `["localhost"]` | Add additional domains that can be used for oidc discovery | | spiffe-oidc-discovery-provider.config.logLevel | string | `"info"` | The log level, valid values are "debug", "info", "warn", and "error" | | spiffe-oidc-discovery-provider.configMap.annotations | object | `{}` | Annotations to add to the SPIFFE OIDC Discovery Provider ConfigMap | | spiffe-oidc-discovery-provider.fullnameOverride | string | `""` | | @@ -189,6 +190,7 @@ Now you can interact with the Spire agent socket from your own application. The | spiffe-oidc-discovery-provider.insecureScheme.nginx.image.tag | string | `"1.24.0-alpine"` | Overrides the image tag | | spiffe-oidc-discovery-provider.insecureScheme.nginx.image.version | string | `""` | This value is deprecated in favor of tag. (Will be removed in a future release) | | spiffe-oidc-discovery-provider.insecureScheme.nginx.resources | object | `{}` | | +| spiffe-oidc-discovery-provider.jwtIssuer | string | `"oidc-discovery.example.org"` | | | spiffe-oidc-discovery-provider.livenessProbe.initialDelaySeconds | int | `5` | Initial delay seconds for livenessProbe | | spiffe-oidc-discovery-provider.livenessProbe.periodSeconds | int | `5` | Period seconds for livenessProbe | | spiffe-oidc-discovery-provider.nameOverride | string | `""` | | @@ -271,6 +273,7 @@ Now you can interact with the Spire agent socket from your own application. The | spire-agent.telemetry.prometheus.podMonitor.labels | object | `{}` | | | spire-agent.telemetry.prometheus.podMonitor.namespace | string | `""` | Override where to install the podMonitor, if not set will use the same namespace as the spire-agent | | spire-agent.telemetry.prometheus.port | int | `9988` | | +| spire-agent.tolerations | list | `[]` | | | spire-agent.trustBundleFormat | string | `"pem"` | If using trustBundleURL, what format is the url. Choices are "pem" and "spiffe" | | spire-agent.trustBundleURL | string | `""` | If set, obtain trust bundle from url instead of Kubernetes ConfigMap | | spire-agent.trustDomain | string | `"example.org"` | The trust domain to be used for the SPIFFE identifiers | @@ -395,7 +398,10 @@ Now you can interact with the Spire agent socket from your own application. The | spire-server.tools.kubectl.image.tag | string | `""` | Overrides the image tag | | spire-server.tools.kubectl.image.version | string | `""` | This value is deprecated in favor of tag. (Will be removed in a future release) | | spire-server.topologySpreadConstraints | list | `[]` | | -| spire-server.tornjak.config.dataStore | object | `{"driver":"sqlite3","file":"/run/spire/data/tornjak.sqlite3"}` | persistent DB for storing Tornjak specific information | +| spire-server.tornjak.config.clientCA.name | string | `"tornjak-client-ca"` | | +| spire-server.tornjak.config.clientCA.type | string | `"Secret"` | Type of delivery for the user CA for mTLS client verification options are `Secret` or `ConfigMap` (required for `mtls` connectionType) | +| spire-server.tornjak.config.dataStore | object | `{"driver":"sqlite3","file":"/run/spire/data/tornjak.sqlite3"}` | Persistent DB for storing Tornjak specific information | +| spire-server.tornjak.config.tlsSecret | string | `"tornjak-tls-secret"` | Name of the secret containing server side key and certificate for TLS verification (required for `tls` or `mtls` connectionType) | | spire-server.tornjak.enabled | bool | `false` | Deploys Tornjak API (backend) (Not for production) | | spire-server.tornjak.image.pullPolicy | string | `"IfNotPresent"` | The Tornjak image pull policy | | spire-server.tornjak.image.registry | string | `"ghcr.io"` | The OCI registry to pull the Tornjak image from | @@ -404,7 +410,7 @@ Now you can interact with the Spire agent socket from your own application. The | spire-server.tornjak.image.version | string | `""` | This value is deprecated in favor of tag. (Will be removed in a future release) | | spire-server.tornjak.resources | object | `{}` | | | spire-server.tornjak.service.annotations | object | `{}` | | -| spire-server.tornjak.service.port | int | `10000` | | +| spire-server.tornjak.service.ports | object | `{"http":10080,"https":10443}` | Ports for tornjak | | spire-server.tornjak.service.type | string | `"ClusterIP"` | | | spire-server.tornjak.startupProbe.failureThreshold | int | `3` | | | spire-server.tornjak.startupProbe.initialDelaySeconds | int | `5` | Initial delay seconds for | diff --git a/charts/spire/charts/spiffe-csi-driver/README.md b/charts/spire/charts/spiffe-csi-driver/README.md index 954456a..2cf643d 100644 --- a/charts/spire/charts/spiffe-csi-driver/README.md +++ b/charts/spire/charts/spiffe-csi-driver/README.md @@ -59,5 +59,6 @@ A Helm chart to install the SPIFFE CSI driver. | serviceAccount.annotations | object | `{}` | Annotations to add to the service account | | serviceAccount.create | bool | `true` | Specifies whether a service account should be created | | serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| tolerations | list | `[]` | | ---------------------------------------------- diff --git a/charts/spire/charts/spiffe-csi-driver/templates/daemonset.yaml b/charts/spire/charts/spiffe-csi-driver/templates/daemonset.yaml index 61204d8..2031f7f 100644 --- a/charts/spire/charts/spiffe-csi-driver/templates/daemonset.yaml +++ b/charts/spire/charts/spiffe-csi-driver/templates/daemonset.yaml @@ -20,11 +20,19 @@ spec: labels: {{- include "spiffe-csi-driver.selectorLabels" . | nindent 8 }} spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} serviceAccountName: {{ include "spiffe-csi-driver.serviceAccountName" . }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} {{- if .Values.priorityClassName }} priorityClassName: {{ .Values.priorityClassName }} {{- end }} diff --git a/charts/spire/charts/spiffe-csi-driver/values.yaml b/charts/spire/charts/spiffe-csi-driver/values.yaml index 64ea54c..b200827 100644 --- a/charts/spire/charts/spiffe-csi-driver/values.yaml +++ b/charts/spire/charts/spiffe-csi-driver/values.yaml @@ -66,6 +66,8 @@ securityContext: nodeSelector: {} +tolerations: [] + nodeDriverRegistrar: image: # -- The OCI registry to pull the image from diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/README.md b/charts/spire/charts/spiffe-oidc-discovery-provider/README.md index dd1e23d..a4b0917 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/README.md +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/README.md @@ -41,8 +41,7 @@ A Helm chart to install the SPIFFE OIDC discovery provider. | config.acme.directoryUrl | string | `"https://acme-v02.api.letsencrypt.org/directory"` | | | config.acme.emailAddress | string | `"letsencrypt@example.org"` | | | config.acme.tosAccepted | bool | `false` | | -| config.domains[0] | string | `"localhost"` | | -| config.domains[1] | string | `"oidc-discovery.example.org"` | | +| config.additionalDomains | list | `["localhost"]` | Add additional domains that can be used for oidc discovery | | config.logLevel | string | `"info"` | The log level, valid values are "debug", "info", "warn", and "error" | | configMap.annotations | object | `{}` | Annotations to add to the SPIFFE OIDC Discovery Provider ConfigMap | | fullnameOverride | string | `""` | | @@ -66,6 +65,7 @@ A Helm chart to install the SPIFFE OIDC discovery provider. | insecureScheme.nginx.image.tag | string | `"1.24.0-alpine"` | Overrides the image tag | | insecureScheme.nginx.image.version | string | `""` | This value is deprecated in favor of tag. (Will be removed in a future release) | | insecureScheme.nginx.resources | object | `{}` | | +| jwtIssuer | string | `"oidc-discovery.example.org"` | | | livenessProbe.initialDelaySeconds | int | `5` | Initial delay seconds for livenessProbe | | livenessProbe.periodSeconds | int | `5` | Period seconds for livenessProbe | | nameOverride | string | `""` | | diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/templates/configmap.yaml b/charts/spire/charts/spiffe-oidc-discovery-provider/templates/configmap.yaml index eb39513..4c219e9 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/templates/configmap.yaml +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/templates/configmap.yaml @@ -8,9 +8,8 @@ domains: - "{{ include "spiffe-oidc-discovery-provider.fullname" . }}" - "{{ include "spiffe-oidc-discovery-provider.fullname" . }}.{{ include "spiffe-oidc-discovery-provider.namespace" . }}" - "{{ include "spiffe-oidc-discovery-provider.fullname" . }}.{{ include "spiffe-oidc-discovery-provider.namespace" . }}.svc.{{ include "spire-lib.cluster-domain" . }}" - {{- if gt (len .Values.config.domains) 0 }} - {{- .Values.config.domains | toYaml | nindent 2 }} - {{- end }} + {{- $jwtIssuer := include "spire-lib.jwt-issuer" . }} + {{- uniq (concat (list $jwtIssuer) .Values.config.additionalDomains) | toYaml | nindent 2 }} {{- if .Values.insecureScheme.enabled }} allow_insecure_scheme: {{ .Values.insecureScheme.enabled }} diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/templates/deployment.yaml b/charts/spire/charts/spiffe-oidc-discovery-provider/templates/deployment.yaml index bf40dd9..4110a83 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/templates/deployment.yaml +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/templates/deployment.yaml @@ -15,11 +15,11 @@ spec: {{- include "spiffe-oidc-discovery-provider.selectorLabels" . | nindent 6 }} template: metadata: - {{- with .Values.podAnnotations }} annotations: checksum/config: {{ $configSum }} + {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} - {{- end }} + {{- end }} labels: {{- include "spiffe-oidc-discovery-provider.selectorLabels" . | nindent 8 }} spec: diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/templates/pre-delete-hook.yaml b/charts/spire/charts/spiffe-oidc-discovery-provider/templates/pre-delete-hook.yaml index 6b2af69..29016f6 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/templates/pre-delete-hook.yaml +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/templates/pre-delete-hook.yaml @@ -13,6 +13,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: {{ include "spiffe-oidc-discovery-provider.fullname" . }}-pre-delete + namespace: {{ include "spiffe-oidc-discovery-provider.namespace" . }} annotations: "helm.sh/hook": pre-delete "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed @@ -26,6 +27,7 @@ kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ include "spiffe-oidc-discovery-provider.fullname" . }}-pre-delete + namespace: {{ include "spiffe-oidc-discovery-provider.namespace" . }} annotations: "helm.sh/hook": pre-delete "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/templates/tests/test-connection.yaml b/charts/spire/charts/spiffe-oidc-discovery-provider/templates/tests/test-connection.yaml index 3c028d8..393cafe 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/templates/tests/test-connection.yaml +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/templates/tests/test-connection.yaml @@ -33,7 +33,7 @@ spec: - name: curl-ingress image: {{ template "spire-lib.image" (dict "image" .Values.tests.bash.image "global" .Values.global) }} command: ['curl'] - args: ['-s', '-f', 'http://{{ index .Values.config.domains 0 }}/.well-known/openid-configuration'] + args: ['-s', '-f', 'http://{{ (index .Values.ingress.hosts 0).host }}/.well-known/openid-configuration'] securityContext: {{- toYaml .Values.securityContext | nindent 8 }} {{- end }} diff --git a/charts/spire/charts/spiffe-oidc-discovery-provider/values.yaml b/charts/spire/charts/spiffe-oidc-discovery-provider/values.yaml index 5b9fa08..07d683a 100644 --- a/charts/spire/charts/spiffe-oidc-discovery-provider/values.yaml +++ b/charts/spire/charts/spiffe-oidc-discovery-provider/values.yaml @@ -104,12 +104,14 @@ insecureScheme: # cpu: 100m # memory: 64Mi +jwtIssuer: oidc-discovery.example.org + config: # -- The log level, valid values are "debug", "info", "warn", and "error" logLevel: info - domains: - - localhost - - oidc-discovery.example.org + # -- Add additional domains that can be used for oidc discovery + additionalDomains: + - localhost acme: tosAccepted: false diff --git a/charts/spire/charts/spire-agent/README.md b/charts/spire/charts/spire-agent/README.md index 63da2b5..fc4e18e 100644 --- a/charts/spire/charts/spire-agent/README.md +++ b/charts/spire/charts/spire-agent/README.md @@ -75,6 +75,7 @@ A Helm chart to install the SPIRE agent. | telemetry.prometheus.podMonitor.labels | object | `{}` | | | telemetry.prometheus.podMonitor.namespace | string | `""` | Override where to install the podMonitor, if not set will use the same namespace as the spire-agent | | telemetry.prometheus.port | int | `9988` | | +| tolerations | list | `[]` | | | trustBundleFormat | string | `"pem"` | If using trustBundleURL, what format is the url. Choices are "pem" and "spiffe" | | trustBundleURL | string | `""` | If set, obtain trust bundle from url instead of Kubernetes ConfigMap | | trustDomain | string | `"example.org"` | The trust domain to be used for the SPIFFE identifiers | diff --git a/charts/spire/charts/spire-agent/templates/daemonset.yaml b/charts/spire/charts/spire-agent/templates/daemonset.yaml index 075d743..f1687e6 100644 --- a/charts/spire/charts/spire-agent/templates/daemonset.yaml +++ b/charts/spire/charts/spire-agent/templates/daemonset.yaml @@ -110,6 +110,10 @@ spec: nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} volumes: - name: spire-config configMap: diff --git a/charts/spire/charts/spire-agent/values.yaml b/charts/spire/charts/spire-agent/values.yaml index 0d6f913..9653d91 100644 --- a/charts/spire/charts/spire-agent/values.yaml +++ b/charts/spire/charts/spire-agent/values.yaml @@ -62,6 +62,8 @@ resources: {} nodeSelector: {} +tolerations: [] + # -- The log level, valid values are "debug", "info", "warn", and "error" logLevel: info # -- The name of the Kubernetes cluster (`kubeadm init --service-dns-domain`) diff --git a/charts/spire/charts/spire-server/README.md b/charts/spire/charts/spire-server/README.md index 0f581a1..f0208c3 100644 --- a/charts/spire/charts/spire-server/README.md +++ b/charts/spire/charts/spire-server/README.md @@ -28,6 +28,59 @@ A Helm chart to install the SPIRE server. * +## Tornjak + +Tornjak is the UI and Control Plane for SPIRE [https://github.com/spiffe/tornjak](https://github.com/spiffe/tornjak) and it is composed of two components: + +* Backend (this chart) - Tornjak APIs that extend SPIRE APIs with Control Plane functionality +* [Frontend](../tornjak-frontend/README.md) - Tornjak UI + +When Tornjak is enabled, it is exposed on both http and https (if TLS server certs are configured). Tornjak handles a permanent redirect from `http` to `https` to ensure users always use the https endpoint. + +In addition, you can configure a `client certificate authority`, this will make Tornjak backend verify Client certificates signed by this authority to enable mTLS authentication. + +**Warning**: For production, we recommend configuring TLS certificates and client CA to protect Tornjak from unauthorized access. + +### Tornjak with TLS Connection Type + +TLS connection requires Tornjak to have access to TLS key and certificate. +Complete instruction on creating your own TLS certificate can be found [here](https://github.com/spiffe/tornjak/blob/main/examples/tls_mtls/README.md). +TLS Certificate and the private key must be provided to Tornjak via *TLS Secret*. Prior to deploying this Helm chart, create TLS Secret in the deployment namespace (e.g. `spire-server`) + +```console +kubectl -n spire-server create secret tls tornjak-tls-secret --cert=client.crt --key=client.key +``` + +Once the charts are deployed, you can test the TLS connection with the following command (assuming localhost): + +```console +curl --cacert CA/rootCA.crt https://localhost:10443 +``` + +### Tornjak with mTLS Connection Type + +mTLS connection allows Tornjak server validation by client and Tornjak client validation by Tornjak server. The server validation is identical to above TLS. Follow the steps to create +TLS secret with key and the certificate. + +Additionally, you must provide the user CA to Tornjak server via `Secret` or `ConfigMap`. +Follow the steps to [create user CA for mTLS](https://github.com/spiffe/tornjak/blob/main/examples/tls_mtls/README.md), then create a *Secret* (or *ConfigMap*) prior to deploying this Helm chart. + +Here is an example using a *Secret* in `spire-server` namespace: + +```console +kubectl -n spire-server create secret generic tornjak-client-ca --from-file=ca.crt="CA/rootCA.crt" +``` + +Once the charts are deployed, you can test the mTLS connection with the following command (assuming localhost): + +```console +curl --cacert CA/rootCA.crt --key client.key --cert client.crt https://localhost:10443 +``` + +### Tornjak with HTTP Connection Type + +In order to run Tornjak with simple HTTP Connection only, make sure you don't create any `Secrets` or `ConfigMaps` listed above. + ## Values | Key | Type | Default | Description | @@ -145,7 +198,10 @@ A Helm chart to install the SPIRE server. | tools.kubectl.image.tag | string | `""` | Overrides the image tag | | tools.kubectl.image.version | string | `""` | This value is deprecated in favor of tag. (Will be removed in a future release) | | topologySpreadConstraints | list | `[]` | | -| tornjak.config.dataStore | object | `{"driver":"sqlite3","file":"/run/spire/data/tornjak.sqlite3"}` | persistent DB for storing Tornjak specific information | +| tornjak.config.clientCA.name | string | `"tornjak-client-ca"` | | +| tornjak.config.clientCA.type | string | `"Secret"` | Type of delivery for the user CA for mTLS client verification options are `Secret` or `ConfigMap` (required for `mtls` connectionType) | +| tornjak.config.dataStore | object | `{"driver":"sqlite3","file":"/run/spire/data/tornjak.sqlite3"}` | Persistent DB for storing Tornjak specific information | +| tornjak.config.tlsSecret | string | `"tornjak-tls-secret"` | Name of the secret containing server side key and certificate for TLS verification (required for `tls` or `mtls` connectionType) | | tornjak.enabled | bool | `false` | Deploys Tornjak API (backend) (Not for production) | | tornjak.image.pullPolicy | string | `"IfNotPresent"` | The Tornjak image pull policy | | tornjak.image.registry | string | `"ghcr.io"` | The OCI registry to pull the Tornjak image from | @@ -154,7 +210,7 @@ A Helm chart to install the SPIRE server. | tornjak.image.version | string | `""` | This value is deprecated in favor of tag. (Will be removed in a future release) | | tornjak.resources | object | `{}` | | | tornjak.service.annotations | object | `{}` | | -| tornjak.service.port | int | `10000` | | +| tornjak.service.ports | object | `{"http":10080,"https":10443}` | Ports for tornjak | | tornjak.service.type | string | `"ClusterIP"` | | | tornjak.startupProbe.failureThreshold | int | `3` | | | tornjak.startupProbe.initialDelaySeconds | int | `5` | Initial delay seconds for | diff --git a/charts/spire/charts/spire-server/README.md.gotmpl b/charts/spire/charts/spire-server/README.md.gotmpl index 712d68b..c66ec6f 100644 --- a/charts/spire/charts/spire-server/README.md.gotmpl +++ b/charts/spire/charts/spire-server/README.md.gotmpl @@ -23,6 +23,59 @@ {{ template "chart.requirementsSection" . }} +## Tornjak + +Tornjak is the UI and Control Plane for SPIRE [https://github.com/spiffe/tornjak](https://github.com/spiffe/tornjak) and it is composed of two components: + +* Backend (this chart) - Tornjak APIs that extend SPIRE APIs with Control Plane functionality +* [Frontend](../tornjak-frontend/README.md) - Tornjak UI + +When Tornjak is enabled, it is exposed on both http and https (if TLS server certs are configured). Tornjak handles a permanent redirect from `http` to `https` to ensure users always use the https endpoint. + +In addition, you can configure a `client certificate authority`, this will make Tornjak backend verify Client certificates signed by this authority to enable mTLS authentication. + +**Warning**: For production, we recommend configuring TLS certificates and client CA to protect Tornjak from unauthorized access. + +### Tornjak with TLS Connection Type + +TLS connection requires Tornjak to have access to TLS key and certificate. +Complete instruction on creating your own TLS certificate can be found [here](https://github.com/spiffe/tornjak/blob/main/examples/tls_mtls/README.md). +TLS Certificate and the private key must be provided to Tornjak via *TLS Secret*. Prior to deploying this Helm chart, create TLS Secret in the deployment namespace (e.g. `spire-server`) + +```console +kubectl -n spire-server create secret tls tornjak-tls-secret --cert=client.crt --key=client.key +``` + +Once the charts are deployed, you can test the TLS connection with the following command (assuming localhost): + +```console +curl --cacert CA/rootCA.crt https://localhost:10443 +``` + +### Tornjak with mTLS Connection Type + +mTLS connection allows Tornjak server validation by client and Tornjak client validation by Tornjak server. The server validation is identical to above TLS. Follow the steps to create +TLS secret with key and the certificate. + +Additionally, you must provide the user CA to Tornjak server via `Secret` or `ConfigMap`. +Follow the steps to [create user CA for mTLS](https://github.com/spiffe/tornjak/blob/main/examples/tls_mtls/README.md), then create a *Secret* (or *ConfigMap*) prior to deploying this Helm chart. + +Here is an example using a *Secret* in `spire-server` namespace: + +```console +kubectl -n spire-server create secret generic tornjak-client-ca --from-file=ca.crt="CA/rootCA.crt" +``` + +Once the charts are deployed, you can test the mTLS connection with the following command (assuming localhost): + +```console +curl --cacert CA/rootCA.crt --key client.key --cert client.crt https://localhost:10443 +``` + +### Tornjak with HTTP Connection Type + +In order to run Tornjak with simple HTTP Connection only, make sure you don't create any `Secrets` or `ConfigMaps` listed above. + {{ template "chart.valuesSection" . }} ---------------------------------------------- diff --git a/charts/spire/charts/spire-server/templates/NOTES.txt b/charts/spire/charts/spire-server/templates/NOTES.txt index 1c00883..8de0ce2 100644 --- a/charts/spire/charts/spire-server/templates/NOTES.txt +++ b/charts/spire/charts/spire-server/templates/NOTES.txt @@ -15,9 +15,23 @@ Tornjak runs without authentication and is therefore NOT suitable to run in prod Only use in test environments! Access Tornjak: + kubectl -n {{ include "spire-server.namespace" . }} port-forward service/{{ include "spire-tornjak.servicename" . }} {{ .Values.tornjak.service.ports.http }}:10080 +{{- if eq (include "spire-tornjak.connectionType" .) "http" }} + Open browser to: http://localhost:{{ .Values.tornjak.service.ports.http }} +{{- else if eq (include "spire-tornjak.connectionType" .) "tls" }} + Open browser to: https://localhost:{{ .Values.tornjak.service.ports.https }} - kubectl -n {{ include "spire-server.namespace" . }} port-forward service/{{ include "spire-tornjak.backend" . }} {{ .Values.tornjak.service.port }}:10000 + *** NOTE: You might get a security warning if using self-signed certificate + or use curl: -Open browser to: http://localhost:{{ .Values.tornjak.service.port }} + curl --cacert certs/ca.crt https://localhost:{{ .Values.tornjak.service.ports.https }} + {{- if eq (include "spire-tornjak.connectionType" .) "mtls" }} + Or provide a client certificate and key to use mTLS authentication: + + curl --cacert certs/ca.crt --key client.key --cert client.crt https://localhost:{{ .Values.tornjak.service.ports.https }} + {{- end }} +{{- else }} + ERROR! Incorrect value selected for "Values.tornjak.config.connectionType" +{{- end }} {{- end }} diff --git a/charts/spire/charts/spire-server/templates/_helpers.tpl b/charts/spire/charts/spire-server/templates/_helpers.tpl index 15874a7..2e2e7a1 100644 --- a/charts/spire/charts/spire-server/templates/_helpers.tpl +++ b/charts/spire/charts/spire-server/templates/_helpers.tpl @@ -168,3 +168,29 @@ Tornjak specific section {{- define "spire-tornjak.backend" -}} {{ include "spire-tornjak.fullname" . }}-backend {{- end }} + +{{/* +Tornjak automatically determines the connection type based on provided configuration. +When TLS Secret is provided, it enables TLS connection. +When TLS Secret and User CA Secret (or ConfigMap) are provided, it enables mTLS connection. +Otherwise it starts HTTP Connection +The code below determines what connection type should be used. +*/}} +{{- define "spire-tornjak.connectionType" -}} + +{{- if (lookup "v1" "Secret" (include "spire-server.namespace" .) .Values.tornjak.config.tlsSecret) -}} + +{{- $caType := default "INVALID" .Values.tornjak.config.clientCA.type }} +{{- if (lookup "v1" $caType (include "spire-server.namespace" .) .Values.tornjak.config.clientCA.name) -}} +{{- printf "mtls" -}} +{{- else }} +{{- printf "tls" -}} +{{- end -}} +{{- else -}} +{{- printf "http" -}} +{{- end -}} +{{- end -}} + +{{- define "spire-tornjak.servicename" -}} +{{- include "spire-tornjak.backend" . -}} +{{- end -}} diff --git a/charts/spire/charts/spire-server/templates/configmap.yaml b/charts/spire/charts/spire-server/templates/configmap.yaml index 704f16d..431adb3 100644 --- a/charts/spire/charts/spire-server/templates/configmap.yaml +++ b/charts/spire/charts/spire-server/templates/configmap.yaml @@ -7,7 +7,7 @@ server: trust_domain: {{ include "spire-lib.trust-domain" . | quote }} data_dir: "/run/spire/data" log_level: {{ .Values.logLevel | quote }} - jwt_issuer: {{ .Values.jwtIssuer | quote }} + jwt_issuer: {{ include "spire-lib.jwt-issuer" . | quote }} ca_key_type: {{ .Values.caKeyType | quote }} ca_ttl: {{ .Values.caTTL | quote }} diff --git a/charts/spire/charts/spire-server/templates/statefulset.yaml b/charts/spire/charts/spire-server/templates/statefulset.yaml index 842b927..4a5e148 100644 --- a/charts/spire/charts/spire-server/templates/statefulset.yaml +++ b/charts/spire/charts/spire-server/templates/statefulset.yaml @@ -175,20 +175,25 @@ spec: {{- toYaml .Values.controllerManager.securityContext | nindent 12 }} image: {{ template "spire-lib.image" (dict "appVersion" $.Chart.AppVersion "image" .Values.tornjak.image "global" .Values.global) }} imagePullPolicy: {{ .Values.tornjak.image.pullPolicy }} + {{- if eq (include "spire-tornjak.connectionType" .) "http" }} startupProbe: httpGet: scheme: HTTP path: /api/tornjak/serverinfo - port: 10000 + port: 10080 {{- toYaml .Values.tornjak.startupProbe | nindent 12 }} + {{- end }} args: - --spire-config - /run/spire/config/server.conf - --tornjak-config - /run/spire/tornjak-config/server.conf ports: - - name: tornjak - containerPort: 10000 + - name: tornjak-http + containerPort: 10080 + protocol: TCP + - name: tornjak-https + containerPort: 10443 protocol: TCP resources: {{- toYaml .Values.tornjak.resources | nindent 12 }} @@ -204,6 +209,14 @@ spec: - name: spire-data mountPath: /run/spire/data readOnly: false + {{- if or (eq (include "spire-tornjak.connectionType" .) "tls") (eq (include "spire-tornjak.connectionType" .) "mtls") }} + - name: server-cert + mountPath: /opt/spire/server + {{- end }} + {{- if eq (include "spire-tornjak.connectionType" .) "mtls" }} + - name: user-cert + mountPath: /opt/spire/user + {{- end }} {{- end }} {{- if gt (len .Values.extraContainers) 0 }} @@ -233,6 +246,24 @@ spec: emptyDir: {} - name: spire-controller-manager-tmp emptyDir: {} + {{- if or (eq (include "spire-tornjak.connectionType" .) "tls") (eq (include "spire-tornjak.connectionType" .) "mtls") }} + - name: server-cert + secret: + defaultMode: 256 + secretName: {{ .Values.tornjak.config.tlsSecret }} + {{- end }} + {{- if eq (include "spire-tornjak.connectionType" .) "mtls" }} + {{- if eq .Values.tornjak.config.clientCA.type "Secret" }} + - name: user-cert + secret: + defaultMode: 256 + secretName: {{ .Values.tornjak.config.clientCA.name }} + {{- else if eq .Values.tornjak.config.clientCA.type "ConfigMap" }} + - name: user-cert + configMap: + name: {{ .Values.tornjak.config.clientCA.name }} + {{- end }} + {{- end }} {{- if eq (.Values.upstreamAuthority.disk.enabled | toString) "true" }} - name: upstream-ca secret: diff --git a/charts/spire/charts/spire-server/templates/tests/test-tornjak-connection.yaml b/charts/spire/charts/spire-server/templates/tests/test-tornjak-connection.yaml index 9c9e6cd..e35ab37 100644 --- a/charts/spire/charts/spire-server/templates/tests/test-tornjak-connection.yaml +++ b/charts/spire/charts/spire-server/templates/tests/test-tornjak-connection.yaml @@ -1,4 +1,5 @@ {{- if eq (.Values.tornjak.enabled | toString) "true" }} +{{- if eq (include "spire-tornjak.connectionType" .) "http" }} apiVersion: v1 kind: Pod metadata: @@ -15,14 +16,15 @@ spec: - name: curl-tornjak-backend image: {{ template "spire-lib.image" (dict "image" .Values.tests.bash.image "global" .Values.global) }} command: ['curl'] - args: ['-k', '-s', '-f', 'http://{{ include "spire-tornjak.backend" . }}.{{ include "spire-server.namespace" . }}.svc.{{ include "spire-lib.cluster-domain" . }}:{{ .Values.tornjak.service.port }}/api/tornjak/serverinfo'] + args: ['-k', '-s', '-f', 'http://{{ include "spire-tornjak.servicename" . }}.{{ include "spire-server.namespace" . }}.svc.{{ include "spire-lib.cluster-domain" . }}:{{ .Values.tornjak.service.ports.http }}/api/tornjak/serverinfo'] securityContext: {{- toYaml .Values.securityContext | nindent 8 }} - name: curl-tornjak-backend-and-spire image: {{ template "spire-lib.image" (dict "image" .Values.tests.bash.image "global" .Values.global) }} command: ['curl'] - args: ['-k', '-s', '-f', 'http://{{ include "spire-tornjak.backend" . }}.{{ include "spire-server.namespace" . }}.svc.{{ include "spire-lib.cluster-domain" . }}:{{ .Values.tornjak.service.port }}/api/healthcheck'] + args: ['-k', '-s', '-f', 'http://{{ include "spire-tornjak.servicename" . }}.{{ include "spire-server.namespace" . }}.svc.{{ include "spire-lib.cluster-domain" . }}:{{ .Values.tornjak.service.ports.http }}/api/healthcheck'] securityContext: {{- toYaml .Values.securityContext | nindent 8 }} restartPolicy: Never {{- end }} +{{- end }} diff --git a/charts/spire/charts/spire-server/templates/tornjak-config.yaml b/charts/spire/charts/spire-server/templates/tornjak-config.yaml index 16a8f61..3f86455 100644 --- a/charts/spire/charts/spire-server/templates/tornjak-config.yaml +++ b/charts/spire/charts/spire-server/templates/tornjak-config.yaml @@ -8,11 +8,29 @@ data: server.conf: | server { spire_socket_path = "unix:///tmp/spire-server/private/api.sock" # socket to communicate with SPIRE server - + {{- if eq (include "spire-tornjak.connectionType" .) "http" }} http { enabled = true # if true, opens HTTP server - port = "10000" # if HTTP enabled, opens HTTP listen port at container port 10000 + port = "10080" # if HTTP enabled, opens HTTP listen port at specified container port } + {{- end }} + {{- if eq (include "spire-tornjak.connectionType" .) "tls" }} + tls { + enabled = true + port = "10443" # container port for TLS connection + cert = "/opt/spire/server/tls.crt" # TLS server cert + key = "/opt/spire/server/tls.key" # TLS server key + } + {{- end }} + {{- if eq (include "spire-tornjak.connectionType" .) "mtls" }} + mtls { + enabled = true + port = "10443" # container port for mTLS connection + cert = "/opt/spire/server/tls.crt" # mTLS server cert + key = "/opt/spire/server/tls.key" # mTLS server key + ca = "/opt/spire/user/ca.crt" # mTLS user CA + } + {{- end }} } plugins { diff --git a/charts/spire/charts/spire-server/templates/tornjak-service.yaml b/charts/spire/charts/spire-server/templates/tornjak-service.yaml index a4a95bd..6606861 100644 --- a/charts/spire/charts/spire-server/templates/tornjak-service.yaml +++ b/charts/spire/charts/spire-server/templates/tornjak-service.yaml @@ -3,7 +3,7 @@ apiVersion: v1 kind: Service metadata: namespace: {{ include "spire-server.namespace" . }} - name: {{ include "spire-tornjak.backend" . }} + name: {{ include "spire-tornjak.servicename" . }} {{- with .Values.tornjak.service.annotations }} annotations: {{- toYaml . | nindent 8 }} @@ -15,8 +15,12 @@ spec: selector: {{- include "spire-server.selectorLabels" . | nindent 4 }} ports: - - name: {{ include "spire-tornjak.backend" . }} - port: {{ .Values.tornjak.service.port }} - targetPort: tornjak + - name: tornjak-srv-http + port: {{ .Values.tornjak.service.ports.http }} + targetPort: tornjak-http + protocol: TCP + - name: tornjak-srv-https + port: {{ .Values.tornjak.service.ports.https }} + targetPort: tornjak-https protocol: TCP {{- end }} diff --git a/charts/spire/charts/spire-server/values.yaml b/charts/spire/charts/spire-server/values.yaml index c859ddc..3472027 100644 --- a/charts/spire/charts/spire-server/values.yaml +++ b/charts/spire/charts/spire-server/values.yaml @@ -344,7 +344,7 @@ nodeAttestor: enabled: true serviceAccountAllowList: [] -# tornjak - Tornjak specific configuration +# tornjak - Tornjak default values tornjak: # -- Deploys Tornjak API (backend) (Not for production) enabled: false @@ -359,9 +359,13 @@ tornjak: version: "" # -- Overrides the image tag tag: "v1.2.2" + service: type: ClusterIP - port: 10000 + # -- Ports for tornjak + ports: + http: 10080 + https: 10443 annotations: {} startupProbe: @@ -372,11 +376,29 @@ tornjak: successThreshold: 1 timeoutSeconds: 5 + # tornjak - Tornjak default values config: - # -- persistent DB for storing Tornjak specific information + # -- Persistent DB for storing Tornjak specific information dataStore: driver: "sqlite3" file: "/run/spire/data/tornjak.sqlite3" + + # Tornjak supports 3 connection types: `http`, `tls`, and `mtls`. + # The connections are determined based on provided configuration + # When `tlsSecret` is created in this chart namespace, the TLS connection is started + # When `tlsSecret` and `clientCA.tornjak-client-ca` are created in this chart namespace, the mTLS connection is started + # When none of them are created, Tornjak starts with HTTP connection only + + # -- Name of the secret containing server side key and certificate for TLS verification + # (required for `tls` or `mtls` connectionType) + tlsSecret: tornjak-tls-secret + clientCA: + # -- Type of delivery for the user CA for mTLS client verification + # options are `Secret` or `ConfigMap` + # (required for `mtls` connectionType) + type: Secret + name: tornjak-client-ca + resources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little diff --git a/charts/spire/charts/tornjak-frontend/README.md b/charts/spire/charts/tornjak-frontend/README.md index b380e34..45aba9a 100644 --- a/charts/spire/charts/tornjak-frontend/README.md +++ b/charts/spire/charts/tornjak-frontend/README.md @@ -21,13 +21,20 @@ A Helm chart to deploy Tornjak frontend | Tornjak | `1.0.x` | | Helm | `3.x` | +## Tornjak + +Tornjak is the UI and Control Plane for SPIRE [https://github.com/spiffe/tornjak](https://github.com/spiffe/tornjak) and it is composed of two components: + +* [Backend](../spire-server/README.md) - Tornjak APIs that extend SPIRE APIs with Control Plane functionality +* Frontend (this chart) - Tornjak UI + ## Prerequisites This chart requires access to Tornjak Backend (`tornjakFrontend.apiServerURL`). This URL needs to be reachable from your web browser and can therefore not be a cluster internal URL. Obtain the URL for Tornjak APIs. If deployed in the same cluster, locally, -Tornjak APIs are typically available at `http://localhost:10000`. +Tornjak APIs are typically available at `http://localhost:10080`. Review Tornjak documentation for more details. ## Usage diff --git a/charts/spire/charts/tornjak-frontend/README.md.gotmpl b/charts/spire/charts/tornjak-frontend/README.md.gotmpl index 152b7dc..5e1d258 100644 --- a/charts/spire/charts/tornjak-frontend/README.md.gotmpl +++ b/charts/spire/charts/tornjak-frontend/README.md.gotmpl @@ -23,13 +23,20 @@ | Tornjak | `1.0.x` | | Helm | `3.x` | +## Tornjak + +Tornjak is the UI and Control Plane for SPIRE [https://github.com/spiffe/tornjak](https://github.com/spiffe/tornjak) and it is composed of two components: + +* [Backend](../spire-server/README.md) - Tornjak APIs that extend SPIRE APIs with Control Plane functionality +* Frontend (this chart) - Tornjak UI + ## Prerequisites This chart requires access to Tornjak Backend (`tornjakFrontend.apiServerURL`). This URL needs to be reachable from your web browser and can therefore not be a cluster internal URL. Obtain the URL for Tornjak APIs. If deployed in the same cluster, locally, -Tornjak APIs are typically available at `http://localhost:10000`. +Tornjak APIs are typically available at `http://localhost:10080`. Review Tornjak documentation for more details. ## Usage diff --git a/charts/spire/ci/external-mysql-values.yaml b/charts/spire/ci/external-mysql-values.yaml new file mode 100644 index 0000000..adc5c25 --- /dev/null +++ b/charts/spire/ci/external-mysql-values.yaml @@ -0,0 +1,11 @@ +spire-server: + dataStore: + sql: + databaseType: mysql + databaseName: spire-server + username: spire + password: sp1ff3Test + host: mysql.mysql + port: 3306 + options: + - parseTime: true diff --git a/charts/spire/ci/external-postgres-values.yaml b/charts/spire/ci/external-postgres-values.yaml new file mode 100644 index 0000000..f8a7068 --- /dev/null +++ b/charts/spire/ci/external-postgres-values.yaml @@ -0,0 +1,11 @@ +spire-server: + dataStore: + sql: + databaseType: postgres + databaseName: spire-server + username: spire + password: sp1ff3Test + host: postgresql.postgresql + port: 5432 + options: + - sslmode: disable diff --git a/.github/tests/extras/values.yaml b/charts/spire/ci/extras-values.yaml similarity index 100% rename from .github/tests/extras/values.yaml rename to charts/spire/ci/extras-values.yaml diff --git a/.github/tests/federation-bundle-endpoint/values.yaml b/charts/spire/ci/federation-bundle-endpoint-values.yaml similarity index 100% rename from .github/tests/federation-bundle-endpoint/values.yaml rename to charts/spire/ci/federation-bundle-endpoint-values.yaml diff --git a/.github/tests/namespace-override/values.yaml b/charts/spire/ci/namespace-override-values-skip.yaml similarity index 100% rename from .github/tests/namespace-override/values.yaml rename to charts/spire/ci/namespace-override-values-skip.yaml diff --git a/.github/tests/no-spire-controller-manager/values.yaml b/charts/spire/ci/no-spire-controller-manager-values.yaml similarity index 100% rename from .github/tests/no-spire-controller-manager/values.yaml rename to charts/spire/ci/no-spire-controller-manager-values.yaml diff --git a/.github/tests/spire-oidc-insecure/values.yaml b/charts/spire/ci/oidc-values.yaml similarity index 62% rename from .github/tests/spire-oidc-insecure/values.yaml rename to charts/spire/ci/oidc-values.yaml index 86f7159..8164ef2 100644 --- a/.github/tests/spire-oidc-insecure/values.yaml +++ b/charts/spire/ci/oidc-values.yaml @@ -8,14 +8,14 @@ spire-server: nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" hosts: - - host: ingress-nginx-controller.spire-oidc-insecure + - host: ingress-nginx-controller.ingress-nginx paths: - path: / pathType: Prefix spire-agent: server: - address: ingress-nginx-controller.spire-oidc-insecure + address: ingress-nginx-controller.ingress-nginx port: 443 spiffe-oidc-discovery-provider: @@ -25,8 +25,9 @@ spiffe-oidc-discovery-provider: enabled: true config: - domains: - - ingress-nginx-controller + additionalDomains: + - ingress-nginx-controller.ingress-nginx + - ingress-nginx-controller.ingress-nginx.svc.cluster.local acme: tosAccepted: false @@ -35,7 +36,7 @@ spiffe-oidc-discovery-provider: enabled: true className: nginx hosts: - - host: ingress-nginx-controller - paths: - - path: / - pathType: Prefix + - host: ingress-nginx-controller.ingress-nginx.svc.cluster.local + paths: + - path: / + pathType: Prefix diff --git a/.github/tests/prometheus/values.yaml b/charts/spire/ci/prometheus-values.yaml similarity index 100% rename from .github/tests/prometheus/values.yaml rename to charts/spire/ci/prometheus-values.yaml diff --git a/charts/spire/ci/tornjak-values.yaml b/charts/spire/ci/tornjak-values.yaml new file mode 100644 index 0000000..5991a5d --- /dev/null +++ b/charts/spire/ci/tornjak-values.yaml @@ -0,0 +1,6 @@ +spire-server: + tornjak: + enabled: true + +tornjak-frontend: + enabled: true diff --git a/.github/tests/upstream-authority-cert-manager/values.yaml b/charts/spire/ci/upstream-authority-cert-manager-values.yaml similarity index 100% rename from .github/tests/upstream-authority-cert-manager/values.yaml rename to charts/spire/ci/upstream-authority-cert-manager-values.yaml diff --git a/.github/tests/upstream-authority-disk/values.yaml b/charts/spire/ci/upstream-authority-disk-values.yaml similarity index 100% rename from .github/tests/upstream-authority-disk/values.yaml rename to charts/spire/ci/upstream-authority-disk-values.yaml diff --git a/charts/spire/templates/_spire-lib.tpl b/charts/spire/templates/_spire-lib.tpl index 1084125..2c78351 100644 --- a/charts/spire/templates/_spire-lib.tpl +++ b/charts/spire/templates/_spire-lib.tpl @@ -14,6 +14,14 @@ {{- end }} {{- end }} +{{- define "spire-lib.jwt-issuer" }} +{{- if ne (len (dig "spire" "jwtIssuer" "" .Values.global)) 0 }} +{{- .Values.global.spire.jwtIssuer }} +{{- else }} +{{- .Values.jwtIssuer }} +{{- end }} +{{- end }} + {{- define "spire-lib.bundle-configmap" }} {{- if ne (len (dig "spire" "bundleConfigMap" "" .Values.global)) 0 }} {{- .Values.global.spire.bundleConfigMap }} diff --git a/charts/spire/values.yaml b/charts/spire/values.yaml index c6ba849..11b7fe0 100644 --- a/charts/spire/values.yaml +++ b/charts/spire/values.yaml @@ -8,6 +8,8 @@ global: clusterName: example-cluster # -- The trust domain to be used for the SPIFFE identifiers trustDomain: example.org + # -- Set the jwt issuer + jwtIssuer: oidc-discovery.example.org # -- Override all instances of bundleConfigMap bundleConfigMap: "" diff --git a/examples/external-mysql/run-tests.sh b/examples/external-mysql/run-tests.sh new file mode 100755 index 0000000..b6b5ee5 --- /dev/null +++ b/examples/external-mysql/run-tests.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -xe + +SCRIPT="$(readlink -f "$0")" +SCRIPTPATH="$(dirname "${SCRIPT}")" +TESTDIR="${SCRIPTPATH}/../../.github/tests" +DEPS="${TESTDIR}/dependencies" + +# shellcheck source=/dev/null +source "${SCRIPTPATH}/../../.github/scripts/parse-versions.sh" +# shellcheck source=/dev/null +source "${TESTDIR}/common.sh" + +helm_install=(helm upgrade --install --create-namespace) +ns=spire-system + +teardown() { + helm uninstall --namespace "${ns}" spire 2>/dev/null || true + kubectl delete ns "${ns}" 2>/dev/null || true + + helm uninstall --namespace mysql mysql 2>/dev/null || true + kubectl delete ns mysql 2>/dev/null || true +} + +trap 'trap - SIGTERM && teardown' SIGINT SIGTERM EXIT + +"${helm_install[@]}" mysql mysql --version "$VERSION_MYSQL" --repo "$HELM_REPO_MYSQL" \ + --namespace mysql \ + --values "${DEPS}/mysql.yaml" \ + --wait + +"${helm_install[@]}" --namespace "${ns}" --values "${SCRIPTPATH}/values.yaml" \ + --set 'spire-server.dataStore.sql.password=sp1ff3Test' --wait spire charts/spire +helm test --namespace "${ns}" spire + +print_helm_releases +print_spire_workload_status "${ns}" + +if [[ "$1" -ne 0 ]]; then + get_namespace_details "${ns}" +fi diff --git a/examples/external-mysql/values.yaml b/examples/external-mysql/values.yaml index c0a8fff..129ee27 100644 --- a/examples/external-mysql/values.yaml +++ b/examples/external-mysql/values.yaml @@ -2,7 +2,8 @@ spire-server: dataStore: sql: databaseType: mysql - databaseName: spire - host: mysql + databaseName: spire-server + host: mysql.mysql port: 3306 username: spire + # password: CHANGE_ME diff --git a/examples/external-postgresql/run-tests.sh b/examples/external-postgresql/run-tests.sh new file mode 100755 index 0000000..1ffe1f6 --- /dev/null +++ b/examples/external-postgresql/run-tests.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -xe + +SCRIPT="$(readlink -f "$0")" +SCRIPTPATH="$(dirname "${SCRIPT}")" +TESTDIR="${SCRIPTPATH}/../../.github/tests" +DEPS="${TESTDIR}/dependencies" + +# shellcheck source=/dev/null +source "${SCRIPTPATH}/../../.github/scripts/parse-versions.sh" +# shellcheck source=/dev/null +source "${TESTDIR}/common.sh" + +helm_install=(helm upgrade --install --create-namespace) +ns=spire-system + +teardown() { + helm uninstall --namespace "${ns}" spire 2>/dev/null || true + kubectl delete ns "${ns}" 2>/dev/null || true + + helm uninstall --namespace postgresql postgresql 2>/dev/null || true + kubectl delete ns postgresql 2>/dev/null || true +} + +trap 'trap - SIGTERM && teardown' SIGINT SIGTERM EXIT + +"${helm_install[@]}" postgresql postgresql --version "$VERSION_POSTGRESQL" --repo "$HELM_REPO_POSTGRESQL" \ + --namespace postgresql \ + --values "${DEPS}/postgresql.yaml" \ + --wait + +"${helm_install[@]}" --namespace "${ns}" --values "${SCRIPTPATH}/values.yaml" \ + --set 'spire-server.dataStore.sql.password=sp1ff3Test' --wait spire charts/spire +helm test --namespace "${ns}" spire + +print_helm_releases +print_spire_workload_status "${ns}" + +if [[ "$1" -ne 0 ]]; then + get_namespace_details "${ns}" +fi diff --git a/examples/external-postgresql/values.yaml b/examples/external-postgresql/values.yaml index 5f1fcfa..8972e87 100644 --- a/examples/external-postgresql/values.yaml +++ b/examples/external-postgresql/values.yaml @@ -2,9 +2,10 @@ spire-server: dataStore: sql: databaseType: postgres - databaseName: spire - host: postgresql + databaseName: spire-server + host: postgresql.postgresql port: 5432 username: spire + # password: CHANGE_ME options: - sslmode: disable diff --git a/examples/production/run-tests.sh b/examples/production/run-tests.sh new file mode 100755 index 0000000..f64f6c2 --- /dev/null +++ b/examples/production/run-tests.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -xe + +SCRIPT="$(readlink -f "$0")" +SCRIPTPATH="$(dirname "${SCRIPT}")" +TESTDIR="${SCRIPTPATH}/../../.github/tests" + +# shellcheck source=/dev/null +source "${TESTDIR}/common.sh" + +helm_install=(helm upgrade --install --create-namespace) +ns=spire-server + +teardown() { + helm uninstall --namespace "${ns}" spire 2>/dev/null || true + kubectl delete ns "${ns}" 2>/dev/null || true + kubectl delete ns spire-system 2>/dev/null || true +} + +trap 'trap - SIGTERM && teardown' SIGINT SIGTERM EXIT + +kubectl create namespace spire-system 2>/dev/null || true +kubectl label namespace spire-system pod-security.kubernetes.io/enforce=privileged || true +kubectl create namespace "${ns}" 2>/dev/null || true +kubectl label namespace "${ns}" pod-security.kubernetes.io/enforce=restricted || true + +"${helm_install[@]}" --namespace "${ns}" --values "${SCRIPTPATH}/values.yaml" --wait spire charts/spire +helm test --namespace "${ns}" spire + +print_helm_releases +print_spire_workload_status "${ns}" + +if [[ "$1" -ne 0 ]]; then + get_namespace_details "${ns}" +fi diff --git a/examples/production/values.yaml b/examples/production/values.yaml index 4ddb95b..0b10ab1 100644 --- a/examples/production/values.yaml +++ b/examples/production/values.yaml @@ -71,6 +71,8 @@ spire-agent: spiffe-oidc-discovery-provider: enabled: true + config: + additionalDomains: [] insecureScheme: enabled: true podSecurityContext: diff --git a/examples/tornjak/run-tests.sh b/examples/tornjak/run-tests.sh new file mode 100755 index 0000000..e4449cd --- /dev/null +++ b/examples/tornjak/run-tests.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +set -xe + +SCRIPT="$(readlink -f "$0")" +SCRIPTPATH="$(dirname "${SCRIPT}")" +TESTDIR="${SCRIPTPATH}/../../.github/tests" + +# shellcheck source=/dev/null +source "${TESTDIR}/common.sh" + +helm_install=(helm upgrade --install --create-namespace) +ns=spire-system + +teardown() { + helm uninstall --namespace "${ns}" spire 2>/dev/null || true + kubectl delete ns "${ns}" 2>/dev/null || true +} + +trap 'trap - SIGTERM && teardown' SIGINT SIGTERM EXIT + +"${helm_install[@]}" --namespace "${ns}" --values "${SCRIPTPATH}/values.yaml" --wait spire charts/spire +helm test --namespace "${ns}" spire + +print_helm_releases +print_spire_workload_status "${ns}" + +if [[ "$1" -ne 0 ]]; then + get_namespace_details "${ns}" +fi diff --git a/tests/go.mod b/tests/go.mod new file mode 100644 index 0000000..c13d8a1 --- /dev/null +++ b/tests/go.mod @@ -0,0 +1,71 @@ +module github.com/spiffe/helm-charts/tests + +go 1.20 + +require ( + github.com/onsi/ginkgo/v2 v2.9.4 + github.com/onsi/gomega v1.27.6 + helm.sh/helm/v3 v3.11.3 +) + +require ( + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/cyphar/filepath-securejoin v0.2.3 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful/v3 v3.10.1 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/swag v0.19.14 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + golang.org/x/crypto v0.5.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/oauth2 v0.4.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/term v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + golang.org/x/tools v0.8.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.26.2 // indirect + k8s.io/apiextensions-apiserver v0.26.0 // indirect + k8s.io/apimachinery v0.26.2 // indirect + k8s.io/client-go v0.26.2 // indirect + k8s.io/klog/v2 v2.90.1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/tests/go.sum b/tests/go.sum new file mode 100644 index 0000000..0078965 --- /dev/null +++ b/tests/go.sum @@ -0,0 +1,291 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= +github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +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= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE= +github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM= +github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= +github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +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= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +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= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +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.11.3 h1:n1X5yaQTP5DYywlBOZMl2gX398Gp6YwFp/IAVj6+5D4= +helm.sh/helm/v3 v3.11.3/go.mod h1:S+sOdQc3BLvt09a9rSlKKVs9x0N/yx+No0y3qFw+FQ8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ= +k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= +k8s.io/apiextensions-apiserver v0.26.0 h1:Gy93Xo1eg2ZIkNX/8vy5xviVSxwQulsnUdQ00nEdpDo= +k8s.io/apiextensions-apiserver v0.26.0/go.mod h1:7ez0LTiyW5nq3vADtK6C3kMESxadD51Bh6uz3JOlqWQ= +k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= +k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI= +k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/tests/unit/main.go b/tests/unit/main.go new file mode 100644 index 0000000..67177cf --- /dev/null +++ b/tests/unit/main.go @@ -0,0 +1 @@ +package unit diff --git a/tests/unit/spire_test.go b/tests/unit/spire_test.go new file mode 100644 index 0000000..417b7c2 --- /dev/null +++ b/tests/unit/spire_test.go @@ -0,0 +1,44 @@ +package unit_test + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + helmchart "helm.sh/helm/v3/pkg/chart" + helmloader "helm.sh/helm/v3/pkg/chart/loader" + helmutil "helm.sh/helm/v3/pkg/chartutil" + helmengine "helm.sh/helm/v3/pkg/engine" +) + +func ValueStringRender(chart *helmchart.Chart, values string) (map[string]string, error) { + v, err := helmutil.ReadValues([]byte(values)) + if err != nil { + return nil, err + } + ro := helmutil.ReleaseOptions{Name: "spire", Namespace: "spire-server", Revision: 1, IsUpgrade: false, IsInstall: true} + v, err = helmutil.ToRenderValues(chart, v, ro, helmutil.DefaultCapabilities); + if err != nil { + return nil, err + } + objs, err := helmengine.Render(chart, v) + return objs, err +} + +var _ = Describe("Spire", func() { + chart, err := helmloader.Load("../../charts/spire") + Expect(err).Should(Succeed()) + Describe("spire-server.upstream.cert-manager", func() { + It("issuer_name when set is passed through", func() { + objs, err := ValueStringRender(chart, ` +spire-server: + upstreamAuthority: + certManager: + enabled: true + issuer_name: abc123 +`) + Expect(err).Should(Succeed()) + notes := objs["spire/charts/spire-server/templates/configmap.yaml"] + Expect(notes).Should(ContainSubstring("abc123")) + }) + }) +}) diff --git a/tests/unit/unit_suite_test.go b/tests/unit/unit_suite_test.go new file mode 100644 index 0000000..5c7f177 --- /dev/null +++ b/tests/unit/unit_suite_test.go @@ -0,0 +1,13 @@ +package unit_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestUnit(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Unit Suite") +}