mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
feat: enable custom data in policy reports using properties (#10933)
* feat: enable custom data in policy reports using properties Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: dont throw error in variable substitution for properties Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> --------- Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>
This commit is contained in:
parent
86fa32af7f
commit
95f54a1cb6
43 changed files with 543 additions and 189 deletions
|
@ -51,6 +51,10 @@ type Rule struct {
|
|||
// +optional
|
||||
Context []ContextEntry `json:"context,omitempty" yaml:"context,omitempty"`
|
||||
|
||||
// ReportProperties are the additional properties from the rule that will be added to the policy report result
|
||||
// +optional
|
||||
ReportProperties map[string]string `json:"reportProperties,omitempty" yaml:"reportProperties,omitempty"`
|
||||
|
||||
// MatchResources defines when this policy rule should be applied. The match
|
||||
// criteria can include resource information (e.g. kind, name, namespace, labels)
|
||||
// and admission review request information like the user name or role.
|
||||
|
|
|
@ -1361,6 +1361,13 @@ func (in *Rule) DeepCopyInto(out *Rule) {
|
|||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.ReportProperties != nil {
|
||||
in, out := &in.ReportProperties, &out.ReportProperties
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
in.MatchResources.DeepCopyInto(&out.MatchResources)
|
||||
in.ExcludeResources.DeepCopyInto(&out.ExcludeResources)
|
||||
if in.ImageExtractors != nil {
|
||||
|
|
|
@ -2814,6 +2814,12 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -7673,6 +7679,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -17172,6 +17185,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
|
|
@ -2815,6 +2815,12 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -7675,6 +7681,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -17175,6 +17188,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
|
|
@ -2808,6 +2808,12 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -7667,6 +7673,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -17166,6 +17179,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
|
|
@ -2809,6 +2809,12 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -7669,6 +7675,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -17169,6 +17182,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
|
|
@ -26,11 +26,13 @@ func TestComputeClusterPolicyReports(t *testing.T) {
|
|||
"pods-require-account",
|
||||
engineapi.Validation,
|
||||
"validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/",
|
||||
nil,
|
||||
),
|
||||
*engineapi.RulePass(
|
||||
"pods-require-limits",
|
||||
engineapi.Validation,
|
||||
"validation rule 'pods-require-limits' passed.",
|
||||
nil,
|
||||
),
|
||||
)
|
||||
clustered, namespaced := ComputePolicyReports(false, er)
|
||||
|
@ -60,11 +62,13 @@ func TestComputePolicyReports(t *testing.T) {
|
|||
"pods-require-account",
|
||||
engineapi.Validation,
|
||||
"validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/",
|
||||
nil,
|
||||
),
|
||||
*engineapi.RulePass(
|
||||
"pods-require-limits",
|
||||
engineapi.Validation,
|
||||
"validation rule 'pods-require-limits' passed.",
|
||||
nil,
|
||||
),
|
||||
)
|
||||
clustered, namespaced := ComputePolicyReports(false, er)
|
||||
|
@ -94,11 +98,13 @@ func TestComputePolicyReportResultsPerPolicyOld(t *testing.T) {
|
|||
"pods-require-account",
|
||||
engineapi.Validation,
|
||||
"validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/",
|
||||
nil,
|
||||
),
|
||||
*engineapi.RulePass(
|
||||
"pods-require-limits",
|
||||
engineapi.Validation,
|
||||
"validation rule 'pods-require-limits' passed.",
|
||||
nil,
|
||||
),
|
||||
)
|
||||
results := ComputePolicyReportResultsPerPolicy(false, er)
|
||||
|
@ -175,7 +181,7 @@ func TestComputePolicyReportResult(t *testing.T) {
|
|||
name: "skip",
|
||||
auditWarn: false,
|
||||
engineResponse: engineapi.NewEngineResponse(unstructured.Unstructured{}, engineapi.NewKyvernoPolicy(policy), nil),
|
||||
ruleResponse: *engineapi.RuleSkip("xxx", engineapi.Mutation, "test"),
|
||||
ruleResponse: *engineapi.RuleSkip("xxx", engineapi.Mutation, "test", nil),
|
||||
want: policyreportv1alpha2.PolicyReportResult{
|
||||
Source: "kyverno",
|
||||
Policy: "pod-requirements",
|
||||
|
@ -191,7 +197,7 @@ func TestComputePolicyReportResult(t *testing.T) {
|
|||
name: "pass",
|
||||
auditWarn: false,
|
||||
engineResponse: engineapi.NewEngineResponse(unstructured.Unstructured{}, engineapi.NewKyvernoPolicy(policy), nil),
|
||||
ruleResponse: *engineapi.RulePass("xxx", engineapi.Mutation, "test"),
|
||||
ruleResponse: *engineapi.RulePass("xxx", engineapi.Mutation, "test", nil),
|
||||
want: policyreportv1alpha2.PolicyReportResult{
|
||||
Source: "kyverno",
|
||||
Policy: "pod-requirements",
|
||||
|
@ -207,7 +213,7 @@ func TestComputePolicyReportResult(t *testing.T) {
|
|||
name: "fail",
|
||||
auditWarn: false,
|
||||
engineResponse: engineapi.NewEngineResponse(unstructured.Unstructured{}, engineapi.NewKyvernoPolicy(policy), nil),
|
||||
ruleResponse: *engineapi.RuleFail("xxx", engineapi.Mutation, "test"),
|
||||
ruleResponse: *engineapi.RuleFail("xxx", engineapi.Mutation, "test", nil),
|
||||
want: policyreportv1alpha2.PolicyReportResult{
|
||||
Source: "kyverno",
|
||||
Policy: "pod-requirements",
|
||||
|
@ -223,7 +229,7 @@ func TestComputePolicyReportResult(t *testing.T) {
|
|||
name: "fail - audit warn",
|
||||
auditWarn: true,
|
||||
engineResponse: engineapi.NewEngineResponse(unstructured.Unstructured{}, engineapi.NewKyvernoPolicy(policy), nil),
|
||||
ruleResponse: *engineapi.RuleFail("xxx", engineapi.Mutation, "test"),
|
||||
ruleResponse: *engineapi.RuleFail("xxx", engineapi.Mutation, "test", nil),
|
||||
want: policyreportv1alpha2.PolicyReportResult{
|
||||
Source: "kyverno",
|
||||
Policy: "pod-requirements",
|
||||
|
@ -239,7 +245,7 @@ func TestComputePolicyReportResult(t *testing.T) {
|
|||
name: "error",
|
||||
auditWarn: false,
|
||||
engineResponse: engineapi.NewEngineResponse(unstructured.Unstructured{}, engineapi.NewKyvernoPolicy(policy), nil),
|
||||
ruleResponse: *engineapi.RuleError("xxx", engineapi.Mutation, "test", nil),
|
||||
ruleResponse: *engineapi.RuleError("xxx", engineapi.Mutation, "test", nil, nil),
|
||||
want: policyreportv1alpha2.PolicyReportResult{
|
||||
Source: "kyverno",
|
||||
Policy: "pod-requirements",
|
||||
|
@ -255,7 +261,7 @@ func TestComputePolicyReportResult(t *testing.T) {
|
|||
name: "warn",
|
||||
auditWarn: false,
|
||||
engineResponse: engineapi.NewEngineResponse(unstructured.Unstructured{}, engineapi.NewKyvernoPolicy(policy), nil),
|
||||
ruleResponse: *engineapi.RuleWarn("xxx", engineapi.Mutation, "test"),
|
||||
ruleResponse: *engineapi.RuleWarn("xxx", engineapi.Mutation, "test", nil),
|
||||
want: policyreportv1alpha2.PolicyReportResult{
|
||||
Source: "kyverno",
|
||||
Policy: "pod-requirements",
|
||||
|
@ -294,7 +300,7 @@ func TestPSSComputePolicyReportResult(t *testing.T) {
|
|||
name: "fail",
|
||||
auditWarn: false,
|
||||
engineResponse: engineapi.NewEngineResponse(unstructured.Unstructured{}, engineapi.NewKyvernoPolicy(policy), nil),
|
||||
ruleResponse: *engineapi.RuleFail("xxx", engineapi.Mutation, "test"),
|
||||
ruleResponse: *engineapi.RuleFail("xxx", engineapi.Mutation, "test", nil),
|
||||
want: policyreportv1alpha2.PolicyReportResult{
|
||||
Source: "kyverno",
|
||||
Policy: "psa",
|
||||
|
|
|
@ -2808,6 +2808,12 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -7667,6 +7673,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -17166,6 +17179,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
|
|
@ -2809,6 +2809,12 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -7669,6 +7675,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -17169,6 +17182,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
|
|
@ -8007,6 +8007,12 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -12866,6 +12872,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -22365,6 +22378,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -27546,6 +27566,12 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -32406,6 +32432,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
@ -41906,6 +41939,13 @@ spec:
|
|||
will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/preconditions/
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
reportProperties:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: ReportProperties are the additional properties
|
||||
from the rule that will be added to the policy report
|
||||
result
|
||||
type: object
|
||||
skipBackgroundRequests:
|
||||
default: true
|
||||
description: |-
|
||||
|
|
|
@ -3828,6 +3828,18 @@ string
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>reportProperties</code><br/>
|
||||
<em>
|
||||
map[string]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ReportProperties are the additional properties from the rule that will be added to the policy report result</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>match</code><br/>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.MatchResources">
|
||||
|
|
|
@ -7590,6 +7590,33 @@ declaration to specify which resources to exclude.</p>
|
|||
|
||||
|
||||
|
||||
<tr>
|
||||
<td><code>reportProperties</code>
|
||||
|
||||
</br>
|
||||
|
||||
|
||||
|
||||
|
||||
<span style="font-family: monospace">map[string]string</span>
|
||||
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
<p>ReportProperties are the additional properties from the rule that will be added to the policy report result</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td><code>match</code>
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
type RuleApplyConfiguration struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Context []ContextEntryApplyConfiguration `json:"context,omitempty"`
|
||||
ReportProperties map[string]string `json:"reportProperties,omitempty"`
|
||||
MatchResources *MatchResourcesApplyConfiguration `json:"match,omitempty"`
|
||||
ExcludeResources *MatchResourcesApplyConfiguration `json:"exclude,omitempty"`
|
||||
ImageExtractors *kyvernov1.ImageExtractorConfigs `json:"imageExtractors,omitempty"`
|
||||
|
@ -67,6 +68,20 @@ func (b *RuleApplyConfiguration) WithContext(values ...*ContextEntryApplyConfigu
|
|||
return b
|
||||
}
|
||||
|
||||
// WithReportProperties puts the entries into the ReportProperties field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, the entries provided by each call will be put on the ReportProperties field,
|
||||
// overwriting an existing map entries in ReportProperties field with the same key.
|
||||
func (b *RuleApplyConfiguration) WithReportProperties(entries map[string]string) *RuleApplyConfiguration {
|
||||
if b.ReportProperties == nil && len(entries) > 0 {
|
||||
b.ReportProperties = make(map[string]string, len(entries))
|
||||
}
|
||||
for k, v := range entries {
|
||||
b.ReportProperties[k] = v
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithMatchResources sets the MatchResources field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the MatchResources field is set to the value of the last call.
|
||||
|
|
|
@ -112,7 +112,7 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -121,7 +121,7 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -133,7 +133,7 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -145,7 +145,7 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -157,7 +157,7 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -197,7 +197,7 @@ func TestEngineResponse_IsSuccessful(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("", Validation, ""),
|
||||
*RulePass("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -206,7 +206,7 @@ func TestEngineResponse_IsSuccessful(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -215,7 +215,7 @@ func TestEngineResponse_IsSuccessful(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("", Validation, ""),
|
||||
*RuleWarn("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -224,7 +224,7 @@ func TestEngineResponse_IsSuccessful(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("", Validation, "", nil),
|
||||
*RuleError("", Validation, "", nil, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -233,7 +233,7 @@ func TestEngineResponse_IsSuccessful(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("", Validation, ""),
|
||||
*RuleSkip("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -270,7 +270,7 @@ func TestEngineResponse_IsSkipped(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("", Validation, ""),
|
||||
*RulePass("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -279,7 +279,7 @@ func TestEngineResponse_IsSkipped(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -288,7 +288,7 @@ func TestEngineResponse_IsSkipped(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("", Validation, ""),
|
||||
*RuleWarn("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -297,7 +297,7 @@ func TestEngineResponse_IsSkipped(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("", Validation, "", nil),
|
||||
*RuleError("", Validation, "", nil, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -306,7 +306,7 @@ func TestEngineResponse_IsSkipped(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("", Validation, ""),
|
||||
*RuleSkip("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -343,7 +343,7 @@ func TestEngineResponse_IsFailed(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("", Validation, ""),
|
||||
*RulePass("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -352,7 +352,7 @@ func TestEngineResponse_IsFailed(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -361,7 +361,7 @@ func TestEngineResponse_IsFailed(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("", Validation, ""),
|
||||
*RuleWarn("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -370,7 +370,7 @@ func TestEngineResponse_IsFailed(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("", Validation, "", nil),
|
||||
*RuleError("", Validation, "", nil, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -379,7 +379,7 @@ func TestEngineResponse_IsFailed(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("", Validation, ""),
|
||||
*RuleSkip("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -416,7 +416,7 @@ func TestEngineResponse_IsError(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("", Validation, ""),
|
||||
*RulePass("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -425,7 +425,7 @@ func TestEngineResponse_IsError(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
*RuleFail("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -434,7 +434,7 @@ func TestEngineResponse_IsError(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("", Validation, ""),
|
||||
*RuleWarn("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -443,7 +443,7 @@ func TestEngineResponse_IsError(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("", Validation, "", nil),
|
||||
*RuleError("", Validation, "", nil, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -452,7 +452,7 @@ func TestEngineResponse_IsError(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("", Validation, ""),
|
||||
*RuleSkip("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -487,7 +487,7 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("skip", Validation, ""),
|
||||
*RuleSkip("skip", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -495,7 +495,7 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("warn", Validation, ""),
|
||||
*RuleWarn("warn", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -503,7 +503,7 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass", Validation, ""),
|
||||
*RulePass("pass", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -511,7 +511,7 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail", Validation, ""),
|
||||
*RuleFail("fail", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -520,8 +520,8 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail-1", Validation, ""),
|
||||
*RuleFail("fail-2", Validation, ""),
|
||||
*RuleFail("fail-1", Validation, "", nil),
|
||||
*RuleFail("fail-2", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -530,8 +530,8 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail-1", Validation, ""),
|
||||
*RuleError("error-1", Validation, "", nil),
|
||||
*RuleFail("fail-1", Validation, "", nil),
|
||||
*RuleError("error-1", Validation, "", nil, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -540,8 +540,8 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("error-1", Validation, "", nil),
|
||||
*RuleError("error-2", Validation, "", nil),
|
||||
*RuleError("error-1", Validation, "", nil, nil),
|
||||
*RuleError("error-2", Validation, "", nil, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -576,7 +576,7 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("skip", Validation, ""),
|
||||
*RuleSkip("skip", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -584,7 +584,7 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("warn", Validation, ""),
|
||||
*RuleWarn("warn", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -592,8 +592,8 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass-1", Validation, ""),
|
||||
*RulePass("pass-2", Validation, ""),
|
||||
*RulePass("pass-1", Validation, "", nil),
|
||||
*RulePass("pass-2", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -602,7 +602,7 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass", Validation, ""),
|
||||
*RulePass("pass", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -611,8 +611,8 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass", Validation, ""),
|
||||
*RuleFail("fail", Validation, ""),
|
||||
*RulePass("pass", Validation, "", nil),
|
||||
*RuleFail("fail", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -621,8 +621,8 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass", Validation, ""),
|
||||
*RuleSkip("skip", Validation, ""),
|
||||
*RulePass("pass", Validation, "", nil),
|
||||
*RuleSkip("skip", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -631,7 +631,7 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail", Validation, ""),
|
||||
*RuleFail("fail", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -639,8 +639,8 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail-1", Validation, ""),
|
||||
*RuleFail("fail-2", Validation, ""),
|
||||
*RuleFail("fail-1", Validation, "", nil),
|
||||
*RuleFail("fail-2", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -648,8 +648,8 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail-1", Validation, ""),
|
||||
*RuleError("error-1", Validation, "", nil),
|
||||
*RuleFail("fail-1", Validation, "", nil),
|
||||
*RuleError("error-1", Validation, "", nil, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -657,8 +657,8 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("error-1", Validation, "", nil),
|
||||
*RuleError("error-2", Validation, "", nil),
|
||||
*RuleError("error-1", Validation, "", nil, nil),
|
||||
*RuleError("error-2", Validation, "", nil, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -49,9 +49,11 @@ type RuleResponse struct {
|
|||
binding *admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding
|
||||
// emitWarning enable passing rule message as warning to api server warning header
|
||||
emitWarning bool
|
||||
// properties are the additional properties from the rule that will be added to the policy report result
|
||||
properties map[string]string
|
||||
}
|
||||
|
||||
func NewRuleResponse(name string, ruleType RuleType, msg string, status RuleStatus) *RuleResponse {
|
||||
func NewRuleResponse(name string, ruleType RuleType, msg string, status RuleStatus, properties map[string]string) *RuleResponse {
|
||||
emitWarn := false
|
||||
if status == RuleStatusError || status == RuleStatusFail || status == RuleStatusWarn {
|
||||
emitWarn = true
|
||||
|
@ -62,30 +64,31 @@ func NewRuleResponse(name string, ruleType RuleType, msg string, status RuleStat
|
|||
message: msg,
|
||||
status: status,
|
||||
emitWarning: emitWarn,
|
||||
properties: properties,
|
||||
}
|
||||
}
|
||||
|
||||
func RuleError(name string, ruleType RuleType, msg string, err error) *RuleResponse {
|
||||
func RuleError(name string, ruleType RuleType, msg string, err error, properties map[string]string) *RuleResponse {
|
||||
if err != nil {
|
||||
return NewRuleResponse(name, ruleType, fmt.Sprintf("%s: %s", msg, err.Error()), RuleStatusError)
|
||||
return NewRuleResponse(name, ruleType, fmt.Sprintf("%s: %s", msg, err.Error()), RuleStatusError, properties)
|
||||
}
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusError)
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusError, properties)
|
||||
}
|
||||
|
||||
func RuleSkip(name string, ruleType RuleType, msg string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusSkip)
|
||||
func RuleSkip(name string, ruleType RuleType, msg string, properties map[string]string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusSkip, properties)
|
||||
}
|
||||
|
||||
func RuleWarn(name string, ruleType RuleType, msg string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusWarn)
|
||||
func RuleWarn(name string, ruleType RuleType, msg string, properties map[string]string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusWarn, properties)
|
||||
}
|
||||
|
||||
func RulePass(name string, ruleType RuleType, msg string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusPass)
|
||||
func RulePass(name string, ruleType RuleType, msg string, properties map[string]string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusPass, properties)
|
||||
}
|
||||
|
||||
func RuleFail(name string, ruleType RuleType, msg string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusFail)
|
||||
func RuleFail(name string, ruleType RuleType, msg string, properties map[string]string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusFail, properties)
|
||||
}
|
||||
|
||||
func (r RuleResponse) WithExceptions(exceptions []kyvernov2.PolicyException) *RuleResponse {
|
||||
|
@ -173,6 +176,10 @@ func (r *RuleResponse) EmitWarning() bool {
|
|||
return r.emitWarning
|
||||
}
|
||||
|
||||
func (r *RuleResponse) Properties() map[string]string {
|
||||
return r.properties
|
||||
}
|
||||
|
||||
// HasStatus checks if rule status is in a given list
|
||||
func (r *RuleResponse) HasStatus(status ...RuleStatus) bool {
|
||||
for _, s := range status {
|
||||
|
|
|
@ -51,6 +51,7 @@ func TestRuleResponse_String(t *testing.T) {
|
|||
tt.fields.Type,
|
||||
tt.fields.Message,
|
||||
tt.fields.Status,
|
||||
nil,
|
||||
)
|
||||
if got := rr.String(); got != tt.want {
|
||||
t.Errorf("RuleResponse.ToString() = %v, want %v", got, tt.want)
|
||||
|
@ -119,6 +120,7 @@ func TestRuleResponse_HasStatus(t *testing.T) {
|
|||
tt.fields.Type,
|
||||
tt.fields.Message,
|
||||
tt.fields.Status,
|
||||
nil,
|
||||
)
|
||||
if got := r.HasStatus(tt.args.status...); got != tt.want {
|
||||
t.Errorf("RuleResponse.HasStatus() = %v, want %v", got, tt.want)
|
||||
|
|
|
@ -73,13 +73,13 @@ func (e *engine) filterRule(
|
|||
key, err := cache.MetaNamespaceKeyFunc(&matchedExceptions[i])
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName())
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to compute exception key", err)
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to compute exception key", err, rule.ReportProperties)
|
||||
}
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return engineapi.RuleSkip(rule.Name, ruleType, "rule is skipped due to policy exception "+strings.Join(keys, ", ")).WithExceptions(matchedExceptions)
|
||||
return engineapi.RuleSkip(rule.Name, ruleType, "rule is skipped due to policy exception "+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions)
|
||||
}
|
||||
|
||||
newResource := policyContext.NewResource()
|
||||
|
@ -93,7 +93,7 @@ func (e *engine) filterRule(
|
|||
if ruleType == engineapi.Generation {
|
||||
// if the oldResource matched, return "false" to delete GR for it
|
||||
if err = engineutils.MatchesResourceDescription(oldResource, rule, admissionInfo, namespaceLabels, policy.GetNamespace(), gvk, subresource, policyContext.Operation()); err == nil {
|
||||
return engineapi.RuleFail(rule.Name, ruleType, "")
|
||||
return engineapi.RuleFail(rule.Name, ruleType, "", rule.ReportProperties)
|
||||
}
|
||||
}
|
||||
logger.V(4).Info("rule not matched", "reason", err.Error())
|
||||
|
@ -113,32 +113,32 @@ func (e *engine) filterRule(
|
|||
copyConditions, err := engineutils.TransformConditions(rule.GetAnyAllConditions())
|
||||
if err != nil {
|
||||
logger.V(4).Info("cannot copy AnyAllConditions", "reason", err.Error())
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to convert AnyAllConditions", err)
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to convert AnyAllConditions", err, rule.ReportProperties)
|
||||
}
|
||||
|
||||
// evaluate pre-conditions
|
||||
pass, msg, err := variables.EvaluateConditions(logger, policyContext.JSONContext(), copyConditions)
|
||||
if err != nil {
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to evaluate conditions", err)
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to evaluate conditions", err, rule.ReportProperties)
|
||||
}
|
||||
|
||||
if pass {
|
||||
return engineapi.RulePass(rule.Name, ruleType, "")
|
||||
return engineapi.RulePass(rule.Name, ruleType, "", rule.ReportProperties)
|
||||
}
|
||||
|
||||
if policyContext.OldResource().Object != nil {
|
||||
if err = policyContext.JSONContext().AddResource(policyContext.OldResource().Object); err != nil {
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to update JSON context for old resource", err)
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to update JSON context for old resource", err, rule.ReportProperties)
|
||||
}
|
||||
if val, msg, err := variables.EvaluateConditions(logger, policyContext.JSONContext(), copyConditions); err != nil {
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to evaluate conditions for old resource", err)
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to evaluate conditions for old resource", err, rule.ReportProperties)
|
||||
} else {
|
||||
if val {
|
||||
return engineapi.RuleFail(rule.Name, ruleType, msg)
|
||||
return engineapi.RuleFail(rule.Name, ruleType, msg, rule.ReportProperties)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.V(4).Info("skip rule as preconditions are not met", "rule", rule.Name, "message", msg)
|
||||
return engineapi.RuleSkip(rule.Name, ruleType, "")
|
||||
return engineapi.RuleSkip(rule.Name, ruleType, "", rule.ReportProperties)
|
||||
}
|
||||
|
|
|
@ -280,6 +280,10 @@ func (e *engine) invokeRuleHandler(
|
|||
s := stringutils.JoinNonEmpty([]string{"preconditions not met", msg}, "; ")
|
||||
return resource, handlers.WithSkip(rule, ruleType, s)
|
||||
}
|
||||
// substitute properties
|
||||
if err := internal.SubstitutePropertiesInRule(logger, &rule, policyContext.JSONContext()); err != nil {
|
||||
logger.Error(err, "failed to substitute variables in rule properties")
|
||||
}
|
||||
// get policy exceptions that matches both policy and rule name
|
||||
exceptions, err := e.GetPolicyExceptions(policyContext.Policy(), rule.Name)
|
||||
if err != nil {
|
||||
|
|
|
@ -23,19 +23,19 @@ type Handler interface {
|
|||
}
|
||||
|
||||
func WithError(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string, err error) []engineapi.RuleResponse {
|
||||
return WithResponses(engineapi.RuleError(rule.Name, ruleType, msg, err))
|
||||
return WithResponses(engineapi.RuleError(rule.Name, ruleType, msg, err, rule.ReportProperties))
|
||||
}
|
||||
|
||||
func WithSkip(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string) []engineapi.RuleResponse {
|
||||
return WithResponses(engineapi.RuleSkip(rule.Name, ruleType, msg))
|
||||
return WithResponses(engineapi.RuleSkip(rule.Name, ruleType, msg, rule.ReportProperties))
|
||||
}
|
||||
|
||||
func WithPass(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string) []engineapi.RuleResponse {
|
||||
return WithResponses(engineapi.RulePass(rule.Name, ruleType, msg))
|
||||
return WithResponses(engineapi.RulePass(rule.Name, ruleType, msg, rule.ReportProperties))
|
||||
}
|
||||
|
||||
func WithFail(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string) []engineapi.RuleResponse {
|
||||
return WithResponses(engineapi.RuleFail(rule.Name, ruleType, msg))
|
||||
return WithResponses(engineapi.RuleFail(rule.Name, ruleType, msg, rule.ReportProperties))
|
||||
}
|
||||
|
||||
func WithResponses(rrs ...*engineapi.RuleResponse) []engineapi.RuleResponse {
|
||||
|
|
|
@ -152,6 +152,7 @@ func buildRuleResponse(rule *kyvernov1.Rule, mutateResp *mutate.Response, info r
|
|||
engineapi.Mutation,
|
||||
message,
|
||||
mutateResp.Status,
|
||||
rule.ReportProperties,
|
||||
)
|
||||
if mutateResp.Status == engineapi.RuleStatusPass {
|
||||
if len(rule.Mutation.Targets) != 0 {
|
||||
|
|
|
@ -53,7 +53,7 @@ func (h mutateExistingHandler) Process(
|
|||
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Mutation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Mutation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ func (h mutateExistingHandler) Process(
|
|||
logger.V(3).Info("processing mutate rule")
|
||||
targets, err := loadTargets(ctx, h.client, rule.Mutation.Targets, policyContext, logger)
|
||||
if err != nil {
|
||||
rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "", err)
|
||||
rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "", err, rule.ReportProperties)
|
||||
responses = append(responses, *rr)
|
||||
}
|
||||
|
||||
|
@ -76,20 +76,20 @@ func (h mutateExistingHandler) Process(
|
|||
}
|
||||
// load target specific context
|
||||
if err := contextLoader(ctx, target.context, policyContext.JSONContext()); err != nil {
|
||||
rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "failed to load context", err)
|
||||
rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "failed to load context", err, rule.ReportProperties)
|
||||
responses = append(responses, *rr)
|
||||
continue
|
||||
}
|
||||
// load target specific 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)
|
||||
rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "failed to evaluate preconditions", err, rule.ReportProperties)
|
||||
responses = append(responses, *rr)
|
||||
continue
|
||||
}
|
||||
if !preconditionsPassed {
|
||||
s := stringutils.JoinNonEmpty([]string{"preconditions not met", msg}, "; ")
|
||||
rr := engineapi.RuleSkip(rule.Name, engineapi.Mutation, s)
|
||||
rr := engineapi.RuleSkip(rule.Name, engineapi.Mutation, s, rule.ReportProperties)
|
||||
responses = append(responses, *rr)
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ func (h mutateImageHandler) Process(
|
|||
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Mutation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Mutation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ func (h mutateImageHandler) Process(
|
|||
ruleCopy, err := substituteVariables(rule, jsonContext, logger)
|
||||
if err != nil {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to substitute variables", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to substitute variables", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
var engineResponses []*engineapi.RuleResponse
|
||||
|
@ -101,7 +101,7 @@ func (h mutateImageHandler) Process(
|
|||
rclient, err := h.rclientFactory.GetClient(ctx, imageVerify.ImageRegistryCredentials)
|
||||
if err != nil {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to fetch secrets", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to fetch secrets", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
iv := internal.NewImageVerifier(logger, rclient, h.ivCache, policyContext, *ruleCopy, h.ivm)
|
||||
|
@ -114,25 +114,25 @@ func (h mutateImageHandler) Process(
|
|||
decoded, err := json_patch.DecodePatch(patch)
|
||||
if err != nil {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to decode patch", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to decode patch", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
options := &json_patch.ApplyOptions{SupportNegativeIndices: true, AllowMissingPathOnRemove: true, EnsurePathExistsOnAdd: true}
|
||||
resourceBytes, err := resource.MarshalJSON()
|
||||
if err != nil {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to marshal resource", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to marshal resource", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
patchedResourceBytes, err := decoded.ApplyWithOptions(resourceBytes, options)
|
||||
if err != nil {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to apply patch", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to apply patch", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
if err := resource.UnmarshalJSON(patchedResourceBytes); err != nil {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to unmarshal resource", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to unmarshal resource", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ func (h mutateResourceHandler) Process(
|
|||
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Mutation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Mutation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ func (h validateAssertHandler) Process(
|
|||
}
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions),
|
||||
)
|
||||
}
|
||||
// load context
|
||||
|
@ -79,7 +79,7 @@ func (h validateAssertHandler) Process(
|
|||
logger.Error(err, "failed to load context")
|
||||
}
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.Validation, "failed to load context", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.Validation, "failed to load context", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
// prepare bindings
|
||||
|
@ -113,12 +113,12 @@ func (h validateAssertHandler) Process(
|
|||
if len(errs) != 0 {
|
||||
var responses []*engineapi.RuleResponse
|
||||
for _, err := range errs {
|
||||
responses = append(responses, engineapi.RuleFail(rule.Name, engineapi.Validation, err.Error()))
|
||||
responses = append(responses, engineapi.RuleFail(rule.Name, engineapi.Validation, err.Error(), rule.ReportProperties))
|
||||
}
|
||||
return resource, handlers.WithResponses(responses...)
|
||||
}
|
||||
msg := fmt.Sprintf("Validation rule '%s' passed.", rule.Name)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RulePass(rule.Name, engineapi.Validation, msg),
|
||||
engineapi.RulePass(rule.Name, engineapi.Validation, msg, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ func (h validateCELHandler) Process(
|
|||
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ func (h validateCELHandler) Process(
|
|||
namespace, err = h.client.GetNamespace(ctx, ns, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.Validation, "Error getting the resource's namespace", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.Validation, "Error getting the resource's namespace", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -174,7 +174,7 @@ func (h validateCELHandler) Process(
|
|||
params, err := collectParams(ctx, h.client, paramKind, paramRef, ns)
|
||||
if err != nil {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.Validation, "error in parameterized resource", err),
|
||||
engineapi.RuleError(rule.Name, engineapi.Validation, "error in parameterized resource", err, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ func (h validateCELHandler) Process(
|
|||
// no validations are returned if preconditions aren't met
|
||||
if datautils.DeepEqual(validationResult, validating.ValidateResult{}) {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "cel preconditions not met"),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "cel preconditions not met", rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -198,12 +198,12 @@ func (h validateCELHandler) Process(
|
|||
case validating.ActionAdmit:
|
||||
if decision.Evaluation == validating.EvalError {
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.Validation, decision.Message, nil),
|
||||
engineapi.RuleError(rule.Name, engineapi.Validation, decision.Message, nil, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
case validating.ActionDeny:
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleFail(rule.Name, engineapi.Validation, decision.Message),
|
||||
engineapi.RuleFail(rule.Name, engineapi.Validation, decision.Message, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ func (h validateCELHandler) Process(
|
|||
|
||||
msg := fmt.Sprintf("Validation rule '%s' passed.", rule.Name)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RulePass(rule.Name, engineapi.Validation, msg),
|
||||
engineapi.RulePass(rule.Name, engineapi.Validation, msg, rule.ReportProperties),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ func (h validateImageHandler) Process(
|
|||
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ func (h validateManifestHandler) Process(
|
|||
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ func (h validatePssHandler) Process(
|
|||
}
|
||||
logger.V(3).Info("policy rule is skipped due to policy exception", "exception", key)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exception "+key).WithExceptions([]kyvernov2.PolicyException{polex}),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exception "+key, rule.ReportProperties).WithExceptions([]kyvernov2.PolicyException{polex}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ func (h validatePssHandler) Process(
|
|||
if allowed {
|
||||
msg := fmt.Sprintf("Validation rule '%s' passed.", rule.Name)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RulePass(rule.Name, engineapi.Validation, msg).WithPodSecurityChecks(podSecurityChecks),
|
||||
engineapi.RulePass(rule.Name, engineapi.Validation, msg, rule.ReportProperties).WithPodSecurityChecks(podSecurityChecks),
|
||||
)
|
||||
} else {
|
||||
// apply pod security exceptions if exist
|
||||
|
@ -120,12 +120,12 @@ func (h validatePssHandler) Process(
|
|||
podSecurityChecks.Checks = pssChecks
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions "+strings.Join(keys, ", ")).WithExceptions(matchedExceptions).WithPodSecurityChecks(podSecurityChecks),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions "+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions).WithPodSecurityChecks(podSecurityChecks),
|
||||
)
|
||||
}
|
||||
msg := fmt.Sprintf(`Validation rule '%s' failed. It violates PodSecurity "%s:%s": %s`, rule.Name, podSecurity.Level, podSecurity.Version, pss.FormatChecksPrint(pssChecks))
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleFail(rule.Name, engineapi.Validation, msg).WithPodSecurityChecks(podSecurityChecks),
|
||||
engineapi.RuleFail(rule.Name, engineapi.Validation, msg, rule.ReportProperties).WithPodSecurityChecks(podSecurityChecks),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ func (h validateResourceHandler) Process(
|
|||
|
||||
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", "), rule.ReportProperties).WithExceptions(matchedExceptions),
|
||||
)
|
||||
}
|
||||
v := newValidator(logger, contextLoader, policyContext, rule)
|
||||
|
@ -120,15 +120,15 @@ func newForEachValidator(
|
|||
|
||||
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)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to load context", err, v.rule.ReportProperties)
|
||||
}
|
||||
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)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to evaluate preconditions", err, v.rule.ReportProperties)
|
||||
}
|
||||
if !preconditionsPassed {
|
||||
s := stringutils.JoinNonEmpty([]string{"preconditions not met", msg}, "; ")
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, s)
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, s, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
if v.deny != nil {
|
||||
|
@ -137,7 +137,7 @@ func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse {
|
|||
|
||||
if v.pattern != nil || v.anyPattern != nil {
|
||||
if err = v.substitutePatterns(); err != nil {
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "variable substitution failed", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "variable substitution failed", err, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
ruleResponse := v.validateResourceWithRule()
|
||||
|
@ -145,7 +145,7 @@ func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse {
|
|||
if engineutils.IsUpdateRequest(v.policyContext) {
|
||||
priorResp, err := v.validateOldObject(ctx)
|
||||
if err != nil {
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to validate old object", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to validate old object", err, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
if engineutils.IsSameRuleResponse(ruleResponse, priorResp) {
|
||||
|
@ -153,7 +153,7 @@ func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse {
|
|||
if ruleResponse.Status() == engineapi.RuleStatusPass {
|
||||
return ruleResponse
|
||||
}
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, "skipping modified resource as validation results have not changed")
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, "skipping modified resource as validation results have not changed", v.rule.ReportProperties)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ func (v *validator) validateForEach(ctx context.Context) *engineapi.RuleResponse
|
|||
if applyCount == 0 {
|
||||
return nil
|
||||
}
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, "rule passed")
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, "rule passed", v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForEachValidation, elements []interface{}, elementScope *bool) (*engineapi.RuleResponse, int) {
|
||||
|
@ -225,13 +225,13 @@ func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForE
|
|||
policyContext := v.policyContext.Copy()
|
||||
if err := engineutils.AddElementToContext(policyContext, element, index, v.nesting, elementScope); err != nil {
|
||||
v.log.Error(err, "failed to add element to context")
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to process foreach", err), applyCount
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to process foreach", err, v.rule.ReportProperties), applyCount
|
||||
}
|
||||
|
||||
foreachValidator, err := newForEachValidator(foreach, v.contextLoader, v.nesting+1, v.rule, policyContext, v.log)
|
||||
if err != nil {
|
||||
v.log.Error(err, "failed to create foreach validator")
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to create foreach validator", err), applyCount
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to create foreach validator", err, v.rule.ReportProperties), applyCount
|
||||
}
|
||||
|
||||
r := foreachValidator.validate(ctx)
|
||||
|
@ -249,16 +249,16 @@ func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForE
|
|||
continue
|
||||
}
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message())
|
||||
return engineapi.NewRuleResponse(v.rule.Name, engineapi.Validation, msg, status), applyCount
|
||||
return engineapi.NewRuleResponse(v.rule.Name, engineapi.Validation, msg, status, v.rule.ReportProperties), applyCount
|
||||
}
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message())
|
||||
return engineapi.NewRuleResponse(v.rule.Name, engineapi.Validation, msg, status), applyCount
|
||||
return engineapi.NewRuleResponse(v.rule.Name, engineapi.Validation, msg, status, v.rule.ReportProperties), applyCount
|
||||
}
|
||||
|
||||
applyCount++
|
||||
}
|
||||
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, ""), applyCount
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, "", v.rule.ReportProperties), applyCount
|
||||
}
|
||||
|
||||
func (v *validator) loadContext(ctx context.Context) error {
|
||||
|
@ -275,12 +275,12 @@ func (v *validator) loadContext(ctx context.Context) error {
|
|||
|
||||
func (v *validator) validateDeny() *engineapi.RuleResponse {
|
||||
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 conditions", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to check deny conditions", err, v.rule.ReportProperties)
|
||||
} else {
|
||||
if deny {
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny, msg))
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny, msg), v.rule.ReportProperties)
|
||||
}
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny, msg))
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny, msg), v.rule.ReportProperties)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,22 +329,22 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
v.log.V(3).Info("validation error", "path", pe.Path, "error", err.Error())
|
||||
|
||||
if pe.Skip {
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, pe.Error())
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, pe.Error(), v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
if pe.Path == "" {
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, ""), nil)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, ""), nil, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, pe.Path))
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, pe.Path), v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, ""), nil)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, ""), nil, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
v.log.V(4).Info("successfully processed rule")
|
||||
msg := fmt.Sprintf("validation rule '%s' passed.", v.rule.Name)
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, msg)
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, msg, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
if v.anyPattern != nil {
|
||||
|
@ -354,14 +354,14 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
|
||||
anyPatterns, err := deserializeAnyPattern(v.anyPattern)
|
||||
if err != nil {
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to deserialize anyPattern, expected type array", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to deserialize anyPattern, expected type array", err, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
for idx, pattern := range anyPatterns {
|
||||
err := validate.MatchPattern(v.log, resource.Object, pattern)
|
||||
if err == nil {
|
||||
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, msg)
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, msg, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
if pe, ok := err.(*validate.PatternError); ok {
|
||||
|
@ -389,7 +389,7 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
errorStr = append(errorStr, err.Error())
|
||||
}
|
||||
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' skipped. %s", v.rule.Name, errorStr))
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, strings.Join(errorStr, " "))
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, strings.Join(errorStr, " "), v.rule.ReportProperties)
|
||||
} else if len(failedAnyPatternsErrors) > 0 {
|
||||
var errorStr []string
|
||||
for _, err := range failedAnyPatternsErrors {
|
||||
|
@ -398,11 +398,11 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
|
||||
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' failed. %s", v.rule.Name, errorStr))
|
||||
msg := v.buildAnyPatternErrorMessage(errorStr)
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, msg)
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, msg, v.rule.ReportProperties)
|
||||
}
|
||||
}
|
||||
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, v.rule.Validation.Message)
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, v.rule.Validation.Message, v.rule.ReportProperties)
|
||||
}
|
||||
|
||||
func deserializeAnyPattern(anyPattern apiextensions.JSON) ([]interface{}, error) {
|
||||
|
|
|
@ -240,7 +240,7 @@ func (iv *ImageVerifier) Verify(
|
|||
if HasImageVerifiedAnnotationChanged(iv.policyContext, iv.logger) {
|
||||
msg := kyverno.AnnotationImageVerify + " annotation cannot be changed"
|
||||
iv.logger.Info("image verification error", "reason", msg, "image", image)
|
||||
responses = append(responses, engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg))
|
||||
responses = append(responses, engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg, iv.rule.ReportProperties))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ func (iv *ImageVerifier) Verify(
|
|||
var digest string
|
||||
if isInCache {
|
||||
iv.logger.V(2).Info("cache entry found", "namespace", iv.policyContext.Policy().GetNamespace(), "policy", iv.policyContext.Policy().GetName(), "ruleName", iv.rule.Name, "imageRef", image)
|
||||
ruleResp = engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, "verified from cache")
|
||||
ruleResp = engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, "verified from cache", iv.rule.ReportProperties)
|
||||
digest = imageInfo.Digest
|
||||
} else {
|
||||
iv.logger.V(2).Info("cache entry not found", "namespace", iv.policyContext.Policy().GetNamespace(), "policy", iv.policyContext.Policy().GetName(), "ruleName", iv.rule.Name, "imageRef", image)
|
||||
|
@ -296,10 +296,10 @@ func (iv *ImageVerifier) Verify(
|
|||
if imageVerify.MutateDigest {
|
||||
patch, retrievedDigest, err := iv.handleMutateDigest(ctx, digest, imageInfo)
|
||||
if err != nil {
|
||||
responses = append(responses, engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, "failed to update digest", err))
|
||||
responses = append(responses, engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, "failed to update digest", err, iv.rule.ReportProperties))
|
||||
} else if patch != nil {
|
||||
if ruleResp == nil {
|
||||
ruleResp = engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, "mutated image digest")
|
||||
ruleResp = engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, "mutated image digest", iv.rule.ReportProperties)
|
||||
}
|
||||
patches = append(patches, *patch)
|
||||
imageInfo.Digest = retrievedDigest
|
||||
|
@ -335,17 +335,17 @@ func (iv *ImageVerifier) verifyImage(
|
|||
iv.logger.V(2).Info("verifying image signatures", "image", image, "attestors", len(imageVerify.Attestors), "attestations", len(imageVerify.Attestations))
|
||||
if err := iv.policyContext.JSONContext().AddImageInfo(imageInfo, cfg); err != nil {
|
||||
iv.logger.Error(err, "failed to add image to context", "image", image)
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("failed to add image to context %s", image), err), ""
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("failed to add image to context %s", image), err, iv.rule.ReportProperties), ""
|
||||
}
|
||||
if len(imageVerify.Attestors) > 0 {
|
||||
if !matchReferences(imageVerify.ImageReferences, image) {
|
||||
return engineapi.RuleSkip(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("skipping image reference image %s, policy %s ruleName %s", image, iv.policyContext.Policy().GetName(), iv.rule.Name)), ""
|
||||
return engineapi.RuleSkip(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("skipping image reference image %s, policy %s ruleName %s", image, iv.policyContext.Policy().GetName(), iv.rule.Name), iv.rule.ReportProperties), ""
|
||||
}
|
||||
|
||||
if matchReferences(imageVerify.SkipImageReferences, image) {
|
||||
iv.logger.Info("skipping image reference", "image", image, "policy", iv.policyContext.Policy().GetName(), "ruleName", iv.rule.Name)
|
||||
iv.ivm.Add(image, engineapi.ImageVerificationSkip)
|
||||
return engineapi.RuleSkip(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("skipping image reference image %s, policy %s ruleName %s", image, iv.policyContext.Policy().GetName(), iv.rule.Name)).WithEmitWarning(true), ""
|
||||
return engineapi.RuleSkip(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("skipping image reference image %s, policy %s ruleName %s", image, iv.policyContext.Policy().GetName(), iv.rule.Name), iv.rule.ReportProperties).WithEmitWarning(true), ""
|
||||
}
|
||||
ruleResp, cosignResp := iv.verifyAttestors(ctx, imageVerify.Attestors, imageVerify, imageInfo)
|
||||
if ruleResp.Status() != engineapi.RuleStatusPass {
|
||||
|
@ -381,10 +381,10 @@ func (iv *ImageVerifier) verifyAttestors(
|
|||
}
|
||||
}
|
||||
if cosignResponse == nil {
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, "invalid response", fmt.Errorf("nil")), nil
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, "invalid response", fmt.Errorf("nil"), iv.rule.ReportProperties), nil
|
||||
}
|
||||
msg := fmt.Sprintf("verified image signatures for %s", image)
|
||||
return engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, msg), cosignResponse
|
||||
return engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, msg, iv.rule.ReportProperties), cosignResponse
|
||||
}
|
||||
|
||||
// handle registry network errors as a rule error (instead of a policy failure)
|
||||
|
@ -392,9 +392,9 @@ func (iv *ImageVerifier) handleRegistryErrors(image string, err error) *engineap
|
|||
msg := fmt.Sprintf("failed to verify image %s: %s", image, err.Error())
|
||||
var netErr *net.OpError
|
||||
if errors.As(err, &netErr) {
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("failed to verify image %s", image), err)
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("failed to verify image %s", image), err, iv.rule.ReportProperties)
|
||||
}
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg)
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg, iv.rule.ReportProperties)
|
||||
}
|
||||
|
||||
func (iv *ImageVerifier) verifyAttestations(
|
||||
|
@ -409,7 +409,7 @@ func (iv *ImageVerifier) verifyAttestations(
|
|||
|
||||
iv.logger.V(2).Info(fmt.Sprintf("attestation %+v", attestation))
|
||||
if attestation.Type == "" && attestation.PredicateType == "" {
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, path+": missing type"), ""
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, path+": missing type", iv.rule.ReportProperties), ""
|
||||
}
|
||||
|
||||
if attestation.Type == "" && attestation.PredicateType != "" {
|
||||
|
@ -464,7 +464,7 @@ func (iv *ImageVerifier) verifyAttestations(
|
|||
}
|
||||
if verifiedCount < requiredCount {
|
||||
msg := fmt.Sprintf("image attestations verification failed, verifiedCount: %v, requiredCount: %v, error: %s", verifiedCount, requiredCount, errMsg)
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg), ""
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg, iv.rule.ReportProperties), ""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -473,7 +473,7 @@ func (iv *ImageVerifier) verifyAttestations(
|
|||
|
||||
msg := fmt.Sprintf("verified image attestations for %s", image)
|
||||
iv.logger.V(2).Info(msg)
|
||||
return engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, msg), imageInfo.Digest
|
||||
return engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, msg, iv.rule.ReportProperties), imageInfo.Digest
|
||||
}
|
||||
|
||||
func (iv *ImageVerifier) verifyAttestorSet(
|
||||
|
|
21
pkg/engine/internal/rule.go
Normal file
21
pkg/engine/internal/rule.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
)
|
||||
|
||||
func SubstitutePropertiesInRule(log logr.Logger, rule *kyvernov1.Rule, jsonContext enginecontext.Interface) error {
|
||||
if len(rule.ReportProperties) == 0 {
|
||||
return nil
|
||||
}
|
||||
properties := rule.ReportProperties
|
||||
updatedProperties, err := variables.SubstituteAllInType(log, jsonContext, &properties)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rule.ReportProperties = *updatedProperties
|
||||
return nil
|
||||
}
|
|
@ -38,9 +38,9 @@ type jsonPatch struct {
|
|||
func applyPatches(rule *types.Rule, resource unstructured.Unstructured) (*engineapi.RuleResponse, unstructured.Unstructured) {
|
||||
mutateResp := Mutate(rule, context.NewContext(jmespath.New(config.NewDefaultConfiguration(false))), resource, logr.Discard())
|
||||
if mutateResp.Status != engineapi.RuleStatusPass {
|
||||
return engineapi.NewRuleResponse("", engineapi.Mutation, mutateResp.Message, mutateResp.Status), resource
|
||||
return engineapi.NewRuleResponse("", engineapi.Mutation, mutateResp.Message, mutateResp.Status, rule.ReportProperties), resource
|
||||
}
|
||||
return engineapi.RulePass("", engineapi.Mutation, mutateResp.Message), mutateResp.PatchedResource
|
||||
return engineapi.RulePass("", engineapi.Mutation, mutateResp.Message, rule.ReportProperties), mutateResp.PatchedResource
|
||||
}
|
||||
|
||||
func TestProcessPatches_EmptyPatches(t *testing.T) {
|
||||
|
|
|
@ -90,12 +90,13 @@ func SeverityFromString(severity string) policyreportv1alpha2.PolicySeverity {
|
|||
|
||||
func ToPolicyReportResult(policyType engineapi.PolicyType, policyName string, ruleResult engineapi.RuleResponse, annotations map[string]string, resource *corev1.ObjectReference) policyreportv1alpha2.PolicyReportResult {
|
||||
result := policyreportv1alpha2.PolicyReportResult{
|
||||
Source: kyverno.ValueKyvernoApp,
|
||||
Policy: policyName,
|
||||
Rule: ruleResult.Name(),
|
||||
Message: ruleResult.Message(),
|
||||
Result: toPolicyResult(ruleResult.Status()),
|
||||
Scored: annotations[kyverno.AnnotationPolicyScored] != "false",
|
||||
Source: kyverno.ValueKyvernoApp,
|
||||
Policy: policyName,
|
||||
Rule: ruleResult.Name(),
|
||||
Message: ruleResult.Message(),
|
||||
Properties: ruleResult.Properties(),
|
||||
Result: toPolicyResult(ruleResult.Status()),
|
||||
Scored: annotations[kyverno.AnnotationPolicyScored] != "false",
|
||||
Timestamp: metav1.Timestamp{
|
||||
Seconds: time.Now().Unix(),
|
||||
},
|
||||
|
|
|
@ -228,23 +228,23 @@ func validateResource(
|
|||
|
||||
// no validations are returned if match conditions aren't met
|
||||
if datautils.DeepEqual(validateResult, validating.ValidateResult{}) {
|
||||
ruleResp = engineapi.RuleSkip(policy.GetName(), engineapi.Validation, "match conditions aren't met")
|
||||
ruleResp = engineapi.RuleSkip(policy.GetName(), engineapi.Validation, "match conditions aren't met", nil)
|
||||
} else {
|
||||
isPass := true
|
||||
for _, policyDecision := range validateResult.Decisions {
|
||||
if policyDecision.Evaluation == validating.EvalError {
|
||||
isPass = false
|
||||
ruleResp = engineapi.RuleError(policy.GetName(), engineapi.Validation, policyDecision.Message, nil)
|
||||
ruleResp = engineapi.RuleError(policy.GetName(), engineapi.Validation, policyDecision.Message, nil, nil)
|
||||
break
|
||||
} else if policyDecision.Action == validating.ActionDeny {
|
||||
isPass = false
|
||||
ruleResp = engineapi.RuleFail(policy.GetName(), engineapi.Validation, policyDecision.Message)
|
||||
ruleResp = engineapi.RuleFail(policy.GetName(), engineapi.Validation, policyDecision.Message, nil)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if isPass {
|
||||
ruleResp = engineapi.RulePass(policy.GetName(), engineapi.Validation, "")
|
||||
ruleResp = engineapi.RulePass(policy.GetName(), engineapi.Validation, "", nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforcePolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail", nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -132,7 +132,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail", nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -146,7 +146,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -160,7 +160,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -174,7 +174,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn),
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -188,7 +188,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn),
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -202,7 +202,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforceRule, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail", nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -216,7 +216,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditRule, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail", nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -230,7 +230,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditRule, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -244,7 +244,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditRule, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -258,7 +258,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditRule, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn),
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -272,7 +272,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditRule, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn),
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -320,7 +320,7 @@ func TestGetBlockedMessages(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforcePolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail", nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -332,7 +332,7 @@ func TestGetBlockedMessages(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforcePolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
@ -344,8 +344,8 @@ func TestGetBlockedMessages(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforcePolicy, nil).WithPolicyResponse(engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail", nil),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil, nil),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
|
|
@ -31,7 +31,7 @@ func TestGetWarningMessages(t *testing.T) {
|
|||
engineapi.EngineResponse{
|
||||
PolicyResponse: engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.NewRuleResponse("rule", engineapi.Validation, "message warn", engineapi.RuleStatusWarn),
|
||||
*engineapi.NewRuleResponse("rule", engineapi.Validation, "message warn", engineapi.RuleStatusWarn, nil),
|
||||
},
|
||||
},
|
||||
}.WithPolicy(engineapi.NewKyvernoPolicy(&v1.ClusterPolicy{
|
||||
|
@ -49,11 +49,11 @@ func TestGetWarningMessages(t *testing.T) {
|
|||
engineapi.EngineResponse{
|
||||
PolicyResponse: engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
*engineapi.RulePass("rule-pass", engineapi.Validation, "message pass"),
|
||||
*engineapi.NewRuleResponse("rule-warn", engineapi.Validation, "message warn", engineapi.RuleStatusWarn),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
*engineapi.RuleSkip("rule-skip", engineapi.Validation, "message skip"),
|
||||
*engineapi.RulePass("rule-pass", engineapi.Validation, "message pass", nil),
|
||||
*engineapi.NewRuleResponse("rule-warn", engineapi.Validation, "message warn", engineapi.RuleStatusWarn, nil),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail", nil),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil, nil),
|
||||
*engineapi.RuleSkip("rule-skip", engineapi.Validation, "message skip", nil),
|
||||
},
|
||||
},
|
||||
}.WithPolicy(engineapi.NewKyvernoPolicy(&v1.ClusterPolicy{
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
"^rbac$/^(aggregate-to-admin|cleanup-policy-with-clusterrole|mutate-policy-with-clusterrole)\\[.*\\]$"
|
||||
],
|
||||
"reports": [
|
||||
"^reports$/^admission$/^(exception|namespaceselector|namespaceselector-assert|test-report-admission-mode|two-rules-with-different-modes|update)\\[.*\\]$",
|
||||
"^reports$/^admission$/^(exception|namespaceselector|namespaceselector-assert|test-report-admission-mode|test-report-properties|two-rules-with-different-modes|update)\\[.*\\]$",
|
||||
"^reports$/^background$/^(exception|exception-assert|exception-with-conditions|exception-with-podsecurity|multiple-exceptions-with-pod-security|report-deletion|test-report-background-mode|two-rules-with-different-modes|verify-image-fail|verify-image-pass)\\[.*\\]$"
|
||||
],
|
||||
"ttl": [
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# Title
|
||||
|
||||
This test checks that a Policy Report in admission mode is created with an entry that is as expected.
|
|
@ -0,0 +1,27 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: require-owner
|
||||
spec:
|
||||
background: false
|
||||
rules:
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
name: check-owner
|
||||
context:
|
||||
- name: objName
|
||||
variable:
|
||||
jmesPath: request.object.metadata.name
|
||||
reportProperties:
|
||||
operation: '{{ request.operation }}'
|
||||
objName: '{{ objName }}'
|
||||
validate:
|
||||
validationFailureAction: Audit
|
||||
message: The `owner` label is required for all Namespaces.
|
||||
pattern:
|
||||
metadata:
|
||||
labels:
|
||||
owner: ?*
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: require-owner
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
labels:
|
||||
owner: david
|
||||
name: bar
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: wgpolicyk8s.io/v1alpha2
|
||||
kind: ClusterPolicyReport
|
||||
metadata:
|
||||
ownerReferences:
|
||||
- apiVersion: v1
|
||||
kind: Namespace
|
||||
name: bar
|
||||
results:
|
||||
- message: validation rule 'check-owner' passed.
|
||||
policy: require-owner
|
||||
result: pass
|
||||
rule: check-owner
|
||||
scored: true
|
||||
source: kyverno
|
||||
properties:
|
||||
objName: bar
|
||||
operation: CREATE
|
||||
scope:
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
name: bar
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||
kind: Test
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: test-report-admission-mode
|
||||
spec:
|
||||
steps:
|
||||
- name: step-01
|
||||
try:
|
||||
- apply:
|
||||
file: chainsaw-step-01-apply-1.yaml
|
||||
- assert:
|
||||
file: chainsaw-step-01-assert-1.yaml
|
||||
- name: step-02
|
||||
try:
|
||||
- apply:
|
||||
file: chainsaw-step-02-apply-1.yaml
|
||||
- name: step-03
|
||||
try:
|
||||
- assert:
|
||||
file: chainsaw-step-03-assert-1.yaml
|
Loading…
Reference in a new issue