Skip to content

Commit b9b9d48

Browse files
committed
add bats tests for alibabacloud secret store csi provider
1 parent 16fe724 commit b9b9d48

File tree

4 files changed

+211
-0
lines changed

4 files changed

+211
-0
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ ENVSUBST := envsubst
9494
EKSCTL := eksctl
9595
AWS_CLI := aws
9696
YQ := yq
97+
ALIYUNCLI := aliyun
9798

9899
# Test variables
99100
KIND_VERSION ?= 0.13.0
@@ -214,6 +215,9 @@ $(PROTOC): ## Install protoc
214215
$(YQ): ## Install yq for running the tests
215216
curl -LO https://github.com/mikefarah/yq/releases/download/$(YQ_VERSION)/yq_linux_amd64 && chmod +x ./yq_linux_amd64 && mv yq_linux_amd64 /usr/local/bin/yq
216217

218+
$(ALIYUNCLI): ## Install aliyun for running the tests
219+
curl -LO https://github.com/aliyun/aliyun-cli/releases/download/v3.0.134/aliyun-cli-linux-3.0.134-amd64.tgz && tar xzvf aliyun-cli-linux-3.0.134-amd64.tgz && chmod +x ./aliyun && cp aliyun /usr/local/bin
220+
217221
SHELLCHECK := $(TOOLS_BIN_DIR)/shellcheck-$(SHELLCHECK_VER)
218222
$(SHELLCHECK): OS := $(shell uname | tr '[:upper:]' '[:lower:]')
219223
$(SHELLCHECK): ARCH := $(shell uname -m)
@@ -482,6 +486,10 @@ e2e-akeyless:
482486
e2e-gcp:
483487
bats -t test/bats/gcp.bats
484488

489+
.PHONY: e2e-alibabacloud
490+
e2e-alibabacloud:
491+
bats -t test/bats/alibabacloud.bats
492+
485493
.PHONY: e2e-aws
486494
e2e-aws:
487495
bats -t test/bats/aws.bats

test/bats/alibabacloud.bats

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#!/usr/bin/env bats
2+
3+
load helpers
4+
5+
WAIT_TIME=120
6+
SLEEP_TIME=1
7+
NAMESPACE=kube-system
8+
POD_NAME=alibabacloud-basic-test-mount
9+
BATS_TEST_DIR=test/bats/tests/alibabacloud
10+
11+
setup() {
12+
if [[ -z "${ALIBABACLOUD_ACCESS_KEY}" ]] || [[ -z "${ALIBABACLOUD_ACCESS_SECRET}" ]]; then
13+
echo "Error: ram ak/sk is not provided" >&2
14+
return 1
15+
fi
16+
}
17+
18+
setup_file() {
19+
#Configure aliyun cli profile
20+
aliyun configure set --profile akProfile --mode AK --region us-west-1 --access-key-id ${ALIBABACLOUD_ACCESS_KEY} --access-key-secret ${ALIBABACLOUD_ACCESS_SECRET}
21+
22+
#Create test secrets
23+
aliyun kms CreateSecret --SecretName testBasic --SecretData testValue --VersionId v1
24+
aliyun kms CreateSecret --SecretName testSync --SecretData syncValue --VersionId v1
25+
aliyun kms CreateSecret --SecretName testRotation --SecretData beforeRotation --VersionId v1
26+
aliyun kms CreateSecret --SecretName testJson --SecretData '{"username": "testUser", "password": "testPassword"}' --VersionId v1
27+
}
28+
29+
teardown_file() {
30+
aliyun kms DeleteSecret --SecretName testBasic --ForceDeleteWithoutRecovery true
31+
aliyun kms DeleteSecret --SecretName testSync --ForceDeleteWithoutRecovery true
32+
aliyun kms DeleteSecret --SecretName testRotation --ForceDeleteWithoutRecovery true
33+
aliyun kms DeleteSecret --SecretName testJson --ForceDeleteWithoutRecovery true
34+
}
35+
36+
validate_jsme_mount() {
37+
result=$(kubectl --namespace $NAMESPACE exec $POD_NAME -- cat /mnt/secrets-store/$USERNAME_ALIAS)
38+
[[ "${result//$'\r'}" == $USERNAME ]]
39+
40+
result=$(kubectl --namespace $NAMESPACE exec $POD_NAME -- cat /mnt/secrets-store/$PASSWORD_ALIAS)
41+
[[ "${result//$'\r'}" == $PASSWORD ]]
42+
43+
result=$(kubectl --namespace $NAMESPACE exec $POD_NAME -- cat /mnt/secrets-store/$SECRET_FILE_NAME)
44+
[[ "${result//$'\r'}" == $SECRET_FILE_CONTENT ]]
45+
46+
run kubectl get secret --namespace $NAMESPACE $K8_SECRET_NAME
47+
[ "$status" -eq 0 ]
48+
49+
result=$(kubectl --namespace=$NAMESPACE get secret $K8_SECRET_NAME -o jsonpath="{.data.username}" | base64 -d)
50+
[[ "$result" == $USERNAME ]]
51+
52+
result=$(kubectl --namespace=$NAMESPACE get secret $K8_SECRET_NAME -o jsonpath="{.data.password}" | base64 -d)
53+
[[ "$result" == $PASSWORD ]]
54+
}
55+
56+
@test "Install alibabacloud provider" {
57+
#Install csi secret driver
58+
helm repo add csi-secrets-store-provider-alibabacloud https://raw.githubusercontent.com/AliyunContainerService/secrets-store-csi-driver-provider-alibaba-cloud/main/charts
59+
helm install csi-secrets-store-provider-alibabacloud/csi-secrets-store-provider-alibabacloud --namespace kube-system --generate-name --set secrets-store-csi-driver.enableSecretRotation=true --set secrets-store-csi-driver.rotationPollInterval=10s --set secrets-store-csi-driver.syncSecret.enabled=true
60+
61+
cmd="kubectl --namespace $NAMESPACE wait --for=condition=Ready --timeout=60s pod -l app=csi-secrets-store-provider-alibabacloud"
62+
wait_for_process $WAIT_TIME $SLEEP_TIME "$cmd"
63+
64+
PROVIDER_POD=$(kubectl --namespace $NAMESPACE get pod -l app=csi-secrets-store-provider-alibabacloud -o jsonpath="{.items[0].metadata.name}")
65+
run kubectl --namespace $NAMESPACE get pod/$PROVIDER_POD
66+
assert_success
67+
}
68+
69+
@test "secretproviderclasses crd is established" {
70+
cmd="kubectl wait --namespace $NAMESPACE --for condition=established --timeout=60s crd/secretproviderclasses.secrets-store.csi.x-k8s.io"
71+
wait_for_process $WAIT_TIME $SLEEP_TIME "$cmd"
72+
73+
run kubectl get crd/secretproviderclasses.secrets-store.csi.x-k8s.io
74+
assert_success
75+
}
76+
77+
@test "create alibabacloud k8s secret" {
78+
run kubectl create secret generic secrets-store-creds --from-literal access_key=${ALIBABACLOUD_ACCESS_KEY} --from-literal access_secret=${ALIBABACLOUD_ACCESS_SECRET} --namespace=$NAMESPACE
79+
assert_success
80+
81+
# label the node publish secret ref secret
82+
run kubectl label secret secrets-store-creds secrets-store.csi.k8s.io/used=true --namespace=$NAMESPACE
83+
assert_success
84+
}
85+
86+
@test "deploy alibabacloud secretproviderclass crd" {
87+
envsubst < $BATS_TEST_DIR/secretproviderclass.yaml | kubectl --namespace $NAMESPACE apply -f -
88+
89+
cmd="kubectl --namespace $NAMESPACE get secretproviderclasses.secrets-store.csi.x-k8s.io/alibabacloud-basic-test-mount-spc -o yaml | grep alibabacloud"
90+
wait_for_process $WAIT_TIME $SLEEP_TIME "$cmd"
91+
}
92+
93+
@test "CSI inline volume test with pod portability" {
94+
kubectl --namespace $NAMESPACE apply -f $BATS_TEST_DIR/pod-inline-volume-secretproviderclass.yaml
95+
cmd="kubectl --namespace $NAMESPACE wait --for=condition=Ready --timeout=60s pod/alibabacloud-basic-test-mount"
96+
wait_for_process $WAIT_TIME $SLEEP_TIME "$cmd"
97+
98+
run kubectl --namespace $NAMESPACE get pod/$POD_NAME
99+
assert_success
100+
}
101+
102+
@test "CSI inline volume test with rotation" {
103+
result=$(kubectl --namespace $NAMESPACE exec $POD_NAME -- cat /mnt/secrets-store/testRotation)
104+
[[ "${result//$'\r'}" == "beforeRotation" ]]
105+
106+
aliyun kms PutSecretValue --SecretName testRotation --SecretData afterRotation --VersionId v2
107+
sleep 20
108+
result=$(kubectl --namespace $NAMESPACE exec $POD_NAME -- cat /mnt/secrets-store/testRotation)
109+
[[ "${result//$'\r'}" == "afterRotation" ]]
110+
}
111+
112+
@test "CSI inline volume test with pod portability - read secrets manager secrets from pod" {
113+
result=$(kubectl --namespace $NAMESPACE exec $POD_NAME -- cat /mnt/secrets-store/testBasic)
114+
[[ "${result//$'\r'}" == "testValue" ]]
115+
}
116+
117+
@test "CSI inline volume test with pod portability - specify jsmePath for Secrets Manager secret with rotation" {
118+
119+
JSON_CONTENT='{"username": "testUser", "password": "testPassword"}'
120+
121+
USERNAME_ALIAS=mySecretUsername USERNAME=testUser PASSWORD_ALIAS=mySecretPassword \
122+
PASSWORD=testPassword SECRET_FILE_NAME=testJson SECRET_FILE_CONTENT=$JSON_CONTENT
123+
K8_SECRET_NAME=sm-secret-json validate_jsme_mount
124+
125+
UPDATED_JSON_CONTENT='{"username": "testUser", "password": "testPasswordUpdated"}'
126+
aliyun kms PutSecretValue --SecretName testJson --SecretData "$UPDATED_JSON_CONTENT" --VersionId v2
127+
128+
sleep 20
129+
USERNAME_ALIAS=mySecretUsername USERNAME=testUser PASSWORD_ALIAS=mySecretPassword \
130+
PASSWORD=testPasswordUpdated SECRET_FILE_NAME=testJson SECRET_FILE_CONTENT=$UPDATED_JSON_CONTENT
131+
K8_SECRET_NAME=sm-secret-json validate_jsme_mount
132+
}
133+
134+
@test "Sync with Kubernetes Secret" {
135+
run kubectl get secret --namespace $NAMESPACE sm-secret
136+
[ "$status" -eq 0 ]
137+
138+
result=$(kubectl --namespace=$NAMESPACE get secret sm-secret -o jsonpath="{.data.username}" | base64 -d)
139+
[[ "$result" == "syncValue" ]]
140+
}
141+
142+
@test "Sync with Kubernetes Secret - Delete deployment. Secret should also be deleted" {
143+
run kubectl --namespace $NAMESPACE delete -f $BATS_TEST_DIR/pod-inline-volume-secretproviderclass.yaml
144+
assert_success
145+
146+
run wait_for_process $WAIT_TIME $SLEEP_TIME "check_secret_deleted secret $NAMESPACE"
147+
assert_success
148+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
kind: Pod
2+
apiVersion: v1
3+
metadata:
4+
name: alibabacloud-basic-test-mount
5+
spec:
6+
containers:
7+
- image: k8s.gcr.io/e2e-test-images/busybox:1.29
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: "alibabacloud-basic-test-mount-spc"
24+
nodePublishSecretRef:
25+
name: secrets-store-creds
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
apiVersion: secrets-store.csi.x-k8s.io/v1
2+
kind: SecretProviderClass
3+
metadata:
4+
name: alibabacloud-basic-test-mount-spc
5+
spec:
6+
provider: alibabacloud
7+
secretObjects:
8+
- secretName: sm-secret
9+
type: Opaque
10+
data:
11+
- objectName: testSync
12+
key: username
13+
- secretName: sm-secret-json
14+
type: Opaque
15+
data:
16+
- objectName: mySecretUsername
17+
key: username
18+
- objectName: mySecretPassword
19+
key: password
20+
parameters:
21+
objects: |
22+
- objectName: testBasic
23+
- objectName: testSync
24+
- objectName: testRotation
25+
- objectName: testJson
26+
jmesPath:
27+
- path: "username"
28+
objectAlias: "mySecretUsername"
29+
- path: "password"
30+
objectAlias: "mySecretPassword"

0 commit comments

Comments
 (0)