Initial commit

This commit is contained in:
Joel Kamp
2024-05-23 10:19:55 -05:00
committed by GitHub
commit 3d0519f92a
36 changed files with 1738 additions and 0 deletions

140
test/bats/helpers.bash Normal file
View File

@@ -0,0 +1,140 @@
#!/bin/bash
assert_success() {
if [[ "$status" != 0 ]]; then
echo "expected: 0"
echo "actual: $status"
echo "output: $output"
return 1
fi
}
assert_failure() {
if [[ "$status" == 0 ]]; then
echo "expected: non-zero exit code"
echo "actual: $status"
echo "output: $output"
return 1
fi
}
assert_equal() {
if [[ "$1" != "$2" ]]; then
echo "expected: $1"
echo "actual: $2"
return 1
fi
}
assert_not_equal() {
if [[ "$1" == "$2" ]]; then
echo "unexpected: $1"
echo "actual: $2"
return 1
fi
}
assert_match() {
if [[ ! "$2" =~ $1 ]]; then
echo "expected: $1"
echo "actual: $2"
return 1
fi
}
assert_not_match() {
if [[ "$2" =~ $1 ]]; then
echo "expected: $1"
echo "actual: $2"
return 1
fi
}
assert_len() {
if [[ "$1" != "${#2}" ]]; then
echo "expected len: $1"
echo "actual len: ${#2} ($2)"
return 1
fi
}
wait_for_process() {
wait_time="$1"
sleep_time="$2"
cmd="$3"
while [ "$wait_time" -gt 0 ]; do
if eval "$cmd"; then
return 0
else
sleep "$sleep_time"
wait_time=$((wait_time - sleep_time))
fi
done
return 1
}
get_ca_cert() {
destination="$1"
if [ $(kubectl get secret -n ${GATEKEEPER_NAMESPACE} gatekeeper-webhook-server-cert -o jsonpath='{.data.ca\.crt}' | wc -w) -eq 0 ]; then
return 1
fi
kubectl get secret -n ${GATEKEEPER_NAMESPACE} gatekeeper-webhook-server-cert -o jsonpath='{.data.ca\.crt}' | base64 -d >$destination
}
constraint_enforced() {
local kind="$1"
local name="$2"
local pod_list="$(kubectl -n ${GATEKEEPER_NAMESPACE} get pod -l gatekeeper.sh/operation=webhook -o json)"
if [[ $? -ne 0 ]]; then
echo "error gathering pods"
return 1
fi
# ensure pod_count is at least one
local pod_count=$(echo "${pod_list}" | jq '.items | length')
if [[ ${pod_count} -lt 1 ]]; then
echo "Gatekeeper pod count is < 1"
return 2
fi
local cstr="$(kubectl get ${kind} ${name} -ojson)"
if [[ $? -ne 0 ]]; then
echo "Error gathering constraint ${kind} ${name}"
return 3
fi
echo "checking constraint ${cstr}"
local ready_count=$(echo "${cstr}" | jq '.metadata.generation as $generation | [.status.byPod[] | select( .operations[] == "webhook" and .observedGeneration == $generation)] | length')
echo "ready: ${ready_count}, expected: ${pod_count}"
[[ "${ready_count}" -eq "${pod_count}" ]]
}
mutator_enforced() {
local kind="$1"
local name="$2"
local pod_list="$(kubectl -n ${GATEKEEPER_NAMESPACE} get pod -l gatekeeper.sh/operation=webhook -o json)"
if [[ $? -ne 0 ]]; then
echo "error gathering pods"
return 1
fi
# ensure pod_count is at least one
local pod_count=$(echo "${pod_list}" | jq '.items | length')
if [[ ${pod_count} -lt 1 ]]; then
echo "Gatekeeper pod count is < 1"
return 2
fi
local cstr="$(kubectl get ${kind} ${name} -ojson)"
if [[ $? -ne 0 ]]; then
echo "Error gathering mutator ${kind} ${name}"
return 3
fi
echo "checking mutator ${cstr}"
local ready_count=$(echo "${cstr}" | jq '.metadata.generation as $generation | [.status.byPod[] | select( .operations[] == "mutation-webhook" and .observedGeneration == $generation)] | length')
echo "ready: ${ready_count}, expected: ${pod_count}"
[[ "${ready_count}" -eq "${pod_count}" ]]
}

51
test/bats/test.bats Normal file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bats
load helpers
WAIT_TIME=120
SLEEP_TIME=1
GATEKEEPER_NAMESPACE=${GATEKEEPER_NAMESPACE:-gatekeeper-system}
teardown_file() {
kubectl delete -f validation/
kubectl delete -f mutation/
}
@test "gatekeeper-controller-manager is running" {
wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "kubectl -n ${GATEKEEPER_NAMESPACE} wait --for=condition=Ready --timeout=60s pod -l control-plane=controller-manager"
}
@test "gatekeeper-audit is running" {
wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "kubectl -n ${GATEKEEPER_NAMESPACE} wait --for=condition=Ready --timeout=60s pod -l control-plane=audit-controller"
}
@test "external-data-provider is running" {
wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "kubectl -n ${GATEKEEPER_NAMESPACE} wait --for=condition=Ready --timeout=60s pod -l run=external-data-provider"
}
@test "external data validation" {
run kubectl apply -f validation/external-data-provider-constraint-template.yaml
assert_success
wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "constraint_enforced constrainttemplate k8sexternaldatavalidation"
run kubectl apply -f validation/external-data-provider-constraint.yaml
assert_success
wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "constraint_enforced k8sexternaldatavalidation deny-images-with-invalid-suffix"
run kubectl run nginx --image=error_nginx --dry-run=server
# should deny pod admission if the image name has an "error_" prefix
assert_failure
assert_match 'error_nginx' "${output}"
assert_match 'error_nginx_invalid' "${output}"
}
@test "external data mutation" {
run kubectl apply -f mutation/external-data-provider-mutation.yaml
assert_success
wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "mutator_enforced Assign append-valid-suffix-to-image"
run kubectl run nginx --image=nginx --dry-run=server --output json
assert_success
# should mutate the image field by appending "_valid" suffix
assert_match "nginx_valid" "$(jq -r '.spec.containers[0].image' <<< ${output})"
}