diff --git a/test/integration/common b/test/integration/common index baf0b7d13f..eef46d56b9 100644 --- a/test/integration/common +++ b/test/integration/common @@ -224,7 +224,7 @@ download-kind() { elif [ "${ARCH}" = "aarch64" ]; then ARCH=arm64 fi - echo "Ensuring kind version $KINDVERSION is available..." + echo "Ensuring kind version $KINDVERSION is available..." KINDURL="https://github.com/kubernetes-sigs/kind/releases/download/$KINDVERSION/kind-$UNAME-$ARCH" local kind_link_or_path=$1 @@ -247,7 +247,7 @@ download-helm() { ARCH=arm64 fi - echo "Ensuring helm version $HELMVERSION is available..." + echo "Ensuring helm version $HELMVERSION is available..." HELMURL="https://get.helm.sh/helm-${HELMVERSION}-${UNAME}-${ARCH}.tar.gz" local helm_link_or_path=$1 @@ -274,7 +274,7 @@ download-kubectl() { ARCH=arm64 fi - KUBECTLURL="https://storage.googleapis.com/kubernetes-release/release/$WANTVERSION/bin/$UNAME/$ARCH/kubectl" + KUBECTLURL="https://dl.k8s.io/release//$WANTVERSION/bin/$UNAME/$ARCH/kubectl" HAVEVERSION="" if [ -x "${KUBECTLPATH}" ]; then diff --git a/test/integration/suites/key-manager-vault/00-setup-kind b/test/integration/suites/key-manager-vault/00-setup-kind new file mode 100755 index 0000000000..eac0016c0d --- /dev/null +++ b/test/integration/suites/key-manager-vault/00-setup-kind @@ -0,0 +1,33 @@ +#!/bin/bash + +# Create a temporary path that will be added to the PATH to avoid picking up +# binaries from the environment that aren't a version match. +mkdir -p ./bin + +KINDVERSION=v0.24.0 +KUBECTLVERSION=v1.31.2 +K8SIMAGE=kindest/node:v1.31.0 +HELMVERSION=v3.16.2 + +KIND_PATH=./bin/kind +KUBECTL_PATH=./bin/kubectl +HELM_PATH=./bin/helm + +# Download kind at the expected version at the given path. +download-kind "${KIND_PATH}" + +# Download kubectl at the expected version. +download-kubectl "${KUBECTL_PATH}" + +# Download helm at the expected version. +download-helm "${HELM_PATH}" + +# Start the kind cluster. +start-kind-cluster "${KIND_PATH}" vault-test + +# Load the given images in the cluster. +container_images=("spire-server:latest-local") +load-images "${KIND_PATH}" vault-test "${container_images[@]}" + +# Set the kubectl context. +set-kubectl-context "${KUBECTL_PATH}" kind-vault-test diff --git a/test/integration/suites/key-manager-vault/01-setup-vault b/test/integration/suites/key-manager-vault/01-setup-vault new file mode 100755 index 0000000000..fd295725c2 --- /dev/null +++ b/test/integration/suites/key-manager-vault/01-setup-vault @@ -0,0 +1,102 @@ +#!/bin/bash + +set -e -o pipefail + +source init-kubectl + +CHARTVERSION=0.28.1 + +log-info "installing hashicorp vault..." + +kubectl-exec-vault() { + ./bin/kubectl exec -n vault vault-0 -- $@ +} + +log-info "preparing certificates..." +# Prepare CSR for Vault instance +openssl ecparam -name prime256v1 -genkey -noout -out vault_key.pem +openssl req -new \ + -key vault_key.pem \ + -out vault_csr.pem \ + -subj "/C=US/O=system:nodes/CN=system:node:vault" \ + -reqexts v3 \ + -config <(cat /etc/ssl/openssl.cnf ; printf "\n[v3]\nsubjectAltName=@alt_names\n[alt_names]\nDNS.1=vault\nDNS.2=vault.vault.svc\nIP.1=127.0.0.1") +cat > csr.yaml </dev/null) ]]; do sleep 1; done' +./bin/kubectl get csr -n vault vault.svc -o jsonpath='{.status.certificate}' | openssl base64 -d -A -out vault.pem +./bin/kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' \ + | base64 -d > vault_ca.pem +./bin/kubectl create secret generic vault-tls -n vault \ + --from-file=vault_key.pem=vault_key.pem \ + --from-file=vault.pem=vault.pem \ + --from-file=vault_ca.pem=vault_ca.pem + +./bin/helm repo add hashicorp https://helm.releases.hashicorp.com +./bin/helm install vault hashicorp/vault --namespace vault --version $CHARTVERSION -f conf/helm-values.yaml +./bin/kubectl wait -n kube-system --for=condition=available deployment --all --timeout=90s +./bin/kubectl wait pods -n vault --for=jsonpath='{.status.phase}'=Running vault-0 --timeout=90s + +# Initialize and unseal +log-info "initializing hashicorp vault..." +kubectl-exec-vault vault operator init -key-shares=1 -key-threshold=1 -format=json > cluster-keys.json +VAULT_UNSEAL_KEY=$(cat cluster-keys.json | jq -r ".unseal_keys_b64[]") +kubectl-exec-vault vault operator unseal $VAULT_UNSEAL_KEY +./bin/kubectl wait pods -n vault --for=condition=Ready vault-0 --timeout=60s +VAULT_ROOT_TOKEN=$(cat cluster-keys.json | jq -r ".root_token") +kubectl-exec-vault vault login $VAULT_ROOT_TOKEN > /dev/null + +./bin/kubectl cp -n vault cert_auth_ca.pem vault-0:/tmp/. +./bin/kubectl cp -n vault conf/configure-transit-secret-engine.sh vault-0:/tmp/. +./bin/kubectl cp -n vault conf/spire.hcl vault-0:tmp/. +./bin/kubectl cp -n vault conf/configure-auth-method.sh vault-0:/tmp/. + +# Configure Vault +log-info "configuring transit secret engine..." +kubectl-exec-vault /tmp/configure-transit-secret-engine.sh +log-info "configuring auth methods..." +kubectl-exec-vault /tmp/configure-auth-method.sh diff --git a/test/integration/suites/key-manager-vault/02-deploy-spire-and-verify-auth b/test/integration/suites/key-manager-vault/02-deploy-spire-and-verify-auth new file mode 100755 index 0000000000..a760bff610 --- /dev/null +++ b/test/integration/suites/key-manager-vault/02-deploy-spire-and-verify-auth @@ -0,0 +1,46 @@ +#!/bin/bash + +set -e -o pipefail + +./bin/kubectl create namespace spire +./bin/kubectl create secret -n spire generic vault-tls \ + --from-file=vault_ca.pem=vault_ca.pem + +# Verify AppRole Auth +log-info "verifying approle auth..." +APPROLE_ID=$(./bin/kubectl exec -n vault vault-0 -- vault read --format json auth/approle/role/spire/role-id | jq -r .data.role_id) +SECRET_ID=$(./bin/kubectl exec -n vault vault-0 -- vault write --format json -f auth/approle/role/spire/secret-id | jq -r .data.secret_id) +./bin/kubectl create secret -n spire generic vault-credential \ + --from-literal=approle_id=$APPROLE_ID \ + --from-literal=secret_id=$SECRET_ID +./bin/kubectl apply -k ./conf/server/approle-auth +./bin/kubectl wait pods -n spire -l app=spire-server --for condition=Ready --timeout=60s +./bin/kubectl delete -k ./conf/server/approle-auth +./bin/kubectl delete secret -n spire vault-credential +./bin/kubectl wait pods -n spire -l app=spire-server --for=delete --timeout=60s + +# Verify K8s Auth +log-info "verifying k8s auth..." +./bin/kubectl apply -k ./conf/server/k8s-auth +./bin/kubectl wait pods -n spire -l app=spire-server --for condition=Ready --timeout=60s +./bin/kubectl delete -k ./conf/server/k8s-auth +./bin/kubectl wait pods -n spire -l app=spire-server --for=delete --timeout=60s + +# Verify Cert Auth +log-info "verifying cert auth..." +./bin/kubectl create secret -n spire generic vault-credential \ + --from-file=client.pem=client.pem \ + --from-file=client_key.pem=client_key.pem +./bin/kubectl apply -k ./conf/server/cert-auth +./bin/kubectl wait pods -n spire -l app=spire-server --for condition=Ready --timeout=60s +./bin/kubectl delete -k ./conf/server/cert-auth +./bin/kubectl delete secret -n spire vault-credential +./bin/kubectl wait pods -n spire -l app=spire-server --for=delete --timeout=60s + +# Verify Token Auth +log-info "verifying token auth..." +TOKEN=$(./bin/kubectl exec -n vault vault-0 -- vault token create -policy=spire -ttl=1m -field=token) +./bin/kubectl create secret -n spire generic vault-credential \ + --from-literal=token=$TOKEN +./bin/kubectl apply -k ./conf/server/token-auth +./bin/kubectl wait pods -n spire -l app=spire-server --for condition=Ready --timeout=60s diff --git a/test/integration/suites/key-manager-vault/04-verify-token-renewal.sh b/test/integration/suites/key-manager-vault/04-verify-token-renewal.sh new file mode 100755 index 0000000000..a467e4bd50 --- /dev/null +++ b/test/integration/suites/key-manager-vault/04-verify-token-renewal.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -eo pipefail + +log-debug "verifying token renewal..." + +timeout=$(date -ud "1 minute 30 second" +%s) +count=0 + +while [ $(date -u +%s) -lt $timeout ]; do + count=`./bin/kubectl logs -n spire $(./bin/kubectl get pod -n spire -o name) | echo "$(grep "Successfully renew auth token" || [[ $? == 1 ]])" | wc -l` + if [ $count -ge 2 ]; then + log-info "token renewal is verified" + exit 0 + fi + sleep 10 +done + +fail-now "expected number of token renewal log not found" diff --git a/test/integration/suites/key-manager-vault/README.md b/test/integration/suites/key-manager-vault/README.md new file mode 100644 index 0000000000..5f4809397f --- /dev/null +++ b/test/integration/suites/key-manager-vault/README.md @@ -0,0 +1,9 @@ +# KeyManager HashiCorp Vault plugin suite + +## Description + +This suite sets up a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io), +installs HashiCorp Vault. It then asserts the following: + +* SPIRE server successfully requests a key from the referenced Vault Transit Secret Engine +* Verifies that Auth Methods are configured successfully diff --git a/test/integration/suites/key-manager-vault/conf/configure-auth-method.sh b/test/integration/suites/key-manager-vault/conf/configure-auth-method.sh new file mode 100755 index 0000000000..82bb9bc22f --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/configure-auth-method.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +set -e -o pipefail + +# Create Policy +vault policy write spire /tmp/spire.hcl + +# Configure Vault Auth Method +vault auth enable approle +vault write auth/approle/role/spire \ + secret_id_ttl=120m \ + token_ttl=1m \ + policies="spire" + +# Configure K8s Auth Method +vault auth enable kubernetes +vault write auth/kubernetes/config kubernetes_host=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT_HTTPS +vault write auth/kubernetes/role/my-role \ + bound_service_account_names=spire-server \ + bound_service_account_namespaces=spire \ + token_ttl=1m \ + policies=spire + +# Configure Cert Auth Method +vault auth enable cert +vault write auth/cert/certs/my-role \ + display_name=spire \ + token_ttl=1m \ + policies=spire \ + certificate=@/tmp/cert_auth_ca.pem diff --git a/test/integration/suites/key-manager-vault/conf/configure-transit-secret-engine.sh b/test/integration/suites/key-manager-vault/conf/configure-transit-secret-engine.sh new file mode 100755 index 0000000000..ddcd987a13 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/configure-transit-secret-engine.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e -o pipefail + +# Configure Root CA +vault secrets enable transit +vault secrets tune -max-lease-ttl=8760h transit diff --git a/test/integration/suites/key-manager-vault/conf/helm-values.yaml b/test/integration/suites/key-manager-vault/conf/helm-values.yaml new file mode 100644 index 0000000000..6607a9cbad --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/helm-values.yaml @@ -0,0 +1,33 @@ +global: + enabled: true + tlsDisable: false +server: + extraEnvironmentVars: + VAULT_CACERT: /vault/userconfig/vault-tls/vault_ca.pem + VAULT_TLSCERT: /vault/userconfig/vault-tls/vault.pem + VAULT_TLSKEY: /vault/userconfig/vault-tls/vault_key.pem + volumes: + - name: userconfig-vault-tls + secret: + defaultMode: 420 + secretName: vault-tls + volumeMounts: + - mountPath: /vault/userconfig/vault-tls + name: userconfig-vault-tls + readOnly: true + standalone: + enabled: "-" + config: | + listener "tcp" { + address = "[::]:8200" + cluster_address = "[::]:8201" + + tls_cert_file = "/vault/userconfig/vault-tls/vault.pem" + tls_key_file = "/vault/userconfig/vault-tls/vault_key.pem" + + tls_disable_client_certs = false + } + + storage "file" { + path = "/vault/data" + } diff --git a/test/integration/suites/key-manager-vault/conf/server/approle-auth/kustomization.yaml b/test/integration/suites/key-manager-vault/conf/server/approle-auth/kustomization.yaml new file mode 100644 index 0000000000..fca71c7ae2 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/approle-auth/kustomization.yaml @@ -0,0 +1,8 @@ +# kustomization.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../base +patchesStrategicMerge: + - spire-server.yaml diff --git a/test/integration/suites/key-manager-vault/conf/server/approle-auth/spire-server.yaml b/test/integration/suites/key-manager-vault/conf/server/approle-auth/spire-server.yaml new file mode 100644 index 0000000000..af2ea53eed --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/approle-auth/spire-server.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-server + namespace: spire +data: + server.conf: | + server { + bind_address = "0.0.0.0" + bind_port = "8081" + trust_domain = "example.org" + data_dir = "/run/spire/data" + log_level = "DEBUG" + default_x509_svid_ttl = "1h" + ca_ttl = "12h" + ca_subject { + country = ["US"] + organization = ["SPIFFE"] + common_name = "" + } + } + + plugins { + DataStore "sql" { + plugin_data { + database_type = "sqlite3" + connection_string = "/run/spire/data/datastore.sqlite3" + } + } + + NodeAttestor "k8s_psat" { + plugin_data { + clusters = { + "example-cluster" = { + service_account_allow_list = ["spire:spire-agent"] + } + } + } + } + + KeyManager "hashicorp_vault" { + plugin_data { + vault_addr="https://vault.vault.svc:8200/" + ca_cert_path="/run/spire/vault/vault_ca.pem" + pki_mount_point="pki_int" + approle_auth {} + } + } + + Notifier "k8sbundle" { + plugin_data { + # This plugin updates the bundle.crt value in the spire:spire-bundle + # ConfigMap by default, so no additional configuration is necessary. + } + } + } + + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } + +--- + +# This is the Deployment for the SPIRE server. It waits for SPIRE database to +# initialize and uses the SPIRE healthcheck command for liveness/readiness +# probes. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spire-server + namespace: spire + labels: + app: spire-server +spec: + template: + spec: + containers: + - name: spire-server + env: + - name: VAULT_APPROLE_ID + valueFrom: + secretKeyRef: + name: vault-credential + key: approle_id + - name: VAULT_APPROLE_SECRET_ID + valueFrom: + secretKeyRef: + name: vault-credential + key: secret_id diff --git a/test/integration/suites/key-manager-vault/conf/server/base/kustomization.yaml b/test/integration/suites/key-manager-vault/conf/server/base/kustomization.yaml new file mode 100644 index 0000000000..c87a9a25d0 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/base/kustomization.yaml @@ -0,0 +1,10 @@ +# kustomization.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +# list of Resource Config to be Applied +resources: + - spire-server.yaml + +# namespace to deploy all Resources to +namespace: spire diff --git a/test/integration/suites/key-manager-vault/conf/server/base/spire-server.yaml b/test/integration/suites/key-manager-vault/conf/server/base/spire-server.yaml new file mode 100644 index 0000000000..05b8bfe53c --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/base/spire-server.yaml @@ -0,0 +1,243 @@ +# ServiceAccount used by the SPIRE server. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: spire-server + namespace: spire + +--- + +# Required cluster role to allow spire-server to query k8s API server +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-cluster-role +rules: + - apiGroups: [""] + resources: ["pods", "nodes"] + verbs: ["get", "list", "watch"] + +--- + +# Binds above cluster role to spire-server service account +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-cluster-role-binding + namespace: spire +subjects: + - kind: ServiceAccount + name: spire-server + namespace: spire +roleRef: + kind: ClusterRole + name: spire-server-cluster-role + apiGroup: rbac.authorization.k8s.io + +--- + +# Role for the SPIRE server +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + namespace: spire + name: spire-server-role +rules: + # allow "get" access to pods (to resolve selectors for PSAT attestation) + - apiGroups: [""] + resources: ["pods"] + verbs: ["get"] + # allow access to "get" and "patch" the spire-bundle ConfigMap (for SPIRE + # agent bootstrapping, see the spire-bundle ConfigMap below) + - apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["spire-bundle"] + verbs: ["get", "patch"] + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["create"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create", "update", "get"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create"] + +--- + +# RoleBinding granting the spire-server-role to the SPIRE server +# service account. +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: spire-server-role-binding + namespace: spire +subjects: + - kind: ServiceAccount + name: spire-server + namespace: spire +roleRef: + kind: Role + name: spire-server-role + apiGroup: rbac.authorization.k8s.io + +--- + +# ConfigMap containing the latest trust bundle for the trust domain. It is +# updated by SPIRE using the k8sbundle notifier plugin. SPIRE agents mount +# this config map and use the certificate to bootstrap trust with the SPIRE +# server during attestation. +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-bundle + namespace: spire + +--- + +# ConfigMap containing the SPIRE server configuration. +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-server + namespace: spire +data: + server.conf: | + server { + bind_address = "0.0.0.0" + bind_port = "8081" + trust_domain = "example.org" + data_dir = "/run/spire/data" + log_level = "DEBUG" + default_x509_svid_ttl = "1h" + ca_ttl = "12h" + ca_subject { + country = ["US"] + organization = ["SPIFFE"] + common_name = "" + } + } + + plugins { + DataStore "sql" { + plugin_data { + database_type = "sqlite3" + connection_string = "/run/spire/data/datastore.sqlite3" + } + } + + NodeAttestor "k8s_psat" { + plugin_data { + clusters = { + "example-cluster" = { + service_account_allow_list = ["spire:spire-agent"] + } + } + } + } + + KeyManager "disk" { + plugin_data { + keys_path = "/run/spire/data/keys.json" + } + } + + UpstreamAuthority "vault" { + plugin_data { + vault_addr="http://vault.vault.svc:8200/" + token_auth {} + } + } + + Notifier "k8sbundle" { + plugin_data { + # This plugin updates the bundle.crt value in the spire:spire-bundle + # ConfigMap by default, so no additional configuration is necessary. + } + } + } + + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } + +--- + +# This is the Deployment for the SPIRE server. It waits for SPIRE database to +# initialize and uses the SPIRE healthcheck command for liveness/readiness +# probes. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spire-server + namespace: spire + labels: + app: spire-server +spec: + replicas: 1 + selector: + matchLabels: + app: spire-server + template: + metadata: + namespace: spire + labels: + app: spire-server + spec: + serviceAccountName: spire-server + shareProcessNamespace: true + containers: + - name: spire-server + image: spire-server:latest-local + imagePullPolicy: Never + args: ["-config", "/run/spire/config/server.conf"] + ports: + - containerPort: 8081 + volumeMounts: + - name: spire-config + mountPath: /run/spire/config + readOnly: true + - name: vault-tls + mountPath: "/run/spire/vault" + readOnly: true + livenessProbe: + httpGet: + path: /live + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: spire-config + configMap: + name: spire-server + - name: vault-tls + secret: + secretName: vault-tls + +--- + +# Service definition for SPIRE server defining the gRPC port. +apiVersion: v1 +kind: Service +metadata: + name: spire-server + namespace: spire +spec: + type: NodePort + ports: + - name: grpc + port: 8081 + targetPort: 8081 + protocol: TCP + selector: + app: spire-server diff --git a/test/integration/suites/key-manager-vault/conf/server/cert-auth/kustomization.yaml b/test/integration/suites/key-manager-vault/conf/server/cert-auth/kustomization.yaml new file mode 100644 index 0000000000..fca71c7ae2 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/cert-auth/kustomization.yaml @@ -0,0 +1,8 @@ +# kustomization.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../base +patchesStrategicMerge: + - spire-server.yaml diff --git a/test/integration/suites/key-manager-vault/conf/server/cert-auth/spire-server.yaml b/test/integration/suites/key-manager-vault/conf/server/cert-auth/spire-server.yaml new file mode 100644 index 0000000000..975ca24e44 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/cert-auth/spire-server.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-server + namespace: spire +data: + server.conf: | + server { + bind_address = "0.0.0.0" + bind_port = "8081" + trust_domain = "example.org" + data_dir = "/run/spire/data" + log_level = "DEBUG" + default_x509_svid_ttl = "1h" + ca_ttl = "12h" + ca_subject { + country = ["US"] + organization = ["SPIFFE"] + common_name = "" + } + } + + plugins { + DataStore "sql" { + plugin_data { + database_type = "sqlite3" + connection_string = "/run/spire/data/datastore.sqlite3" + } + } + + NodeAttestor "k8s_psat" { + plugin_data { + clusters = { + "example-cluster" = { + service_account_allow_list = ["spire:spire-agent"] + } + } + } + } + + KeyManager "hashicorp_vault" { + plugin_data { + vault_addr="https://vault.vault.svc:8200/" + ca_cert_path="/run/spire/vault/vault_ca.pem" + pki_mount_point="pki_int" + cert_auth { + client_cert_path="/run/spire/vault-auth/client.pem" + client_key_path="/run/spire/vault-auth/client_key.pem" + } + } + } + + Notifier "k8sbundle" { + plugin_data { + # This plugin updates the bundle.crt value in the spire:spire-bundle + # ConfigMap by default, so no additional configuration is necessary. + } + } + } + + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } + +--- + +# This is the Deployment for the SPIRE server. It waits for SPIRE database to +# initialize and uses the SPIRE healthcheck command for liveness/readiness +# probes. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spire-server + namespace: spire + labels: + app: spire-server +spec: + template: + spec: + volumes: + - name: vault-credential + secret: + secretName: vault-credential + containers: + - name: spire-server + volumeMounts: + - name: vault-credential + mountPath: "/run/spire/vault-auth" + readOnly: true diff --git a/test/integration/suites/key-manager-vault/conf/server/k8s-auth/kustomization.yaml b/test/integration/suites/key-manager-vault/conf/server/k8s-auth/kustomization.yaml new file mode 100644 index 0000000000..fca71c7ae2 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/k8s-auth/kustomization.yaml @@ -0,0 +1,8 @@ +# kustomization.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../base +patchesStrategicMerge: + - spire-server.yaml diff --git a/test/integration/suites/key-manager-vault/conf/server/k8s-auth/spire-server.yaml b/test/integration/suites/key-manager-vault/conf/server/k8s-auth/spire-server.yaml new file mode 100644 index 0000000000..a964962596 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/k8s-auth/spire-server.yaml @@ -0,0 +1,67 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-server + namespace: spire +data: + server.conf: | + server { + bind_address = "0.0.0.0" + bind_port = "8081" + trust_domain = "example.org" + data_dir = "/run/spire/data" + log_level = "DEBUG" + default_x509_svid_ttl = "1h" + ca_ttl = "12h" + ca_subject { + country = ["US"] + organization = ["SPIFFE"] + common_name = "" + } + } + + plugins { + DataStore "sql" { + plugin_data { + database_type = "sqlite3" + connection_string = "/run/spire/data/datastore.sqlite3" + } + } + + NodeAttestor "k8s_psat" { + plugin_data { + clusters = { + "example-cluster" = { + service_account_allow_list = ["spire:spire-agent"] + } + } + } + } + + KeyManager "hashicorp_vault" { + plugin_data { + vault_addr="https://vault.vault.svc:8200/" + ca_cert_path="/run/spire/vault/vault_ca.pem" + pki_mount_point="pki_int" + k8s_auth { + k8s_auth_role_name = "my-role" + token_path = "/var/run/secrets/kubernetes.io/serviceaccount/token" + } + } + } + + Notifier "k8sbundle" { + plugin_data { + # This plugin updates the bundle.crt value in the spire:spire-bundle + # ConfigMap by default, so no additional configuration is necessary. + } + } + } + + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } diff --git a/test/integration/suites/key-manager-vault/conf/server/token-auth/kustomization.yaml b/test/integration/suites/key-manager-vault/conf/server/token-auth/kustomization.yaml new file mode 100644 index 0000000000..fca71c7ae2 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/token-auth/kustomization.yaml @@ -0,0 +1,8 @@ +# kustomization.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../base +patchesStrategicMerge: + - spire-server.yaml diff --git a/test/integration/suites/key-manager-vault/conf/server/token-auth/spire-server.yaml b/test/integration/suites/key-manager-vault/conf/server/token-auth/spire-server.yaml new file mode 100644 index 0000000000..3613ed7841 --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/server/token-auth/spire-server.yaml @@ -0,0 +1,88 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: spire-server + namespace: spire +data: + server.conf: | + server { + bind_address = "0.0.0.0" + bind_port = "8081" + trust_domain = "example.org" + data_dir = "/run/spire/data" + log_level = "DEBUG" + default_x509_svid_ttl = "1h" + ca_ttl = "12h" + ca_subject { + country = ["US"] + organization = ["SPIFFE"] + common_name = "" + } + } + + plugins { + DataStore "sql" { + plugin_data { + database_type = "sqlite3" + connection_string = "/run/spire/data/datastore.sqlite3" + } + } + + NodeAttestor "k8s_psat" { + plugin_data { + clusters = { + "example-cluster" = { + service_account_allow_list = ["spire:spire-agent"] + } + } + } + } + + KeyManager "hashicorp_vault" { + plugin_data { + vault_addr="https://vault.vault.svc:8200/" + ca_cert_path="/run/spire/vault/vault_ca.pem" + pki_mount_point="pki_int" + token_auth {} + } + } + + Notifier "k8sbundle" { + plugin_data { + # This plugin updates the bundle.crt value in the spire:spire-bundle + # ConfigMap by default, so no additional configuration is necessary. + } + } + } + + health_checks { + listener_enabled = true + bind_address = "0.0.0.0" + bind_port = "8080" + live_path = "/live" + ready_path = "/ready" + } + +--- + +# This is the Deployment for the SPIRE server. It waits for SPIRE database to +# initialize and uses the SPIRE healthcheck command for liveness/readiness +# probes. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spire-server + namespace: spire + labels: + app: spire-server +spec: + template: + spec: + containers: + - name: spire-server + env: + - name: VAULT_TOKEN + valueFrom: + secretKeyRef: + name: vault-credential + key: token diff --git a/test/integration/suites/key-manager-vault/conf/spire.hcl b/test/integration/suites/key-manager-vault/conf/spire.hcl new file mode 100644 index 0000000000..0f3bb2116a --- /dev/null +++ b/test/integration/suites/key-manager-vault/conf/spire.hcl @@ -0,0 +1,3 @@ +path "transit/*" { + capabilities = [ "create", "read", "update", "delete", "list" ] +} diff --git a/test/integration/suites/key-manager-vault/init-kubectl b/test/integration/suites/key-manager-vault/init-kubectl new file mode 100644 index 0000000000..a167777059 --- /dev/null +++ b/test/integration/suites/key-manager-vault/init-kubectl @@ -0,0 +1,8 @@ +#!/bin/bash + +KUBECONFIG="${RUNDIR}/kubeconfig" +if [ ! -f "${RUNDIR}/kubeconfig" ]; then + ./bin/kind get kubeconfig --name=vault-test > "${RUNDIR}/kubeconfig" +fi +export KUBECONFIG + diff --git a/test/integration/suites/key-manager-vault/teardown b/test/integration/suites/key-manager-vault/teardown new file mode 100755 index 0000000000..83c7ae74e5 --- /dev/null +++ b/test/integration/suites/key-manager-vault/teardown @@ -0,0 +1,10 @@ +#!/bin/bash + +source init-kubectl + +if [ -z "$SUCCESS" ]; then + ./bin/kubectl -nspire logs deployment/spire-server --all-containers || true +fi + +export KUBECONFIG= +./bin/kind delete cluster --name vault-test