Skip to content

Commit 27963a0

Browse files
InverseIntegralMarcosDY
authored andcommitted
Add KeyManager vault integration test (spiffe#5058)
Signed-off-by: Matteo Kamm <[email protected]>
1 parent 9ac73c1 commit 27963a0

22 files changed

+928
-2
lines changed

test/integration/common

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ download-kind() {
249249
elif [ "${ARCH}" = "aarch64" ]; then
250250
ARCH=arm64
251251
fi
252-
echo "Ensuring kind version $KINDVERSION is available..."
252+
echo "Ensuring kind version $KINDVERSION is available..."
253253
KINDURL="https://github.com/kubernetes-sigs/kind/releases/download/$KINDVERSION/kind-$UNAME-$ARCH"
254254

255255
local kind_link_or_path=$1
@@ -272,7 +272,7 @@ download-helm() {
272272
ARCH=arm64
273273
fi
274274

275-
echo "Ensuring helm version $HELMVERSION is available..."
275+
echo "Ensuring helm version $HELMVERSION is available..."
276276
HELMURL="https://get.helm.sh/helm-${HELMVERSION}-${UNAME}-${ARCH}.tar.gz"
277277

278278
local helm_link_or_path=$1
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
3+
# Create a temporary path that will be added to the PATH to avoid picking up
4+
# binaries from the environment that aren't a version match.
5+
mkdir -p ./bin
6+
7+
KINDVERSION=v0.24.0
8+
KUBECTLVERSION=v1.31.2
9+
K8SIMAGE=kindest/node:v1.31.0
10+
HELMVERSION=v3.16.2
11+
12+
KIND_PATH=./bin/kind
13+
KUBECTL_PATH=./bin/kubectl
14+
HELM_PATH=./bin/helm
15+
16+
# Download kind at the expected version at the given path.
17+
download-kind "${KIND_PATH}"
18+
19+
# Download kubectl at the expected version.
20+
download-kubectl "${KUBECTL_PATH}"
21+
22+
# Download helm at the expected version.
23+
download-helm "${HELM_PATH}"
24+
25+
# Start the kind cluster.
26+
start-kind-cluster "${KIND_PATH}" vault-test
27+
28+
# Load the given images in the cluster.
29+
container_images=("spire-server:latest-local")
30+
load-images "${KIND_PATH}" vault-test "${container_images[@]}"
31+
32+
# Set the kubectl context.
33+
set-kubectl-context "${KUBECTL_PATH}" kind-vault-test
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/bin/bash
2+
3+
set -e -o pipefail
4+
5+
source init-kubectl
6+
7+
CHARTVERSION=0.28.1
8+
9+
log-info "installing hashicorp vault..."
10+
11+
kubectl-exec-vault() {
12+
./bin/kubectl exec -n vault vault-0 -- $@
13+
}
14+
15+
log-info "preparing certificates..."
16+
# Prepare CSR for Vault instance
17+
openssl ecparam -name prime256v1 -genkey -noout -out vault_key.pem
18+
openssl req -new \
19+
-key vault_key.pem \
20+
-out vault_csr.pem \
21+
-subj "/C=US/O=system:nodes/CN=system:node:vault" \
22+
-reqexts v3 \
23+
-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")
24+
cat > csr.yaml <<EOF
25+
apiVersion: certificates.k8s.io/v1
26+
kind: CertificateSigningRequest
27+
metadata:
28+
name: vault.svc
29+
namespace: vault
30+
spec:
31+
signerName: kubernetes.io/kubelet-serving
32+
expirationSeconds: 8640000
33+
request: $(cat vault_csr.pem|base64|tr -d '\n')
34+
usages:
35+
- digital signature
36+
- key encipherment
37+
- server auth
38+
EOF
39+
40+
# Prepare certificates for Vault Cert Auth
41+
openssl ecparam -name prime256v1 -genkey -noout -out cert_auth_ca_key.pem
42+
openssl req -days 30 -x509 -new \
43+
-key cert_auth_ca_key.pem \
44+
-out cert_auth_ca.pem \
45+
-subj "/C=US/O=SPIFFE" \
46+
-extensions v3 \
47+
-config <(cat /etc/ssl/openssl.cnf ; printf "\n[v3]\nsubjectAltName=URI:spiffe://cert-auth-ca\nbasicConstraints=CA:true")
48+
openssl ecparam -name prime256v1 -genkey -noout -out client_key.pem
49+
openssl req -new \
50+
-key client_key.pem \
51+
-out client_csr.pem \
52+
-subj "/C=US/O=SPIFFE/CN=Cert Auth Client" \
53+
-config <(cat /etc/ssl/openssl.cnf ; printf "\n[v3]\nsubjectAltName=URI:spiffe://cert-auth-client")
54+
openssl x509 -days 10 -req \
55+
-CAcreateserial \
56+
-CA cert_auth_ca.pem \
57+
-CAkey cert_auth_ca_key.pem \
58+
-in client_csr.pem \
59+
-out client.pem \
60+
-sha256 \
61+
-extensions v3 \
62+
-extfile <(cat /etc/ssl/openssl.cnf ; printf "\n[v3]\nsubjectAltName=URI:spiffe://cert-auth-client")
63+
64+
# Install Vault
65+
log-info "installing hashicorp vault..."
66+
./bin/kubectl create namespace vault
67+
./bin/kubectl create -f csr.yaml
68+
./bin/kubectl certificate -n vault approve vault.svc
69+
log-debug "waiting for certificate to be issued by k8s..."
70+
timeout 30s bash -c 'while [[ -z $(./bin/kubectl get csr -n vault vault.svc -o jsonpath="{.status.certificate}" 2>/dev/null) ]]; do sleep 1; done'
71+
./bin/kubectl get csr -n vault vault.svc -o jsonpath='{.status.certificate}' | openssl base64 -d -A -out vault.pem
72+
./bin/kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' \
73+
| base64 -d > vault_ca.pem
74+
./bin/kubectl create secret generic vault-tls -n vault \
75+
--from-file=vault_key.pem=vault_key.pem \
76+
--from-file=vault.pem=vault.pem \
77+
--from-file=vault_ca.pem=vault_ca.pem
78+
79+
./bin/helm repo add hashicorp https://helm.releases.hashicorp.com
80+
./bin/helm install vault hashicorp/vault --namespace vault --version $CHARTVERSION -f conf/helm-values.yaml
81+
./bin/kubectl wait -n kube-system --for=condition=available deployment --all --timeout=90s
82+
./bin/kubectl wait pods -n vault --for=jsonpath='{.status.phase}'=Running vault-0 --timeout=90s
83+
84+
# Initialize and unseal
85+
log-info "initializing hashicorp vault..."
86+
kubectl-exec-vault vault operator init -key-shares=1 -key-threshold=1 -format=json > cluster-keys.json
87+
VAULT_UNSEAL_KEY=$(cat cluster-keys.json | jq -r ".unseal_keys_b64[]")
88+
kubectl-exec-vault vault operator unseal $VAULT_UNSEAL_KEY
89+
./bin/kubectl wait pods -n vault --for=condition=Ready vault-0 --timeout=60s
90+
VAULT_ROOT_TOKEN=$(cat cluster-keys.json | jq -r ".root_token")
91+
kubectl-exec-vault vault login $VAULT_ROOT_TOKEN > /dev/null
92+
93+
./bin/kubectl cp -n vault cert_auth_ca.pem vault-0:/tmp/.
94+
./bin/kubectl cp -n vault conf/configure-transit-secret-engine.sh vault-0:/tmp/.
95+
./bin/kubectl cp -n vault conf/spire.hcl vault-0:tmp/.
96+
./bin/kubectl cp -n vault conf/configure-auth-method.sh vault-0:/tmp/.
97+
98+
# Configure Vault
99+
log-info "configuring transit secret engine..."
100+
kubectl-exec-vault /tmp/configure-transit-secret-engine.sh
101+
log-info "configuring auth methods..."
102+
kubectl-exec-vault /tmp/configure-auth-method.sh
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
3+
set -e -o pipefail
4+
5+
./bin/kubectl create namespace spire
6+
./bin/kubectl create secret -n spire generic vault-tls \
7+
--from-file=vault_ca.pem=vault_ca.pem
8+
9+
# Verify AppRole Auth
10+
log-info "verifying approle auth..."
11+
APPROLE_ID=$(./bin/kubectl exec -n vault vault-0 -- vault read --format json auth/approle/role/spire/role-id | jq -r .data.role_id)
12+
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)
13+
./bin/kubectl create secret -n spire generic vault-credential \
14+
--from-literal=approle_id=$APPROLE_ID \
15+
--from-literal=secret_id=$SECRET_ID
16+
./bin/kubectl apply -k ./conf/server/approle-auth
17+
./bin/kubectl wait pods -n spire -l app=spire-server --for condition=Ready --timeout=60s
18+
./bin/kubectl delete -k ./conf/server/approle-auth
19+
./bin/kubectl delete secret -n spire vault-credential
20+
./bin/kubectl wait pods -n spire -l app=spire-server --for=delete --timeout=60s
21+
22+
# Verify K8s Auth
23+
log-info "verifying k8s auth..."
24+
./bin/kubectl apply -k ./conf/server/k8s-auth
25+
./bin/kubectl wait pods -n spire -l app=spire-server --for condition=Ready --timeout=60s
26+
./bin/kubectl delete -k ./conf/server/k8s-auth
27+
./bin/kubectl wait pods -n spire -l app=spire-server --for=delete --timeout=60s
28+
29+
# Verify Cert Auth
30+
log-info "verifying cert auth..."
31+
./bin/kubectl create secret -n spire generic vault-credential \
32+
--from-file=client.pem=client.pem \
33+
--from-file=client_key.pem=client_key.pem
34+
./bin/kubectl apply -k ./conf/server/cert-auth
35+
./bin/kubectl wait pods -n spire -l app=spire-server --for condition=Ready --timeout=60s
36+
./bin/kubectl delete -k ./conf/server/cert-auth
37+
./bin/kubectl delete secret -n spire vault-credential
38+
./bin/kubectl wait pods -n spire -l app=spire-server --for=delete --timeout=60s
39+
40+
# Verify Token Auth
41+
log-info "verifying token auth..."
42+
TOKEN=$(./bin/kubectl exec -n vault vault-0 -- vault token create -policy=spire -ttl=1m -field=token)
43+
./bin/kubectl create secret -n spire generic vault-credential \
44+
--from-literal=token=$TOKEN
45+
./bin/kubectl apply -k ./conf/server/token-auth
46+
./bin/kubectl wait pods -n spire -l app=spire-server --for condition=Ready --timeout=60s
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
set -eo pipefail
4+
5+
log-debug "verifying token renewal..."
6+
7+
timeout=$(date -ud "1 minute 30 second" +%s)
8+
count=0
9+
10+
while [ $(date -u +%s) -lt $timeout ]; do
11+
count=`./bin/kubectl logs -n spire $(./bin/kubectl get pod -n spire -o name) | echo "$(grep "Successfully renew auth token" || [[ $? == 1 ]])" | wc -l`
12+
if [ $count -ge 2 ]; then
13+
log-info "token renewal is verified"
14+
exit 0
15+
fi
16+
sleep 10
17+
done
18+
19+
fail-now "expected number of token renewal log not found"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# KeyManager HashiCorp Vault plugin suite
2+
3+
## Description
4+
5+
This suite sets up a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io),
6+
installs HashiCorp Vault. It then asserts the following:
7+
8+
* SPIRE server successfully requests a key from the referenced Vault Transit Secret Engine
9+
* Verifies that Auth Methods are configured successfully
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/sh
2+
3+
set -e -o pipefail
4+
5+
# Create Policy
6+
vault policy write spire /tmp/spire.hcl
7+
8+
# Configure Vault Auth Method
9+
vault auth enable approle
10+
vault write auth/approle/role/spire \
11+
secret_id_ttl=120m \
12+
token_ttl=1m \
13+
policies="spire"
14+
15+
# Configure K8s Auth Method
16+
vault auth enable kubernetes
17+
vault write auth/kubernetes/config kubernetes_host=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT_HTTPS
18+
vault write auth/kubernetes/role/my-role \
19+
bound_service_account_names=spire-server \
20+
bound_service_account_namespaces=spire \
21+
token_ttl=1m \
22+
policies=spire
23+
24+
# Configure Cert Auth Method
25+
vault auth enable cert
26+
vault write auth/cert/certs/my-role \
27+
display_name=spire \
28+
token_ttl=1m \
29+
policies=spire \
30+
certificate=@/tmp/cert_auth_ca.pem
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/sh
2+
3+
set -e -o pipefail
4+
5+
# Configure Root CA
6+
vault secrets enable transit
7+
vault secrets tune -max-lease-ttl=8760h transit
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
global:
2+
enabled: true
3+
tlsDisable: false
4+
server:
5+
extraEnvironmentVars:
6+
VAULT_CACERT: /vault/userconfig/vault-tls/vault_ca.pem
7+
VAULT_TLSCERT: /vault/userconfig/vault-tls/vault.pem
8+
VAULT_TLSKEY: /vault/userconfig/vault-tls/vault_key.pem
9+
volumes:
10+
- name: userconfig-vault-tls
11+
secret:
12+
defaultMode: 420
13+
secretName: vault-tls
14+
volumeMounts:
15+
- mountPath: /vault/userconfig/vault-tls
16+
name: userconfig-vault-tls
17+
readOnly: true
18+
standalone:
19+
enabled: "-"
20+
config: |
21+
listener "tcp" {
22+
address = "[::]:8200"
23+
cluster_address = "[::]:8201"
24+
25+
tls_cert_file = "/vault/userconfig/vault-tls/vault.pem"
26+
tls_key_file = "/vault/userconfig/vault-tls/vault_key.pem"
27+
28+
tls_disable_client_certs = false
29+
}
30+
31+
storage "file" {
32+
path = "/vault/data"
33+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# kustomization.yaml
2+
apiVersion: kustomize.config.k8s.io/v1beta1
3+
kind: Kustomization
4+
5+
resources:
6+
- ../base
7+
patchesStrategicMerge:
8+
- spire-server.yaml

0 commit comments

Comments
 (0)