From d58c4e4ef0a45accd060b77b7999484fa0209439 Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:00:16 -0300 Subject: [PATCH 01/10] feat(kyverno): validate XQueueClaim fields via policy and enforce on PR with GitHub Action - Add Kyverno policy to validate location, message size, and timeout fields - Include workflow to apply policy on PRs to crossplane/claims - Add bootstrap script to install and verify Kyverno in the platform cluster --- .bootstrap/kyverno/up.sh | 73 ++++++++++++++++++++++++++ .github/workflows/validate-claims.yaml | 27 ++++++++++ crossplane/claims/lorem-ipsum.yaml | 11 ++++ kyverno/.gitkeep | 0 kyverno/validate-xqueue-fields.yaml | 57 ++++++++++++++++++++ 5 files changed, 168 insertions(+) create mode 100755 .bootstrap/kyverno/up.sh create mode 100644 .github/workflows/validate-claims.yaml create mode 100644 crossplane/claims/lorem-ipsum.yaml delete mode 100644 kyverno/.gitkeep create mode 100644 kyverno/validate-xqueue-fields.yaml diff --git a/.bootstrap/kyverno/up.sh b/.bootstrap/kyverno/up.sh new file mode 100755 index 0000000..7008a22 --- /dev/null +++ b/.bootstrap/kyverno/up.sh @@ -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!" diff --git a/.github/workflows/validate-claims.yaml b/.github/workflows/validate-claims.yaml new file mode 100644 index 0000000..8857bc4 --- /dev/null +++ b/.github/workflows/validate-claims.yaml @@ -0,0 +1,27 @@ +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: Set up Kyverno CLI + run: | + curl -sL https://github.com/kyverno/kyverno/releases/latest/download/kyverno-cli_linux_x86_64.tar.gz | tar xz + sudo mv kyverno /usr/local/bin/ + + - name: Run Kyverno policy checks on claims + run: | + kyverno apply ./kyverno --resource ./crossplane/claims diff --git a/crossplane/claims/lorem-ipsum.yaml b/crossplane/claims/lorem-ipsum.yaml new file mode 100644 index 0000000..83590f2 --- /dev/null +++ b/crossplane/claims/lorem-ipsum.yaml @@ -0,0 +1,11 @@ +apiVersion: platform.hooli.tech/v1alpha1 +kind: XQueueClaim +metadata: + name: lorem-ipsum +spec: + location: LOREM + providerName: default + visibilityTimeoutSeconds: 30 + maxMessageSize: 262144 + tags: + a: b \ No newline at end of file diff --git a/kyverno/.gitkeep b/kyverno/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/kyverno/validate-xqueue-fields.yaml b/kyverno/validate-xqueue-fields.yaml new file mode 100644 index 0000000..23319be --- /dev/null +++ b/kyverno/validate-xqueue-fields.yaml @@ -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 From 017529997a59471be674261ea6d7780546df8a0f Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:05:43 -0300 Subject: [PATCH 02/10] chore(ci): pin Kyverno CLI version in GitHub Action to v1.12.0 Pinned the Kyverno CLI to a specific version to ensure consistent validation behavior across runs. --- .github/workflows/validate-claims.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate-claims.yaml b/.github/workflows/validate-claims.yaml index 8857bc4..b6a53e4 100644 --- a/.github/workflows/validate-claims.yaml +++ b/.github/workflows/validate-claims.yaml @@ -17,10 +17,12 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Set up Kyverno CLI + - name: Install Kyverno CLI run: | - curl -sL https://github.com/kyverno/kyverno/releases/latest/download/kyverno-cli_linux_x86_64.tar.gz | tar xz + curl -LO https://github.com/kyverno/kyverno/releases/download/v1.12.0/kyverno-cli_v1.12.0_linux_x86_64.tar.gz + tar -xvf kyverno-cli_v1.12.0_linux_x86_64.tar.gz sudo mv kyverno /usr/local/bin/ + kyverno version - name: Run Kyverno policy checks on claims run: | From 8ac51723a72c3264b8ae98a4c61822e21dac8ac5 Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:11:07 -0300 Subject: [PATCH 03/10] chore(ci): extract Kyverno CLI to temporary directory to avoid conflict Extract Kyverno CLI tarball to /tmp/kyverno-cli instead of current directory to prevent overwrite errors when kyverno folder already exists. --- .github/workflows/validate-claims.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate-claims.yaml b/.github/workflows/validate-claims.yaml index b6a53e4..bd0a567 100644 --- a/.github/workflows/validate-claims.yaml +++ b/.github/workflows/validate-claims.yaml @@ -20,8 +20,9 @@ jobs: - name: Install Kyverno CLI run: | curl -LO https://github.com/kyverno/kyverno/releases/download/v1.12.0/kyverno-cli_v1.12.0_linux_x86_64.tar.gz - tar -xvf kyverno-cli_v1.12.0_linux_x86_64.tar.gz - sudo mv kyverno /usr/local/bin/ + mkdir -p /tmp/kyverno-cli + tar -xvf kyverno-cli_v1.12.0_linux_x86_64.tar.gz -C /tmp/kyverno-cli + sudo mv /tmp/kyverno-cli/kyverno /usr/local/bin/ kyverno version - name: Run Kyverno policy checks on claims From 5412aeef34101122190ca40e31fb9f1a3565371f Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:20:00 -0300 Subject: [PATCH 04/10] ci(kyverno): redirect policy validation results to GitHub step summary Redirected Kyverno CLI output to `$GITHUB_STEP_SUMMARY` for --- .github/workflows/validate-claims.yaml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/validate-claims.yaml b/.github/workflows/validate-claims.yaml index bd0a567..7d2aa97 100644 --- a/.github/workflows/validate-claims.yaml +++ b/.github/workflows/validate-claims.yaml @@ -27,4 +27,18 @@ jobs: - name: Run Kyverno policy checks on claims run: | - kyverno apply ./kyverno --resource ./crossplane/claims + echo "## 🛡️ Kyverno Policy Validation Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + if kyverno apply ./kyverno --resource ./crossplane/claims | tee result.txt; then + echo "✅ All policies passed." >> $GITHUB_STEP_SUMMARY + else + cat result.txt >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "❌ One or more Kyverno policies failed." >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + echo '```' >> $GITHUB_STEP_SUMMARY From 892bf4f1c3733817f44ea513ebb2544672de07f6 Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:23:48 -0300 Subject: [PATCH 05/10] fix(workflow): ensure Kyverno errors are written to PR summary and exit properly Previously, Kyverno failures were not clearly visible in the PR summary due to missing output redirects and improper exit checks. This change captures the Kyverno exit code explicitly, appends the results to `$GITHUB_STEP_SUMMARY`, and exits with an error when validation fails. --- .github/workflows/validate-claims.yaml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/validate-claims.yaml b/.github/workflows/validate-claims.yaml index 7d2aa97..7e394b3 100644 --- a/.github/workflows/validate-claims.yaml +++ b/.github/workflows/validate-claims.yaml @@ -31,14 +31,18 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY - if kyverno apply ./kyverno --resource ./crossplane/claims | tee result.txt; then - echo "✅ All policies passed." >> $GITHUB_STEP_SUMMARY - else - cat result.txt >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY + set +e + kyverno apply ./kyverno --resource ./crossplane/claims | 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." >> $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 - - echo '```' >> $GITHUB_STEP_SUMMARY From 8f7414588e51e7e7aaca325c346a7624e61bf293 Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:28:50 -0300 Subject: [PATCH 06/10] fix(ci): include stderr in Kyverno CLI output to capture validation errors in workflow summary Redirects stderr to stdout during Kyverno validation to ensure all messages are recorded in result.txt. --- .github/workflows/validate-claims.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-claims.yaml b/.github/workflows/validate-claims.yaml index 7e394b3..f485bb0 100644 --- a/.github/workflows/validate-claims.yaml +++ b/.github/workflows/validate-claims.yaml @@ -32,7 +32,7 @@ jobs: echo '```' >> $GITHUB_STEP_SUMMARY set +e - kyverno apply ./kyverno --resource ./crossplane/claims | tee result.txt + kyverno apply ./kyverno --resource ./crossplane/claims 2>&1 | tee result.txt KYVERNO_EXIT_CODE=${PIPESTATUS[0]} set -e From 0b55607d3543245c99366baec23fdd652ad262e6 Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:34:21 -0300 Subject: [PATCH 07/10] fix(ci): add `--remove-color` and `-t` flags to Kyverno apply for cleaner CI output Improves readability of validation logs by removing ANSI colors and enabling table output format. --- .github/workflows/validate-claims.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-claims.yaml b/.github/workflows/validate-claims.yaml index f485bb0..c8970c6 100644 --- a/.github/workflows/validate-claims.yaml +++ b/.github/workflows/validate-claims.yaml @@ -32,7 +32,7 @@ jobs: echo '```' >> $GITHUB_STEP_SUMMARY set +e - kyverno apply ./kyverno --resource ./crossplane/claims 2>&1 | tee result.txt + kyverno apply ./kyverno --resource ./crossplane/claims -t --remove-color 2>&1 | tee result.txt KYVERNO_EXIT_CODE=${PIPESTATUS[0]} set -e From bf9724e161f3a353fc69dab7207c55895c841dd6 Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:39:17 -0300 Subject: [PATCH 08/10] chore(ci): use Kyverno GitHub Action to install CLI instead of manual download Replaces custom install logic with official kyverno/action-install-cli for version v1.13.4. --- .github/workflows/validate-claims.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/validate-claims.yaml b/.github/workflows/validate-claims.yaml index c8970c6..129117e 100644 --- a/.github/workflows/validate-claims.yaml +++ b/.github/workflows/validate-claims.yaml @@ -18,12 +18,12 @@ jobs: uses: actions/checkout@v4 - name: Install Kyverno CLI - run: | - curl -LO https://github.com/kyverno/kyverno/releases/download/v1.12.0/kyverno-cli_v1.12.0_linux_x86_64.tar.gz - mkdir -p /tmp/kyverno-cli - tar -xvf kyverno-cli_v1.12.0_linux_x86_64.tar.gz -C /tmp/kyverno-cli - sudo mv /tmp/kyverno-cli/kyverno /usr/local/bin/ - kyverno version + 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: | @@ -32,7 +32,7 @@ jobs: echo '```' >> $GITHUB_STEP_SUMMARY set +e - kyverno apply ./kyverno --resource ./crossplane/claims -t --remove-color 2>&1 | tee result.txt + kyverno apply ./kyverno --resource ./crossplane/claims 2>&1 | tee result.txt KYVERNO_EXIT_CODE=${PIPESTATUS[0]} set -e From 912d41e05045cb9e386cf9cf0dd5ee854a0ae944 Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:45:29 -0300 Subject: [PATCH 09/10] fix(claim): update invalid location value to 'US' to satisfy Kyverno validation policy --- crossplane/claims/lorem-ipsum.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crossplane/claims/lorem-ipsum.yaml b/crossplane/claims/lorem-ipsum.yaml index 83590f2..effc67f 100644 --- a/crossplane/claims/lorem-ipsum.yaml +++ b/crossplane/claims/lorem-ipsum.yaml @@ -3,7 +3,7 @@ kind: XQueueClaim metadata: name: lorem-ipsum spec: - location: LOREM + location: US providerName: default visibilityTimeoutSeconds: 30 maxMessageSize: 262144 From 656e9d13b48a997ee9191bc79c609acc5229accb Mon Sep 17 00:00:00 2001 From: William Queiroz Date: Mon, 21 Apr 2025 17:49:51 -0300 Subject: [PATCH 10/10] chore(claims): remove example XQueueClaim and add .gitkeep to preserve directory --- crossplane/claims/.gitkeep | 0 crossplane/claims/lorem-ipsum.yaml | 11 ----------- 2 files changed, 11 deletions(-) create mode 100644 crossplane/claims/.gitkeep delete mode 100644 crossplane/claims/lorem-ipsum.yaml diff --git a/crossplane/claims/.gitkeep b/crossplane/claims/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/crossplane/claims/lorem-ipsum.yaml b/crossplane/claims/lorem-ipsum.yaml deleted file mode 100644 index effc67f..0000000 --- a/crossplane/claims/lorem-ipsum.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: platform.hooli.tech/v1alpha1 -kind: XQueueClaim -metadata: - name: lorem-ipsum -spec: - location: US - providerName: default - visibilityTimeoutSeconds: 30 - maxMessageSize: 262144 - tags: - a: b \ No newline at end of file