diff --git a/api/kyverno/v1/common_types.go b/api/kyverno/v1/common_types.go index 103f674ee9..5a5ddd5176 100644 --- a/api/kyverno/v1/common_types.go +++ b/api/kyverno/v1/common_types.go @@ -197,6 +197,9 @@ type Condition struct { // or can be variables declared using JMESPath. // +optional RawValue *apiextv1.JSON `json:"value,omitempty" yaml:"value,omitempty"` + + // Message is an optional display message + Message string `json:"message,omitempty" yaml:"message,omitempty"` } func (c *Condition) GetKey() apiextensions.JSON { diff --git a/charts/kyverno/templates/crds/crds.yaml b/charts/kyverno/templates/crds/crds.yaml index 82c293ac24..fd9eb76199 100644 --- a/charts/kyverno/templates/crds/crds.yaml +++ b/charts/kyverno/templates/crds/crds.yaml @@ -5710,6 +5710,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -5759,6 +5763,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6210,6 +6218,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6259,6 +6271,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6885,6 +6901,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6936,6 +6956,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9278,6 +9302,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9329,6 +9357,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9802,6 +9834,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9853,6 +9889,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10511,6 +10551,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10563,6 +10607,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12505,6 +12553,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12554,6 +12606,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13173,6 +13229,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13222,6 +13282,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13833,6 +13897,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13884,6 +13952,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -16201,6 +16273,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -16252,6 +16328,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -16725,6 +16805,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -16776,6 +16860,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -17434,6 +17522,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -17486,6 +17578,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -19881,6 +19977,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -19930,6 +20030,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -20381,6 +20485,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -20430,6 +20538,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -21056,6 +21168,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -21107,6 +21223,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -23450,6 +23570,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -23501,6 +23625,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -23974,6 +24102,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -24025,6 +24157,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -24683,6 +24819,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -24735,6 +24875,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -26678,6 +26822,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -26727,6 +26875,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -27346,6 +27498,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -27395,6 +27551,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -28006,6 +28166,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -28057,6 +28221,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -30374,6 +30542,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -30425,6 +30597,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -30898,6 +31074,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -30949,6 +31129,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -31607,6 +31791,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -31659,6 +31847,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators diff --git a/config/crds/kyverno.io_clusterpolicies.yaml b/config/crds/kyverno.io_clusterpolicies.yaml index a78c662bdf..b174c21a32 100644 --- a/config/crds/kyverno.io_clusterpolicies.yaml +++ b/config/crds/kyverno.io_clusterpolicies.yaml @@ -1968,6 +1968,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -2017,6 +2021,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -2468,6 +2476,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -2517,6 +2529,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -3143,6 +3159,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -3194,6 +3214,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -5536,6 +5560,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -5587,6 +5615,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6060,6 +6092,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6111,6 +6147,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6769,6 +6809,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6821,6 +6865,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -8763,6 +8811,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -8812,6 +8864,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9431,6 +9487,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9480,6 +9540,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10091,6 +10155,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10142,6 +10210,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12459,6 +12531,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12510,6 +12586,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12983,6 +13063,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13034,6 +13118,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13692,6 +13780,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13744,6 +13836,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators diff --git a/config/crds/kyverno.io_policies.yaml b/config/crds/kyverno.io_policies.yaml index 73b4366bcd..78f122c931 100644 --- a/config/crds/kyverno.io_policies.yaml +++ b/config/crds/kyverno.io_policies.yaml @@ -1969,6 +1969,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -2018,6 +2022,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -2469,6 +2477,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -2518,6 +2530,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -3144,6 +3160,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -3195,6 +3215,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -5538,6 +5562,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -5589,6 +5617,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6062,6 +6094,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6113,6 +6149,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6771,6 +6811,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6823,6 +6867,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -8766,6 +8814,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -8815,6 +8867,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9434,6 +9490,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9483,6 +9543,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10094,6 +10158,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10145,6 +10213,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12462,6 +12534,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12513,6 +12589,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12986,6 +13066,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13037,6 +13121,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13695,6 +13783,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13747,6 +13839,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index 7282293afe..cdab31a9c9 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -5914,6 +5914,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -5963,6 +5967,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6414,6 +6422,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -6463,6 +6475,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -7089,6 +7105,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -7140,6 +7160,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9482,6 +9506,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -9533,6 +9561,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10006,6 +10038,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10057,6 +10093,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10715,6 +10755,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -10767,6 +10811,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12709,6 +12757,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -12758,6 +12810,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13377,6 +13433,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -13426,6 +13486,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -14037,6 +14101,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -14088,6 +14156,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -16405,6 +16477,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -16456,6 +16532,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -16929,6 +17009,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -16980,6 +17064,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -17638,6 +17726,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -17690,6 +17782,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -20085,6 +20181,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -20134,6 +20234,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -20585,6 +20689,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -20634,6 +20742,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -21260,6 +21372,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -21311,6 +21427,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -23654,6 +23774,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -23705,6 +23829,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -24178,6 +24306,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -24229,6 +24361,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -24887,6 +25023,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -24939,6 +25079,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -26882,6 +27026,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -26931,6 +27079,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -27550,6 +27702,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -27599,6 +27755,10 @@ spec: description: Key is the context entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional display + message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -28210,6 +28370,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -28261,6 +28425,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -30578,6 +30746,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -30629,6 +30801,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -31102,6 +31278,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -31153,6 +31333,10 @@ spec: (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -31811,6 +31995,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators @@ -31863,6 +32051,10 @@ spec: entry (using JMESPath) for conditional rule evaluation. x-kubernetes-preserve-unknown-fields: true + message: + description: Message is an optional + display message + type: string operator: description: 'Operator is the conditional operation to perform. Valid operators diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index 73ebc82e52..a01206c581 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -1120,6 +1120,17 @@ Kubernetes apiextensions/v1.JSON or can be variables declared using JMESPath.

+ + +message
+ +string + + + +

Message is an optional display message

+ +
diff --git a/pkg/engine/attestation_test.go b/pkg/engine/attestation_test.go index 5768649ec7..e48b99c00d 100644 --- a/pkg/engine/attestation_test.go +++ b/pkg/engine/attestation_test.go @@ -260,7 +260,7 @@ func Test_Conditions(t *testing.T) { err := json.Unmarshal([]byte(scanPredicate), &dataMap) assert.NilError(t, err) - pass, err := internal.EvaluateConditions(conditions, ctx, dataMap, logr.Discard()) + pass, _, err := internal.EvaluateConditions(conditions, ctx, dataMap, logr.Discard()) assert.NilError(t, err) assert.Equal(t, pass, true) } diff --git a/pkg/engine/background.go b/pkg/engine/background.go index 73726d1a6a..17116fdea3 100644 --- a/pkg/engine/background.go +++ b/pkg/engine/background.go @@ -9,7 +9,6 @@ import ( "github.com/kyverno/kyverno/pkg/autogen" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/internal" - "github.com/kyverno/kyverno/pkg/engine/utils" engineutils "github.com/kyverno/kyverno/pkg/engine/utils" "github.com/kyverno/kyverno/pkg/engine/variables" ) @@ -104,15 +103,15 @@ func (e *engine) filterRule( } // operate on the copy of the conditions, as we perform variable substitution - copyConditions, err := utils.TransformConditions(ruleCopy.GetAnyAllConditions()) + copyConditions, err := engineutils.TransformConditions(ruleCopy.GetAnyAllConditions()) if err != nil { logger.V(4).Info("cannot copy AnyAllConditions", "reason", err.Error()) return nil } // evaluate pre-conditions - if !variables.EvaluateConditions(logger, ctx, copyConditions) { - logger.V(4).Info("skip rule as preconditions are not met", "rule", ruleCopy.Name) + if val, msg := variables.EvaluateConditions(logger, ctx, copyConditions); !val { + logger.V(4).Info("skip rule as preconditions are not met", "rule", ruleCopy.Name, "message", msg) return engineapi.RuleSkip(ruleCopy.Name, ruleType, "") } diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 94287c188b..f29753a58b 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -20,6 +20,7 @@ import ( "github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/tracing" + stringutils "github.com/kyverno/kyverno/pkg/utils/strings" "go.opentelemetry.io/otel/metric/global" "go.opentelemetry.io/otel/metric/instrument" "go.opentelemetry.io/otel/trace" @@ -256,12 +257,13 @@ func (e *engine) invokeRuleHandler( return resource, handlers.WithError(rule, ruleType, "failed to load context", err) } // check preconditions - preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), rule.GetAnyAllConditions()) + preconditionsPassed, msg, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), rule.GetAnyAllConditions()) if err != nil { return resource, handlers.WithError(rule, ruleType, "failed to evaluate preconditions", err) } if !preconditionsPassed { - return resource, handlers.WithSkip(rule, ruleType, "preconditions not met") + s := stringutils.JoinNonEmpty([]string{"preconditions not met", msg}, "; ") + return resource, handlers.WithSkip(rule, ruleType, s) } // process handler return handler.Process(ctx, logger, policyContext, resource, rule, contextLoader) diff --git a/pkg/engine/handlers/mutation/common.go b/pkg/engine/handlers/mutation/common.go index f88a2772ac..7d6486bf01 100644 --- a/pkg/engine/handlers/mutation/common.go +++ b/pkg/engine/handlers/mutation/common.go @@ -97,13 +97,13 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F return mutate.NewErrorResponse(fmt.Sprintf("failed to load to mutate.foreach[%d].context", index), err) } - preconditionsPassed, err := internal.CheckPreconditions(f.logger, policyContext.JSONContext(), foreach.AnyAllConditions) + preconditionsPassed, msg, err := internal.CheckPreconditions(f.logger, policyContext.JSONContext(), foreach.AnyAllConditions) if err != nil { return mutate.NewErrorResponse(fmt.Sprintf("failed to evaluate mutate.foreach[%d].preconditions", index), err) } if !preconditionsPassed { - f.logger.Info("mutate.foreach.preconditions not met", "elementIndex", index) + f.logger.Info("mutate.foreach.preconditions not met", "elementIndex", index, "message", msg) continue } diff --git a/pkg/engine/handlers/mutation/mutate_existing.go b/pkg/engine/handlers/mutation/mutate_existing.go index ddc0b42d79..2a8bdd56b7 100644 --- a/pkg/engine/handlers/mutation/mutate_existing.go +++ b/pkg/engine/handlers/mutation/mutate_existing.go @@ -10,6 +10,7 @@ import ( "github.com/kyverno/kyverno/pkg/engine/handlers" "github.com/kyverno/kyverno/pkg/engine/internal" "github.com/kyverno/kyverno/pkg/engine/mutate" + stringutils "github.com/kyverno/kyverno/pkg/utils/strings" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -57,14 +58,15 @@ func (h mutateExistingHandler) Process( continue } // load target specific preconditions - preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), target.preconditions) + preconditionsPassed, msg, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), target.preconditions) if err != nil { rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "failed to evaluate preconditions", err) responses = append(responses, *rr) continue } if !preconditionsPassed { - rr := engineapi.RuleSkip(rule.Name, engineapi.Mutation, "preconditions not met") + s := stringutils.JoinNonEmpty([]string{"preconditions not met", msg}, "; ") + rr := engineapi.RuleSkip(rule.Name, engineapi.Mutation, s) responses = append(responses, *rr) continue } diff --git a/pkg/engine/handlers/validation/validate_resource.go b/pkg/engine/handlers/validation/validate_resource.go index 7205c191f9..bacec36bf1 100644 --- a/pkg/engine/handlers/validation/validate_resource.go +++ b/pkg/engine/handlers/validation/validate_resource.go @@ -17,6 +17,7 @@ import ( "github.com/kyverno/kyverno/pkg/engine/variables" "github.com/kyverno/kyverno/pkg/utils/api" datautils "github.com/kyverno/kyverno/pkg/utils/data" + stringutils "github.com/kyverno/kyverno/pkg/utils/strings" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -101,12 +102,13 @@ func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse { if err := v.loadContext(ctx); err != nil { return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to load context", err) } - preconditionsPassed, err := internal.CheckPreconditions(v.log, v.policyContext.JSONContext(), v.anyAllConditions) + preconditionsPassed, msg, err := internal.CheckPreconditions(v.log, v.policyContext.JSONContext(), v.anyAllConditions) if err != nil { return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to evaluate preconditions", err) } if !preconditionsPassed { - return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, "preconditions not met") + s := stringutils.JoinNonEmpty([]string{"preconditions not met", msg}, "; ") + return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, s) } if v.deny != nil { @@ -217,28 +219,31 @@ func (v *validator) loadContext(ctx context.Context) error { } func (v *validator) validateDeny() *engineapi.RuleResponse { - if deny, err := internal.CheckDenyPreconditions(v.log, v.policyContext.JSONContext(), v.deny.GetAnyAllConditions()); err != nil { + if deny, msg, err := internal.CheckDenyPreconditions(v.log, v.policyContext.JSONContext(), v.deny.GetAnyAllConditions()); err != nil { return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to check deny preconditions", err) } else { if deny { - return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny)) + return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny, msg)) } - return engineapi.RulePass(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny)) + return engineapi.RulePass(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny, msg)) } } -func (v *validator) getDenyMessage(deny bool) string { +func (v *validator) getDenyMessage(deny bool, msg string) string { if !deny { return fmt.Sprintf("validation rule '%s' passed.", v.rule.Name) } - msg := v.rule.Validation.Message - if msg == "" { + + if v.rule.Validation.Message == "" && msg == "" { return fmt.Sprintf("validation error: rule %s failed", v.rule.Name) } - raw, err := variables.SubstituteAll(v.log, v.policyContext.JSONContext(), msg) + + s := stringutils.JoinNonEmpty([]string{v.rule.Validation.Message, msg}, "; ") + raw, err := variables.SubstituteAll(v.log, v.policyContext.JSONContext(), s) if err != nil { return msg } + switch typed := raw.(type) { case string: return typed diff --git a/pkg/engine/image_verify_test.go b/pkg/engine/image_verify_test.go index b6207b3275..aaf79ecd27 100644 --- a/pkg/engine/image_verify_test.go +++ b/pkg/engine/image_verify_test.go @@ -17,7 +17,6 @@ import ( "github.com/kyverno/kyverno/pkg/engine/internal" "github.com/kyverno/kyverno/pkg/engine/jmespath" "github.com/kyverno/kyverno/pkg/engine/policycontext" - "github.com/kyverno/kyverno/pkg/engine/utils" engineutils "github.com/kyverno/kyverno/pkg/engine/utils" "github.com/kyverno/kyverno/pkg/registryclient" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" @@ -799,7 +798,7 @@ func Test_MarkImageVerified(t *testing.T) { } func testApplyPatches(t *testing.T, patches [][]byte) unstructured.Unstructured { - patchedResource, err := utils.ApplyPatches([]byte(testResource), patches) + patchedResource, err := engineutils.ApplyPatches([]byte(testResource), patches) assert.NilError(t, err) assert.Assert(t, patchedResource != nil) diff --git a/pkg/engine/internal/imageverifier.go b/pkg/engine/internal/imageverifier.go index bdd42ef6b2..2a4cac58f4 100644 --- a/pkg/engine/internal/imageverifier.go +++ b/pkg/engine/internal/imageverifier.go @@ -162,20 +162,20 @@ func EvaluateConditions( ctx enginecontext.Interface, s map[string]interface{}, log logr.Logger, -) (bool, error) { +) (bool, string, error) { predicate, ok := s["predicate"].(map[string]interface{}) if !ok { - return false, fmt.Errorf("failed to extract predicate from statement: %v", s) + return false, "", fmt.Errorf("failed to extract predicate from statement: %v", s) } if err := enginecontext.AddJSONObject(ctx, predicate); err != nil { - return false, fmt.Errorf("failed to add Statement to the context %v: %w", s, err) + return false, "", fmt.Errorf("failed to add Statement to the context %v: %w", s, err) } c, err := variables.SubstituteAllInConditions(log, ctx, conditions) if err != nil { - return false, fmt.Errorf("failed to substitute variables in attestation conditions: %w", err) + return false, "", fmt.Errorf("failed to substitute variables in attestation conditions: %w", err) } - pass := variables.EvaluateAnyAllConditions(log, ctx, c) - return pass, nil + pass, msg := variables.EvaluateAnyAllConditions(log, ctx, c) + return pass, msg, nil } // verify applies policy rules to each matching image. The policy rule results and annotation patches are @@ -545,20 +545,20 @@ func (iv *ImageVerifier) verifyAttestation(statements []map[string]interface{}, } for _, s := range statements { iv.logger.Info("checking attestation", "predicates", types, "image", imageInfo.String()) - val, err := iv.checkAttestations(attestation, s) + val, msg, err := iv.checkAttestations(attestation, s) if err != nil { return fmt.Errorf("failed to check attestations: %w", err) } if !val { - return fmt.Errorf("attestation checks failed for %s and predicate %s", imageInfo.String(), attestation.PredicateType) + return fmt.Errorf("attestation checks failed for %s and predicate %s: %s", imageInfo.String(), attestation.PredicateType, msg) } } return nil } -func (iv *ImageVerifier) checkAttestations(a kyvernov1.Attestation, s map[string]interface{}) (bool, error) { +func (iv *ImageVerifier) checkAttestations(a kyvernov1.Attestation, s map[string]interface{}) (bool, string, error) { if len(a.Conditions) == 0 { - return true, nil + return true, "", nil } iv.policyContext.JSONContext().Checkpoint() defer iv.policyContext.JSONContext().Restore() diff --git a/pkg/engine/internal/preconditions.go b/pkg/engine/internal/preconditions.go index 3c5a7e9c25..54c0ed1c81 100644 --- a/pkg/engine/internal/preconditions.go +++ b/pkg/engine/internal/preconditions.go @@ -10,26 +10,30 @@ import ( "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" ) -func CheckPreconditions(logger logr.Logger, jsonContext enginecontext.Interface, anyAllConditions apiextensions.JSON) (bool, error) { +func CheckPreconditions(logger logr.Logger, jsonContext enginecontext.Interface, anyAllConditions apiextensions.JSON) (bool, string, error) { preconditions, err := variables.SubstituteAllInPreconditions(logger, jsonContext, anyAllConditions) if err != nil { - return false, fmt.Errorf("failed to substitute variables in preconditions: %w", err) + return false, "", fmt.Errorf("failed to substitute variables in preconditions: %w", err) } typeConditions, err := utils.TransformConditions(preconditions) if err != nil { - return false, fmt.Errorf("failed to parse preconditions: %w", err) + return false, "", fmt.Errorf("failed to parse preconditions: %w", err) } - return variables.EvaluateConditions(logger, jsonContext, typeConditions), nil + + val, msg := variables.EvaluateConditions(logger, jsonContext, typeConditions) + return val, msg, nil } -func CheckDenyPreconditions(logger logr.Logger, jsonContext enginecontext.Interface, anyAllConditions apiextensions.JSON) (bool, error) { +func CheckDenyPreconditions(logger logr.Logger, jsonContext enginecontext.Interface, anyAllConditions apiextensions.JSON) (bool, string, error) { preconditions, err := variables.SubstituteAll(logger, jsonContext, anyAllConditions) if err != nil { - return false, fmt.Errorf("failed to substitute variables in deny conditions: %w", err) + return false, "", fmt.Errorf("failed to substitute variables in deny conditions: %w", err) } typeConditions, err := utils.TransformConditions(preconditions) if err != nil { - return false, fmt.Errorf("failed to parse deny conditions: %w", err) + return false, "", fmt.Errorf("failed to parse deny conditions: %w", err) } - return variables.EvaluateConditions(logger, jsonContext, typeConditions), nil + + val, msg := variables.EvaluateConditions(logger, jsonContext, typeConditions) + return val, msg, nil } diff --git a/pkg/engine/variables/evaluate.go b/pkg/engine/variables/evaluate.go index 03ff1e8d73..b97a2bd8bf 100644 --- a/pkg/engine/variables/evaluate.go +++ b/pkg/engine/variables/evaluate.go @@ -1,6 +1,8 @@ package variables import ( + "strings" + "github.com/go-logr/logr" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" "github.com/kyverno/kyverno/pkg/engine/context" @@ -8,48 +10,54 @@ import ( ) // Evaluate evaluates the condition -func Evaluate(log logr.Logger, ctx context.EvalInterface, condition kyvernov1.Condition) bool { +func Evaluate(log logr.Logger, ctx context.EvalInterface, condition kyvernov1.Condition) (bool, string) { // get handler for the operator handle := operator.CreateOperatorHandler(log, ctx, condition.Operator) if handle == nil { - return false + return false, condition.Message } - return handle.Evaluate(condition.GetKey(), condition.GetValue()) + + return handle.Evaluate(condition.GetKey(), condition.GetValue()), condition.Message } // EvaluateConditions evaluates all the conditions present in a slice, in a backwards compatible way -func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions interface{}) bool { +func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions interface{}) (bool, string) { switch typedConditions := conditions.(type) { case kyvernov1.AnyAllConditions: return evaluateAnyAllConditions(log, ctx, typedConditions) case []kyvernov1.Condition: // backwards compatibility return evaluateOldConditions(log, ctx, typedConditions) } - return false + return false, "invalid condition" } -func EvaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyvernov1.AnyAllConditions) bool { +func EvaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyvernov1.AnyAllConditions) (bool, string) { for _, c := range conditions { - if !evaluateAnyAllConditions(log, ctx, c) { - return false + if val, msg := evaluateAnyAllConditions(log, ctx, c); !val { + return false, msg } } - return true + return true, "" } // evaluateAnyAllConditions evaluates multiple conditions as a logical AND (all) or OR (any) operation depending on the conditions -func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, conditions kyvernov1.AnyAllConditions) bool { +func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, conditions kyvernov1.AnyAllConditions) (bool, string) { anyConditions, allConditions := conditions.AnyConditions, conditions.AllConditions anyConditionsResult, allConditionsResult := true, true + var messages []string // update the anyConditionsResult if they are present if anyConditions != nil { anyConditionsResult = false for _, condition := range anyConditions { - if Evaluate(log, ctx, condition) { + if val, msg := Evaluate(log, ctx, condition); val { anyConditionsResult = true break + } else { + if msg != "" { + messages = append(messages, msg) + } } } @@ -60,24 +68,26 @@ func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, condit // update the allConditionsResult if they are present for _, condition := range allConditions { - if !Evaluate(log, ctx, condition) { + if val, msg := Evaluate(log, ctx, condition); !val { allConditionsResult = false - log.V(3).Info("a condition failed in 'all' block", "condition", condition) + messages = append(messages, msg) + log.V(3).Info("a condition failed in 'all' block", "condition", condition, "message", msg) break } } finalResult := anyConditionsResult && allConditionsResult - return finalResult + message := strings.Join(messages, "; ") + return finalResult, message } // evaluateOldConditions evaluates multiple conditions when those conditions are provided in the old manner i.e. without 'any' or 'all' -func evaluateOldConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyvernov1.Condition) bool { +func evaluateOldConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyvernov1.Condition) (bool, string) { for _, condition := range conditions { - if !Evaluate(log, ctx, condition) { - return false + if val, msg := Evaluate(log, ctx, condition); !val { + return false, msg } } - return true + return true, "" } diff --git a/pkg/engine/variables/evaluate_test.go b/pkg/engine/variables/evaluate_test.go index de0acaefba..98d05ca293 100644 --- a/pkg/engine/variables/evaluate_test.go +++ b/pkg/engine/variables/evaluate_test.go @@ -380,7 +380,7 @@ func TestEvaluate(t *testing.T) { ctx := context.NewContext(jmespath.New(config.NewDefaultConfiguration(false))) for _, tc := range testCases { - if Evaluate(logr.Discard(), ctx, tc.Condition) != tc.Result { + if val, _ := Evaluate(logr.Discard(), ctx, tc.Condition); val != tc.Result { t.Errorf("%v - expected result to be %v", tc.Condition, tc.Result) } } @@ -427,7 +427,9 @@ func Test_Eval_Equal_Var_Pass(t *testing.T) { err = json.Unmarshal(conditionJSON, &condition) assert.Nil(t, err) - assert.True(t, Evaluate(logr.Discard(), ctx, condition)) + + val, _ := Evaluate(logr.Discard(), ctx, condition) + assert.True(t, val) } func Test_Eval_Equal_Var_Fail(t *testing.T) { @@ -456,7 +458,74 @@ func Test_Eval_Equal_Var_Fail(t *testing.T) { RawValue: kyverno.ToJSON("temp1"), } - if Evaluate(logr.Discard(), ctx, condition) { + if val, _ := Evaluate(logr.Discard(), ctx, condition); val { t.Error("expected to fail") } } + +func Test_Condition_Messages(t *testing.T) { + resourceRaw := []byte(` + { + "metadata": { + "name": "temp", + "namespace": "n1" + }, + "spec": { + "foo": "bar", + "foo2": "bar2" + } + } + `) + + ctx := context.NewContext(jmespath.New(config.NewDefaultConfiguration(false))) + err := context.AddResource(ctx, resourceRaw) + if err != nil { + t.Error(err) + } + + conditions := []kyverno.AnyAllConditions{ + { + AnyConditions: []kyverno.Condition{ + { + RawKey: kyverno.ToJSON("{{request.object.metadata.name}}"), + Operator: kyverno.ConditionOperators["Equal"], + RawValue: kyverno.ToJSON("temp"), + Message: "invalid name", + }, + { + RawKey: kyverno.ToJSON("{{request.object.spec.foo}}"), + Operator: kyverno.ConditionOperators["Equal"], + RawValue: kyverno.ToJSON("bar2"), + Message: "invalid foo", + }, + }, + }, + } + + val, msg := EvaluateAnyAllConditions(logr.Discard(), ctx, conditions) + assert.Equal(t, false, val) + assert.Contains(t, msg, "invalid name; invalid foo") + + conditions[0].AnyConditions[1].RawValue = kyverno.ToJSON("bar") + conditions, err = SubstituteAllInConditions(logr.Discard(), ctx, conditions) + assert.Nil(t, err) + + val, msg = EvaluateAnyAllConditions(logr.Discard(), ctx, conditions) + assert.Equal(t, true, val) + assert.Equal(t, msg, "") + + conditions[0].AllConditions = append(conditions[0].AllConditions, conditions[0].AnyConditions[0]) + conditions[0].AllConditions = append(conditions[0].AllConditions, conditions[0].AnyConditions[1]) + conditions[0].AllConditions[1].RawValue = kyverno.ToJSON("bar2") + + val, msg = EvaluateAnyAllConditions(logr.Discard(), ctx, conditions) + assert.Equal(t, false, val) + assert.Contains(t, msg, "invalid foo") + + conditions[0].AnyConditions[0].RawValue = kyverno.ToJSON("temp1") + conditions[0].AnyConditions[1].RawValue = kyverno.ToJSON("bar2") + conditions[0].AllConditions[1].Message = "invalid foo2" + val, msg = EvaluateAnyAllConditions(logr.Discard(), ctx, conditions) + assert.Equal(t, false, val) + assert.Contains(t, msg, "invalid name; invalid foo; invalid foo2") +} diff --git a/pkg/utils/strings/join.go b/pkg/utils/strings/join.go new file mode 100644 index 0000000000..36f4c3dbb1 --- /dev/null +++ b/pkg/utils/strings/join.go @@ -0,0 +1,20 @@ +package strings + +import "strings" + +func JoinNonEmpty(elems []string, sep string) string { + var bldr strings.Builder + var idx int = 0 + for _, s := range elems { + if s != "" { + if idx > 0 { + bldr.WriteString(sep) + } + + bldr.WriteString(s) + idx++ + } + } + + return bldr.String() +} diff --git a/pkg/utils/strings/join_test.go b/pkg/utils/strings/join_test.go new file mode 100644 index 0000000000..0321a821dd --- /dev/null +++ b/pkg/utils/strings/join_test.go @@ -0,0 +1,14 @@ +package strings + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestJoins(t *testing.T) { + assert.Equal(t, "test", JoinNonEmpty([]string{"test", ""}, ",")) + assert.Equal(t, "test,test", JoinNonEmpty([]string{"test", "test"}, ",")) + assert.Equal(t, "test; test", JoinNonEmpty([]string{"test", "", "test", ""}, "; ")) + assert.Equal(t, "fi fo fum", JoinNonEmpty([]string{"", "fi", "", "fo", "", "fum"}, " ")) +}