Skip to content

feat(kyverno): validate XQueueClaim fields via policy and enforce on PR with GitHub Action #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .bootstrap/kyverno/up.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash

set -euo pipefail

# Change to platform cluster
if [[ "$(kubectl config current-context)" != "kind-platform" ]]; then
kubectl config use-context kind-platform || {
echo "Failed to switch context to kind-platform"
exit 1
}
fi

NS=kyverno-system
KYVERNO_CHART=kyverno/kyverno
POLICIES_DIR=./kyverno
TIMEOUT=120
INTERVAL=5
ELAPSED=0

echo "Adding Kyverno Helm repository..."
helm repo add kyverno https://kyverno.github.io/kyverno/ 2>/dev/null || true
helm repo update

echo "Installing or upgrading Kyverno via Helm..."
helm upgrade --install kyverno "$KYVERNO_CHART" \
--namespace "$NS" \
--create-namespace

echo "Waiting for Kyverno webhook to be ready..."
kubectl wait deployment/kyverno-admission-controller \
-n "$NS" \
--for=condition=Available=True \
--timeout=${TIMEOUT}s

echo "Ensuring all Kyverno pods are ready..."
while true; do
READY=$(kubectl get pods -n "$NS" -o jsonpath='{.items[*].status.containerStatuses[*].ready}' | tr " " "\n" | grep -c false || true)
if [[ "$READY" -eq 0 ]]; then
break
fi
if [[ "$ELAPSED" -ge "$TIMEOUT" ]]; then
echo "Timeout reached. Kyverno pods are not ready."
exit 1
fi
echo "Waiting for Kyverno pods to become ready..."
sleep $INTERVAL
ELAPSED=$((ELAPSED + INTERVAL))
done

echo "All Kyverno pods are ready!"

apply_kyverno_policies() {
local retries=20
local delay=3

for i in $(seq 1 $retries); do
if kubectl apply -f "$POLICIES_DIR" --recursive; then
echo "✅ Kyverno policies applied successfully!"
return 0
else
echo "⚠️ Failed to apply policies, retrying in ${delay}s... (${i}/${retries})"
sleep $delay
fi
done

echo "❌ Failed to apply Kyverno policies after ${retries} attempts."
exit 1
}

echo "Applying Kyverno policies from $POLICIES_DIR..."
apply_kyverno_policies

echo "✅ Kyverno setup and policy application completed successfully!"
48 changes: 48 additions & 0 deletions .github/workflows/validate-claims.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Validate Crossplane Claims

on:
pull_request:
paths:
- "crossplane/claims/**/*.yaml"
- "crossplane/claims/**/*.yml"
- "kyverno/**/*.yaml"
- "kyverno/**/*.yml"

jobs:
validate-claims:
name: Validate Claims YAML with Kyverno
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Kyverno CLI
uses: kyverno/action-install-cli@v0.2.0
with:
release: "v1.13.4"

- name: Check install
run: kyverno version

- name: Run Kyverno policy checks on claims
run: |
echo "## 🛡️ Kyverno Policy Validation Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY

set +e
kyverno apply ./kyverno --resource ./crossplane/claims 2>&1 | tee result.txt
KYVERNO_EXIT_CODE=${PIPESTATUS[0]}
set -e

cat result.txt >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY

if [[ $KYVERNO_EXIT_CODE -ne 0 ]]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "❌ One or more Kyverno policies failed. Please fix the issues above." >> $GITHUB_STEP_SUMMARY
exit 1
else
echo "✅ All policies passed." >> $GITHUB_STEP_SUMMARY
fi
File renamed without changes.
57 changes: 57 additions & 0 deletions kyverno/validate-xqueue-fields.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: validate-xqueue-fields
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-invalid-location
match:
resources:
kinds:
- platform.hooli.tech/v1alpha1/XQueueClaim
validate:
message: "Invalid location: only 'EU' or 'US' are allowed in spec.location"
deny:
conditions:
all:
- key: "{{ request.object.spec.location }}"
operator: AllNotIn
value:
- "EU"
- "US"

- name: deny-invalid-max-message-size
match:
resources:
kinds:
- platform.hooli.tech/v1alpha1/XQueueClaim
validate:
message: "Invalid maxMessageSize: must be between 1024 and 262144 (bytes)"
deny:
conditions:
any:
- key: "{{ request.object.spec.maxMessageSize }}"
operator: GreaterThan
value: 262144
- key: "{{ request.object.spec.maxMessageSize }}"
operator: LessThan
value: 1024

- name: deny-invalid-visibility-timeout
match:
resources:
kinds:
- platform.hooli.tech/v1alpha1/XQueueClaim
validate:
message: "Invalid visibilityTimeoutSeconds: must be between 0 and 43200 (seconds)"
deny:
conditions:
any:
- key: "{{ request.object.spec.visibilityTimeoutSeconds }}"
operator: GreaterThan
value: 43200
- key: "{{ request.object.spec.visibilityTimeoutSeconds }}"
operator: LessThan
value: 0