Skip to content
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
19 changes: 17 additions & 2 deletions scripts/guard-consumer-discovery-conservation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,10 @@ while IFS=$'\t' read -r file label; do
# The second reviewed shape (#5102) is the shared catalog's auto-vpa: a
# Kyverno GeneratingPolicy whose spec holds only evaluation settings, one
# apps resource rule (apiGroups, apiVersions, operations, resources) naming
# one deployments, daemonsets or statefulsets resource, and one generate
# one deployments, daemonsets or statefulsets resource, optionally a
# namespaceSelector that only excludes named namespaces (#5125: matchExpressions
# alone, each kubernetes.io/metadata.name NotIn a list of strings; a label
# selector is not CEL and can only narrow what triggers), and one generate
# expression equal, whitespace aside, to the reviewed one for that resource
# (REVIEWED_AUTO_VPA_*). That expression builds only a
# VerticalPodAutoscaler for the triggering workload, in its own namespace,
Expand Down Expand Up @@ -791,7 +794,19 @@ while IFS=$'\t' read -r file label; do
and ([.spec.evaluation | keys | .[] | select((. == "admission" or . == "generateExisting"
or . == "synchronize" or . == "orphanDownstreamOnPolicyDelete") | not)] | length) == 0))
and (.spec.matchConstraints | type) == "!!map"
and ([.spec.matchConstraints | keys | .[] | select(. != "resourceRules")] | length) == 0
and ([.spec.matchConstraints | keys | .[] | select((. == "resourceRules"
or . == "namespaceSelector") | not)] | length) == 0
and ((.spec.matchConstraints | has("namespaceSelector") | not)
or ((.spec.matchConstraints.namespaceSelector | type) == "!!map"
and ([.spec.matchConstraints.namespaceSelector | keys | .[] | select(. != "matchExpressions")] | length) == 0
and (.spec.matchConstraints.namespaceSelector.matchExpressions | type) == "!!seq"
and (.spec.matchConstraints.namespaceSelector.matchExpressions | length) > 0
and ([.spec.matchConstraints.namespaceSelector.matchExpressions[] | select(type != "!!map"
or ([keys | .[] | select((. == "key" or . == "operator" or . == "values") | not)] | length) != 0
or (.key | type) != "!!str" or .key != "kubernetes.io/metadata.name"
or (.operator | type) != "!!str" or .operator != "NotIn"
or (.values | type) != "!!seq" or (.values | length) == 0
or ([.values[] | select(type != "!!str")] | length) != 0)] | length) == 0))
and (.spec.matchConstraints.resourceRules | type) == "!!seq"
and (.spec.matchConstraints.resourceRules | length) == 1
and (.spec.matchConstraints.resourceRules[0] | type) == "!!map"
Expand Down
20 changes: 18 additions & 2 deletions scripts/tests/crossplane-egress-policy-rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,10 @@ rules:
# policies/best-practices/auto-vpa-generating-policy.yaml): a
# GeneratingPolicy whose spec holds only evaluation settings, one apps
# resource rule (apiGroups, apiVersions, operations, resources) naming one
# deployments, daemonsets or statefulsets resource, and one generate
# deployments, daemonsets or statefulsets resource, optionally (#5125) a
# namespaceSelector whose only field is matchExpressions, each
# kubernetes.io/metadata.name NotIn a list of names (a label selector is not
# CEL and can only narrow which workloads trigger it), and one generate
# expression that equals the catalog's expression for that resource once
# spaces, tabs and line breaks are removed from both. Every other spec field
# is refused, because variables and matchConditions are CEL that can read or
Expand Down Expand Up @@ -707,7 +710,20 @@ rules:
'admission', 'generateExisting', 'synchronize',
'orphanDownstreamOnPolicyDelete'])) &&
has(object.spec.matchConstraints) &&
object.spec.matchConstraints.all(key, key == 'resourceRules') &&
object.spec.matchConstraints.all(key,
key in ['resourceRules', 'namespaceSelector']) &&
(!has(object.spec.matchConstraints.namespaceSelector) ||
(object.spec.matchConstraints.namespaceSelector.all(key,
key == 'matchExpressions') &&
has(object.spec.matchConstraints.namespaceSelector.matchExpressions) &&
object.spec.matchConstraints.namespaceSelector.matchExpressions.size() > 0 &&
object.spec.matchConstraints.namespaceSelector.matchExpressions.all(expression,
expression.all(key, key in ['key', 'operator', 'values']) &&
has(expression.key) &&
expression.key == 'kubernetes.io/metadata.name' &&
has(expression.operator) && expression.operator == 'NotIn' &&
has(expression.values) && expression.values.size() > 0 &&
expression.values.all(value, type(value) == string)))) &&
has(object.spec.matchConstraints.resourceRules) &&
object.spec.matchConstraints.resourceRules.size() == 1 &&
object.spec.matchConstraints.resourceRules[0].all(key, key in [
Expand Down
70 changes: 70 additions & 0 deletions scripts/tests/test-crossplane-egress-policy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,76 @@ assert_helm_rules_accept \
"${auto_vpa_one_line_fixture}" \
'a reviewed GeneratingPolicy that differs only in whitespace is the reviewed exception'

# #5125: a namespaceSelector that only excludes named namespaces keeps the
# reviewed shape; every other selector form voids it.
auto_vpa_namespace_exclusion_fixture="${auto_vpa_generating_policy_fixture/ matchConstraints:
/ matchConstraints:
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: NotIn
values: [\"kube-system\", \"kube-public\", \"kube-node-lease\", \"kyverno\"]
}"
[ "${auto_vpa_namespace_exclusion_fixture}" != "${auto_vpa_generating_policy_fixture}" ] ||
fail 'the namespace-excluded GeneratingPolicy must differ from the reviewed one'
assert_helm_rules_accept \
'auto-vpa-generating-policy-namespace-exclusion' \
"${auto_vpa_namespace_exclusion_fixture}" \
'a reviewed GeneratingPolicy that excludes named namespaces is the reviewed exception'

assert_namespace_exclusion_variant_rejected() {
local fixture_name="$1"
local fixture_body="$2"
local failure_message="$3"

[ "${fixture_body}" != "${auto_vpa_namespace_exclusion_fixture}" ] ||
fail "${fixture_name}: the variant must differ from the namespace-excluded GeneratingPolicy"
assert_helm_rules_reject \
"${fixture_name}" \
"${fixture_body}" \
"${failure_message}" \
'reject-cel-policy-producers'
}

assert_namespace_exclusion_variant_rejected \
'generating-policy-namespace-empty-expressions' \
"${auto_vpa_namespace_exclusion_fixture/ matchExpressions:
- key: kubernetes.io\/metadata.name
operator: NotIn
values: \[\"kube-system\", \"kube-public\", \"kube-node-lease\", \"kyverno\"\]/ matchExpressions: []}" \
'a namespaceSelector with no expressions must void the reviewed GeneratingPolicy shape'
assert_namespace_exclusion_variant_rejected \
'generating-policy-namespace-match-labels' \
"${auto_vpa_namespace_exclusion_fixture/ matchExpressions:/ matchLabels:
team: platform
matchExpressions:}" \
'a namespaceSelector with matchLabels must void the reviewed GeneratingPolicy shape'
assert_namespace_exclusion_variant_rejected \
'generating-policy-namespace-in-operator' \
"${auto_vpa_namespace_exclusion_fixture/operator: NotIn/operator: In}" \
'a namespaceSelector that selects namespaces must void the reviewed GeneratingPolicy shape'
assert_namespace_exclusion_variant_rejected \
'generating-policy-namespace-exists-operator' \
"${auto_vpa_namespace_exclusion_fixture/operator: NotIn/operator: Exists}" \
'an Exists namespaceSelector must void the reviewed GeneratingPolicy shape'
assert_namespace_exclusion_variant_rejected \
'generating-policy-namespace-other-key' \
"${auto_vpa_namespace_exclusion_fixture/key: kubernetes.io\/metadata.name/key: team}" \
'a namespaceSelector on another label must void the reviewed GeneratingPolicy shape'
assert_namespace_exclusion_variant_rejected \
'generating-policy-namespace-empty-values' \
"${auto_vpa_namespace_exclusion_fixture/values: \[\"kube-system\", \"kube-public\", \"kube-node-lease\", \"kyverno\"\]/values: []}" \
'a namespaceSelector with no values must void the reviewed GeneratingPolicy shape'
assert_reviewed_generation_variant_rejected \
'generating-policy-object-selector' \
"${auto_vpa_generating_policy_fixture/ matchConstraints:
/ matchConstraints:
objectSelector:
matchLabels:
app: x
}" \
'an objectSelector must void the reviewed GeneratingPolicy shape'

helm_admin_network_policy_fixture=$'apiVersion: policy.networking.k8s.io/v1alpha1\nkind: AdminNetworkPolicy\nmetadata:\n name: crossplane-world-egress\nspec:\n priority: 10\n subject:\n namespaces:\n matchLabels:\n kubernetes.io/metadata.name: crossplane-system\n egress:\n - name: allow-world\n action: Allow\n to:\n - networks: [0.0.0.0/0]'
assert_helm_rules_reject \
'helm-crossplane-admin-network-policy' \
Expand Down
26 changes: 26 additions & 0 deletions scripts/tests/test-guard-consumer-discovery-conservation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,32 @@ YAML
{ printf 'FAIL: the one-line variant did not change the reviewed GeneratingPolicy\n' >&2; failures=$((failures + 1)); }
printf ' - cel-generation.yaml\n' >>"$root/k8s/providers/prod/apps/kustomization.yaml"
expect_pass 'the reviewed auto-vpa GeneratingPolicy on one line does not alter consumers' "$root" '2 consumer(s)'
# #5125: a NotIn exclusion of named namespaces passes too; a label selector
# only narrows which workloads the policy reacts to.
root="$(fixture reviewed-cel-generation-namespace-exclusion)"
yq '.spec.matchConstraints.namespaceSelector = {"matchExpressions": [{"key": "kubernetes.io/metadata.name", "operator": "NotIn", "values": ["kube-system", "kube-public", "kube-node-lease", "kyverno"]}]}' \
"$WORK/reviewed-cel-generation/k8s/providers/prod/apps/cel-generation.yaml" >"$root/k8s/providers/prod/apps/cel-generation.yaml"
printf ' - cel-generation.yaml\n' >>"$root/k8s/providers/prod/apps/kustomization.yaml"
expect_pass 'the reviewed auto-vpa GeneratingPolicy with a namespace exclusion does not alter consumers' "$root" '2 consumer(s)'
for target in match-labels in-operator exists-operator other-key object-selector empty-expressions empty-values non-string-value extra-expression-key; do
root="$(fixture "reviewed-cel-generation-namespace-exclusion-$target")"
cp "$WORK/reviewed-cel-generation-namespace-exclusion/k8s/providers/prod/apps/cel-generation.yaml" "$root/k8s/providers/prod/apps/cel-generation.yaml"
case "$target" in
match-labels) yq -i '.spec.matchConstraints.namespaceSelector.matchLabels = {"team": "platform"}' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
in-operator) yq -i '.spec.matchConstraints.namespaceSelector.matchExpressions[0].operator = "In"' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
exists-operator) yq -i '.spec.matchConstraints.namespaceSelector.matchExpressions[0] |= (.operator = "Exists" | del(.values))' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
other-key) yq -i '.spec.matchConstraints.namespaceSelector.matchExpressions[0].key = "team"' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
object-selector) yq -i '.spec.matchConstraints.objectSelector = {"matchLabels": {"app": "x"}}' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
empty-expressions) yq -i '.spec.matchConstraints.namespaceSelector.matchExpressions = []' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
empty-values) yq -i '.spec.matchConstraints.namespaceSelector.matchExpressions[0].values = []' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
non-string-value) yq -i '.spec.matchConstraints.namespaceSelector.matchExpressions[0].values += [{"name": "x"}]' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
extra-expression-key) yq -i '.spec.matchConstraints.namespaceSelector.matchExpressions[0].extra = "x"' "$root/k8s/providers/prod/apps/cel-generation.yaml" ;;
esac
cmp -s "$WORK/reviewed-cel-generation-namespace-exclusion/k8s/providers/prod/apps/cel-generation.yaml" "$root/k8s/providers/prod/apps/cel-generation.yaml" &&
{ printf 'FAIL: the %s variant did not change the namespace-excluded GeneratingPolicy\n' "$target" >&2; failures=$((failures + 1)); }
printf ' - cel-generation.yaml\n' >>"$root/k8s/providers/prod/apps/kustomization.yaml"
expect_refusal "a $target namespace selector is outside the reviewed shape" "$root" 'unevaluated CEL admission mutation' 'consumers are UNKNOWN'
done
for target in network-policy-kind source-api-version namespace-trigger extra-group variables resource-clone workload-clone computed-key escaped-key label-read generated-deployment unbound-apps-kind unbound-target-ref other-target-name literal-apply-namespace literal-object-namespace mismatched-trigger second-generation match-conditions foreign-group split-literal delete-operation any-version; do
root="$(fixture "reviewed-cel-generation-$target")"
cp "$WORK/reviewed-cel-generation/k8s/providers/prod/apps/cel-generation.yaml" "$root/k8s/providers/prod/apps/cel-generation.yaml"
Expand Down
Loading