Skip to content

Commit f95f32d

Browse files
authored
Merge pull request #1498 from gl-johnson/conjur-e2e
test: add e2e for conjur csi provider
2 parents 5f6daa0 + 9eedbee commit f95f32d

8 files changed

+262
-1
lines changed

Makefile

+6-1
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,8 @@ e2e-helm-deploy:
437437
--set enableSecretRotation=true \
438438
--set rotationPollInterval=30s \
439439
--set tokenRequests[0].audience="aud1" \
440-
--set tokenRequests[1].audience="aud2"
440+
--set tokenRequests[1].audience="aud2" \
441+
--set tokenRequests[2].audience="conjur"
441442

442443
.PHONY: e2e-helm-upgrade
443444
e2e-helm-upgrade:
@@ -494,6 +495,10 @@ e2e-gcp:
494495
e2e-aws:
495496
bats -t test/bats/aws.bats
496497

498+
.PHONY: e2e-conjur
499+
e2e-conjur:
500+
bats -t test/bats/conjur.bats
501+
497502
## --------------------------------------
498503
## Generate
499504
## --------------------------------------

test/bats/conjur.bats

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#!/usr/bin/env bats
2+
3+
load helpers
4+
5+
BATS_TESTS_DIR=test/bats/tests/conjur
6+
WAIT_TIME=180
7+
SLEEP_TIME=1
8+
9+
CONJUR_NAMESPACE=conjur
10+
CONJUR_DATA_KEY="$(openssl rand -base64 32)"
11+
CONJUR_ACCOUNT=default
12+
CONJUR_URL=conjur-conjur-oss.conjur.svc.cluster.local
13+
14+
EXPECTED_USERNAME="some_user"
15+
EXPECTED_PASSWORD="SecretPassword1234!"
16+
17+
@test "install conjur provider" {
18+
# Update Helm repos
19+
helm repo add cyberark https://cyberark.github.io/helm-charts || true
20+
helm repo update
21+
22+
# Install Conjur
23+
helm install conjur cyberark/conjur-oss --namespace=$CONJUR_NAMESPACE --wait --timeout ${WAIT_TIME}s --create-namespace \
24+
--set dataKey=$CONJUR_DATA_KEY \
25+
--set authenticators="authn\,authn-jwt/kube" \
26+
--set service.external.enabled=false
27+
28+
# Install Conjur CSI Provider
29+
helm install conjur-csi-provider cyberark/conjur-k8s-csi-provider --wait --timeout ${WAIT_TIME}s --namespace=kube-system \
30+
--set providerServer.image.tag=0.1.0
31+
}
32+
33+
@test "setup conjur" {
34+
# Create Conjur account and store admin API key
35+
admin_api_key="$(kubectl exec deployment/conjur-conjur-oss \
36+
--namespace=$CONJUR_NAMESPACE \
37+
--container=conjur-oss \
38+
-- conjurctl account create $CONJUR_ACCOUNT | grep API | awk '{print $5}')"
39+
40+
# Create a Conjur CLI pod
41+
kubectl run conjur-cli-pod --image=cyberark/conjur-cli:8 --namespace=$CONJUR_NAMESPACE --command -- sleep infinity
42+
kubectl wait --for=condition=ready --timeout=${WAIT_TIME}s --namespace=$CONJUR_NAMESPACE pod/conjur-cli-pod
43+
44+
# Get values required by authn-jwt authenticator
45+
ISSUER=$(kubectl get --raw /.well-known/openid-configuration | jq -r .issuer)
46+
JWKS='{"type":"jwks","value":'$(kubectl get --raw /openid/v1/jwks)'}'
47+
48+
# Copy policy files into CLI container and configure Conjur
49+
kubectl -n "${CONJUR_NAMESPACE}" cp $BATS_TESTS_DIR/policy conjur-cli-pod:/policy -c conjur-cli-pod
50+
kubectl -n "${CONJUR_NAMESPACE}" exec conjur-cli-pod -- /bin/sh -c "
51+
set -x
52+
# Initialise CLI and login
53+
echo yes | conjur init -u 'https://$CONJUR_URL' -a '$CONJUR_ACCOUNT' --self-signed
54+
conjur login -i admin -p $admin_api_key
55+
56+
# Apply policy
57+
conjur policy replace -b root -f /policy/host.yaml
58+
conjur policy load -b root -f /policy/authn-jwt.yaml
59+
conjur policy load -b root -f /policy/variables.yaml
60+
# Set test secret values
61+
conjur variable set -i db-credentials/username -v '$EXPECTED_USERNAME'
62+
conjur variable set -i db-credentials/password -v '$EXPECTED_PASSWORD'
63+
# Set variable values on authenticator
64+
conjur variable set -i conjur/authn-jwt/kube/public-keys -v '$JWKS'
65+
conjur variable set -i conjur/authn-jwt/kube/issuer -v '$ISSUER'
66+
"
67+
}
68+
69+
@test "deploy conjur secretproviderclass crd" {
70+
CONJUR_POD=$(kubectl get pods --namespace=$CONJUR_NAMESPACE -l "app=conjur-oss" -o=jsonpath='{.items[0].metadata.name}')
71+
export CONJUR_SSL_CERT=$(kubectl exec --namespace=$CONJUR_NAMESPACE -c conjur-oss $CONJUR_POD -- sh -c "openssl s_client -showcerts -connect $CONJUR_URL:443 </dev/null 2>/dev/null | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p'")
72+
envsubst < $BATS_TESTS_DIR/conjur_v1_secretproviderclass.yaml | sed '/^ *-----BEGIN CERTIFICATE-----/,$s/^/ /' | kubectl apply -f -
73+
74+
kubectl wait --for condition=established --timeout=60s crd/secretproviderclasses.secrets-store.csi.x-k8s.io
75+
76+
cmd="kubectl get secretproviderclasses.secrets-store.csi.x-k8s.io/conjur -o yaml | grep conjur"
77+
wait_for_process $WAIT_TIME $SLEEP_TIME "$cmd"
78+
}
79+
80+
@test "CSI inline volume test with pod portability" {
81+
kubectl apply -f $BATS_TESTS_DIR/pod-secrets-store-inline-volume-crd.yaml
82+
83+
kubectl wait --for=condition=Ready --timeout=60s pod/secrets-store-inline-crd
84+
85+
run kubectl get pod/secrets-store-inline-crd
86+
assert_success
87+
}
88+
89+
@test "CSI inline volume test with pod portability - read conjur secret from pod" {
90+
result=$(kubectl exec secrets-store-inline-crd -- cat /mnt/secrets-store/relative/path/username)
91+
[[ "${result}" == "$EXPECTED_USERNAME" ]]
92+
93+
result=$(kubectl exec secrets-store-inline-crd -- cat /mnt/secrets-store/relative/path/password)
94+
[[ "${result}" == "$EXPECTED_PASSWORD" ]]
95+
}
96+
97+
@test "CSI inline volume test with pod portability - rotation succeeds" {
98+
# Set initial value
99+
kubectl -n conjur exec conjur-cli-pod -- conjur variable set -i db-credentials/username -v initial_value
100+
101+
# Deploy pod
102+
CONJUR_POD=$(kubectl get pods --namespace=$CONJUR_NAMESPACE -l "app=conjur-oss" -o=jsonpath='{.items[0].metadata.name}')
103+
export CONJUR_SSL_CERT=$(kubectl exec --namespace=$CONJUR_NAMESPACE -c conjur-oss $CONJUR_POD -- sh -c "openssl s_client -showcerts -connect $CONJUR_URL:443 </dev/null 2>/dev/null | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p'")
104+
envsubst < $BATS_TESTS_DIR/pod-conjur-rotation.yaml | sed '/^ *-----BEGIN CERTIFICATE-----/,$s/^/ /' | kubectl apply -f -
105+
kubectl wait --for=condition=Ready --timeout=60s pod/secrets-store-inline-rotation
106+
107+
run kubectl get pod/secrets-store-inline-rotation
108+
assert_success
109+
110+
# Verify initial value
111+
result=$(kubectl exec secrets-store-inline-rotation -- cat /mnt/secrets-store/relative/path/username)
112+
[[ "${result}" == "initial_value" ]]
113+
114+
# Update the secret value and wait for rotation interval
115+
kubectl -n conjur exec conjur-cli-pod -- conjur variable set -i db-credentials/username -v rotated_value
116+
sleep 40
117+
118+
# Verify rotated value
119+
result=$(kubectl exec secrets-store-inline-rotation -- cat /mnt/secrets-store/relative/path/username)
120+
[[ "${result}" == "rotated_value" ]]
121+
}
122+
123+
@test "CSI inline volume test with pod portability - unmount succeeds" {
124+
# On Linux a failure to unmount the tmpfs will block the pod from being deleted.
125+
run kubectl delete pod secrets-store-inline-crd
126+
assert_success
127+
128+
run kubectl wait --for=delete --timeout=${WAIT_TIME}s pod/secrets-store-inline-crd
129+
130+
# Sleep to allow time for logs to propagate.
131+
sleep 10
132+
133+
# save debug information to archive in case of failure
134+
archive_info
135+
136+
# On Windows, the failed unmount calls from: https://github.com/kubernetes-sigs/secrets-store-csi-driver/pull/545
137+
# do not prevent the pod from being deleted. Search through the driver logs
138+
# for the error.
139+
run bash -c "kubectl logs -l app=secrets-store-csi-driver --tail -1 -c secrets-store -n kube-system | grep '^E.*failed to clean and unmount target path.*$'"
140+
assert_failure
141+
}
142+
143+
teardown_file() {
144+
archive_provider "app=csi-secrets-store-provider-conjur" || true
145+
archive_info || true
146+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: secrets-store.csi.x-k8s.io/v1
2+
kind: SecretProviderClass
3+
metadata:
4+
name: conjur
5+
spec:
6+
provider: conjur
7+
parameters:
8+
account: default
9+
applianceUrl: https://conjur-conjur-oss.conjur.svc.cluster.local
10+
authnId: authn-jwt/kube
11+
identity: host/workload-host
12+
secrets: |
13+
- "relative/path/username": "db-credentials/username"
14+
- "relative/path/password": "db-credentials/password"
15+
sslCertificate: |
16+
$CONJUR_SSL_CERT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
kind: Pod
2+
apiVersion: v1
3+
metadata:
4+
name: secrets-store-inline-rotation
5+
spec:
6+
containers:
7+
- image: registry.k8s.io/e2e-test-images/busybox:1.29-4
8+
name: busybox
9+
imagePullPolicy: IfNotPresent
10+
command:
11+
- "/bin/sleep"
12+
- "10000"
13+
volumeMounts:
14+
- name: secrets-store-inline
15+
mountPath: "/mnt/secrets-store"
16+
readOnly: true
17+
volumes:
18+
- name: secrets-store-inline
19+
csi:
20+
driver: secrets-store.csi.k8s.io
21+
readOnly: true
22+
volumeAttributes:
23+
secretProviderClass: "conjur-rotation"
24+
---
25+
apiVersion: secrets-store.csi.x-k8s.io/v1
26+
kind: SecretProviderClass
27+
metadata:
28+
name: conjur-rotation
29+
spec:
30+
provider: conjur
31+
parameters:
32+
account: default
33+
applianceUrl: https://conjur-conjur-oss.conjur.svc.cluster.local
34+
authnId: authn-jwt/kube
35+
identity: host/workload-host
36+
secrets: |
37+
- "relative/path/username": "db-credentials/username"
38+
- "relative/path/password": "db-credentials/password"
39+
sslCertificate: |
40+
$CONJUR_SSL_CERT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
kind: Pod
2+
apiVersion: v1
3+
metadata:
4+
name: secrets-store-inline-crd
5+
spec:
6+
containers:
7+
- image: registry.k8s.io/e2e-test-images/busybox:1.29-4
8+
name: busybox
9+
imagePullPolicy: IfNotPresent
10+
command:
11+
- "/bin/sleep"
12+
- "10000"
13+
volumeMounts:
14+
- name: secrets-store-inline
15+
mountPath: "/mnt/secrets-store"
16+
readOnly: true
17+
volumes:
18+
- name: secrets-store-inline
19+
csi:
20+
driver: secrets-store.csi.k8s.io
21+
readOnly: true
22+
volumeAttributes:
23+
secretProviderClass: conjur
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
- !policy
3+
id: conjur/authn-jwt/kube
4+
body:
5+
- !webservice
6+
7+
- !variable public-keys
8+
- !variable issuer
9+
10+
- !permit
11+
role: !host /workload-host
12+
privilege: [ read, authenticate ]
13+
resource: !webservice
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
- !host
3+
id: workload-host
4+
annotations:
5+
authn-jwt/kube/kubernetes.io/namespace: default
6+
authn-jwt/kube/kubernetes.io/serviceaccount/name: default
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
- !policy
3+
id: db-credentials
4+
body:
5+
- &variables
6+
- !variable username
7+
- !variable password
8+
9+
- !permit
10+
role: !host /workload-host
11+
privileges: [ read, execute ]
12+
resource: *variables

0 commit comments

Comments
 (0)