|
| 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 | +} |
0 commit comments