Skip to content

Commit

Permalink
Accomodate the change in Kyverno report aggregation in v1.11+ (#890)
Browse files Browse the repository at this point in the history
* Accomodate the change in Kyverno report aggregation in v1.11+ (kyverno/kyverno#8426)
  • Loading branch information
jslivka authored Apr 4, 2024
1 parent 79d0544 commit 2811fae
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 61 deletions.
3 changes: 3 additions & 0 deletions plugins/kyverno/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.2.0
* Accomodate the change in Kyverno report aggregation in v1.11+ (https://github.com/kyverno/kyverno/pull/8426)

## 0.1.5
* Bump kubectl to 1.29.0

Expand Down
108 changes: 48 additions & 60 deletions plugins/kyverno/main.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#! /bin/bash
# Additional information on PolicyReport,ClusterPolicyReport: https://kyverno.io/docs/policy-reports/
# NOTE: this may only work for Kyverno versions v1.11 and up
# See https://github.com/kyverno/kyverno/pull/8426 for more information
set -e
trap 'echo "Error on Line: $LINENO"' ERR
echo "Starting kyverno"
Expand All @@ -15,77 +17,56 @@ kubectl get crd clusterpolicies.kyverno.io >/dev/null || exit 1
# collect policyreports, exit early if CRD is missing
KIND="policyreport"
kubectl get crd "$KIND"s.wgpolicyk8s.io >/dev/null || exit 1
echo "Retrieving namespaces"

echo "Retrieving "
namespaces=$(kubectl get namespaces -o name | sed 's/namespace\///g')
IFS=$'\n' namespaces=($namespaces)
IFS=$'\n' namespaces=("$namespaces")

declare -a policies
declare -a policy_titles
declare -a policy_descriptions

for namespace in "${namespaces[@]}"; do
reports=$(kubectl get $KIND -n $namespace -o name | sed "s/$KIND\.wgpolicyk8s\.io\///g")
IFS=$'\n' reports=($reports)

count=${#reports[@]}
echo "found $count $KIND for namespace $namespace"

for report in "${reports[@]}"; do
# remove passed or skipped results to minimize payload and trigger a 'fixed' status for action items
report_json_full=$(kubectl -n $namespace get $KIND $report -o json)
echo $report_json_full | jq '. | del( ."results"[]? | select(."result" == "pass" or ."result" == "skip") )' > $report_file
policy_name=$(cat $report_file | jq -r '.results[0]?.policy')
# if there are no policyreports whatsoever, exit
reports=$(kubectl get policyreport,clusterpolicyreport --all-namespaces)
if [[ -z "$reports" ]]; then
echo "no policyreport,clusterpolicyreport found in cluster. quitting..."
cat $list_file | jq > $results_file
rm $list_file
exit 0
fi

# use lookup table to minimize control plane load
if [[ "$policy_name" != "null" && (! "${policies[*]}" =~ "${policy_name}") ]]; then
# determine if report refers to a policy or a clusterpolicy
policy_type="clusterpolicy"
kubectl get $policy_type $policy_name >/dev/null || policy_type="policy"
# retrieve necessary metadata from the associated policy
policy_title=$(kubectl -n $namespace get $policy_type $policy_name -o=jsonpath="{.metadata.annotations.policies\.kyverno\.io\/title}")
policy_description=$(kubectl -n $namespace get $policy_type $policy_name -o=jsonpath="{.metadata.annotations.policies\.kyverno\.io\/description}")
# populate the policy title and name
jq --arg title "$policy_title" --arg description "$policy_description" '. += {policyTitle: $title, policyDescription: $description}' < $report_file | sponge $report_file

policies+=($policy_name)
policy_titles["$policy_name"]=$policy_title
policy_descriptions["$policy_name"]=$policy_description
else
policy_title=${policy_titles[$policy_name]}
policy_description=${policy_descriptions[$policy_name]}
jq --arg title "$policy_title" --arg description "$policy_description" '. += {policyTitle: $title, policyDescription: $description}' < $report_file | sponge $report_file
fi

# append the modified policyreport to the output file
jq --slurpfile report_json "$report_file" '.policyReports += $report_json' < $list_file | sponge $list_file
done
# get policyreport totals for diagnostics
for namespace in "${namespaces[@]}"; do
reports_for_count=$(kubectl get policyreport,clusterpolicyreport -n "$namespace" -o name)
IFS=$'\n' reports_for_count=("$reports_for_count")
count=${#reports_for_count[@]}
echo "found $count policyreport,clusterpolicyreport for namespace $namespace"
done

# collect clusterpolicyreports, exit early if CRD is missing
KIND="clusterpolicyreport"
kubectl get crd "$KIND"s.wgpolicyk8s.io >/dev/null || exit 1
cpol_reports=$(kubectl get $KIND -n $namespace -o name | sed "s/$KIND\.wgpolicyk8s\.io\///g")
IFS=$'\n' cpol_reports=($cpol_reports)

count=${#cpol_reports[@]}
echo "found $count $KIND"

for report in "${cpol_reports[@]}"; do
# remove passed or skipped results to minimize payload and trigger a 'fixed' status for action items
report_json_full=$(kubectl -n $namespace get $KIND $report -o json)
echo $report_json_full | jq '. | del( ."results"[]? | select(."result" == "pass" or ."result" == "skip") )' > $report_file
policy_name=$(cat $report_file | jq -r '.results[0]?.policy')

if [[ "$policy_name" != "null" && (! "${policies[*]}" =~ "${policy_name}") ]]; then
echo "" > $report_file
# retrieve all policyreports in all namespaces, only include those with nonzero numbers of:
# 'fail', 'warn', or 'error'
reports=$(kubectl get policyreport,clusterpolicyreport -A -ojson | jq '.items | map(select(.summary.fail > 0 or .summary.warn > 0 or .summary.error > 0))')
echo "$reports" | jq -c '.[]' | while read -r r; do
# remove 'pass' or 'skip' results from the report, these are not needed for generating
# Insights action items, write to the report file
echo "$r" | jq '. | del( ."results"[]? | select(."result" == "pass" or ."result" == "skip") )' > $report_file
policy_name=$(cat $report_file | jq -r '.results[0]?.policy')
namespace=$(cat $report_file | jq -r '.metadata.namespace')
kind=$(cat $report_file | jq -r '.kind')

# use lookup table to minimize control plane load
if [[ "$policy_name" != "null" && (! "${policies[*]}" =~ ${policy_name}) ]]; then
# determine if report refers to a policy or a clusterpolicy
policy_type="clusterpolicy"

kubectl get $policy_type $policy_name >/dev/null || policy_type="policy -n $namespace"

policy_title=$(kubectl get $policy_type $policy_name -o=jsonpath="{.metadata.annotations.policies\.kyverno\.io\/title}")
policy_description=$(kubectl get $policy_type $policy_name -o=jsonpath="{.metadata.annotations.policies\.kyverno\.io\/description}")

kubectl get $policy_type "$policy_name" >/dev/null || policy_type="policy"
# retrieve necessary metadata from the associated policy
policy_title=$(kubectl -n "$namespace" get "$policy_type" "$policy_name" -o=jsonpath="{.metadata.annotations.policies\.kyverno\.io\/title}")
policy_description=$(kubectl -n "$namespace" get "$policy_type" "$policy_name" -o=jsonpath="{.metadata.annotations.policies\.kyverno\.io\/description}")
# populate the policy title and name
jq --arg title "$policy_title" --arg description "$policy_description" '. += {policyTitle: $title, policyDescription: $description}' < $report_file | sponge $report_file

policies+=("$policy_name")
policy_titles["$policy_name"]=$policy_title
policy_descriptions["$policy_name"]=$policy_description
else
Expand All @@ -94,7 +75,14 @@ for report in "${cpol_reports[@]}"; do
jq --arg title "$policy_title" --arg description "$policy_description" '. += {policyTitle: $title, policyDescription: $description}' < $report_file | sponge $report_file
fi

jq --slurpfile report_json "$report_file" '.clusterPolicyReports += $report_json' < $list_file | sponge $list_file
# append the modified policyreport to the output file
if [[ "$kind" == "PolicyReport" ]]; then
jq --slurpfile report_json "$report_file" '.policyReports += $report_json' < $list_file | sponge $list_file
fi

if [[ "$kind" == "ClusterPolicyReport" ]]; then
jq --slurpfile report_json "$report_file" '.clusterPolicyReports += $report_json' < $list_file | sponge $list_file
fi
done

cat $list_file | jq > $results_file
Expand Down
2 changes: 1 addition & 1 deletion plugins/kyverno/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.5
0.2.0

0 comments on commit 2811fae

Please sign in to comment.