mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
feat: use pointer in rule (exclude field) (#11050)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
9934c0e61a
commit
b5e1c97913
20 changed files with 219 additions and 178 deletions
|
@ -46,6 +46,9 @@ func (m *MatchResources) GetKinds() []string {
|
|||
|
||||
// Validate implements programmatic validation
|
||||
func (m *MatchResources) Validate(path *field.Path, namespaced bool, clusterResources sets.Set[string]) (errs field.ErrorList) {
|
||||
if m == nil {
|
||||
return errs
|
||||
}
|
||||
if len(m.Any) > 0 && len(m.All) > 0 {
|
||||
errs = append(errs, field.Invalid(path, m, "Can't specify any and all together"))
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ type Rule struct {
|
|||
// criteria can include resource information (e.g. kind, name, namespace, labels)
|
||||
// and admission review request information like the name or role.
|
||||
// +optional
|
||||
ExcludeResources MatchResources `json:"exclude,omitempty"`
|
||||
ExcludeResources *MatchResources `json:"exclude,omitempty"`
|
||||
|
||||
// ImageExtractors defines a mapping from kinds to ImageExtractorConfigs.
|
||||
// This config is only valid for verifyImages rules.
|
||||
|
@ -252,6 +252,9 @@ func (r *Rule) ValidateRuleType(path *field.Path) (errs field.ErrorList) {
|
|||
|
||||
// ValidateMatchExcludeConflict checks if the resultant of match and exclude block is not an empty set
|
||||
func (r *Rule) ValidateMatchExcludeConflict(path *field.Path) (errs field.ErrorList) {
|
||||
if r.ExcludeResources == nil {
|
||||
return errs
|
||||
}
|
||||
if len(r.ExcludeResources.All) > 0 || len(r.MatchResources.All) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
@ -266,7 +269,7 @@ func (r *Rule) ValidateMatchExcludeConflict(path *field.Path) (errs field.ErrorL
|
|||
}
|
||||
return errs
|
||||
}
|
||||
if datautils.DeepEqual(r.ExcludeResources, MatchResources{}) {
|
||||
if datautils.DeepEqual(*r.ExcludeResources, MatchResources{}) {
|
||||
return errs
|
||||
}
|
||||
excludeRoles := sets.New(r.ExcludeResources.Roles...)
|
||||
|
|
|
@ -1396,7 +1396,11 @@ func (in *Rule) DeepCopyInto(out *Rule) {
|
|||
}
|
||||
}
|
||||
in.MatchResources.DeepCopyInto(&out.MatchResources)
|
||||
in.ExcludeResources.DeepCopyInto(&out.ExcludeResources)
|
||||
if in.ExcludeResources != nil {
|
||||
in, out := &in.ExcludeResources, &out.ExcludeResources
|
||||
*out = new(MatchResources)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ImageExtractors != nil {
|
||||
in, out := &in.ImageExtractors, &out.ImageExtractors
|
||||
*out = make(ImageExtractorConfigs, len(*in))
|
||||
|
|
|
@ -41,6 +41,9 @@ func (m *MatchResources) GetKinds() []string {
|
|||
|
||||
// ValidateNoUserInfo verifies that no user info is used
|
||||
func (m *MatchResources) ValidateNoUserInfo(path *field.Path) (errs field.ErrorList) {
|
||||
if m == nil {
|
||||
return errs
|
||||
}
|
||||
anyPath := path.Child("any")
|
||||
for i, filter := range m.Any {
|
||||
errs = append(errs, filter.UserInfo.ValidateNoUserInfo(anyPath.Index(i))...)
|
||||
|
@ -54,6 +57,9 @@ func (m *MatchResources) ValidateNoUserInfo(path *field.Path) (errs field.ErrorL
|
|||
|
||||
// ValidateResourceWithNoUserInfo implements programmatic validation and verifies that no user info is used
|
||||
func (m *MatchResources) ValidateResourceWithNoUserInfo(path *field.Path, namespaced bool, clusterResources sets.Set[string]) (errs field.ErrorList) {
|
||||
if m == nil {
|
||||
return errs
|
||||
}
|
||||
if len(m.Any) > 0 && len(m.All) > 0 {
|
||||
errs = append(errs, field.Invalid(path, m, "Can't specify any and all together"))
|
||||
}
|
||||
|
@ -72,6 +78,9 @@ func (m *MatchResources) ValidateResourceWithNoUserInfo(path *field.Path, namesp
|
|||
|
||||
// Validate implements programmatic validation
|
||||
func (m *MatchResources) Validate(path *field.Path, namespaced bool, clusterResources sets.Set[string]) (errs field.ErrorList) {
|
||||
if m == nil {
|
||||
return errs
|
||||
}
|
||||
if len(m.Any) > 0 && len(m.All) > 0 {
|
||||
errs = append(errs, field.Invalid(path, m, "Can't specify any and all together"))
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ type Rule struct {
|
|||
// criteria can include resource information (e.g. kind, name, namespace, labels)
|
||||
// and admission review request information like the name or role.
|
||||
// +optional
|
||||
ExcludeResources MatchResources `json:"exclude,omitempty"`
|
||||
ExcludeResources *MatchResources `json:"exclude,omitempty"`
|
||||
|
||||
// ImageExtractors defines a mapping from kinds to ImageExtractorConfigs.
|
||||
// This config is only valid for verifyImages rules.
|
||||
|
@ -160,6 +160,9 @@ func (r *Rule) ValidateRuleType(path *field.Path) (errs field.ErrorList) {
|
|||
|
||||
// ValidateMatchExcludeConflict checks if the resultant of match and exclude block is not an empty set
|
||||
func (r *Rule) ValidateMatchExcludeConflict(path *field.Path) (errs field.ErrorList) {
|
||||
if r.ExcludeResources == nil {
|
||||
return errs
|
||||
}
|
||||
if len(r.ExcludeResources.All) > 0 || len(r.MatchResources.All) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
|
|
@ -712,7 +712,11 @@ func (in *Rule) DeepCopyInto(out *Rule) {
|
|||
}
|
||||
}
|
||||
in.MatchResources.DeepCopyInto(&out.MatchResources)
|
||||
in.ExcludeResources.DeepCopyInto(&out.ExcludeResources)
|
||||
if in.ExcludeResources != nil {
|
||||
in, out := &in.ExcludeResources, &out.ExcludeResources
|
||||
*out = new(MatchResources)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ImageExtractors != nil {
|
||||
in, out := &in.ImageExtractors, &out.ImageExtractors
|
||||
*out = make(v1.ImageExtractorConfigs, len(*in))
|
||||
|
|
|
@ -98,13 +98,15 @@ func GetKindsFromPolicy(out io.Writer, policy kyvernov1.PolicyInterface, subreso
|
|||
}
|
||||
knownkinds.Insert(k)
|
||||
}
|
||||
for _, kind := range rule.ExcludeResources.ResourceDescription.Kinds {
|
||||
k, err := getKind(kind, subresources, dClient)
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, "Error: %s", err.Error())
|
||||
continue
|
||||
if rule.ExcludeResources != nil {
|
||||
for _, kind := range rule.ExcludeResources.ResourceDescription.Kinds {
|
||||
k, err := getKind(kind, subresources, dClient)
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, "Error: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
knownkinds.Insert(k)
|
||||
}
|
||||
knownkinds.Insert(k)
|
||||
}
|
||||
}
|
||||
return knownkinds
|
||||
|
|
|
@ -77,8 +77,8 @@ func CanAutoGen(spec *kyvernov1.Spec) (applyAutoGen bool, controllers sets.Set[s
|
|||
return false, sets.New("none")
|
||||
}
|
||||
}
|
||||
match, exclude := rule.MatchResources, rule.ExcludeResources
|
||||
if !checkAutogenSupport(&needed, match.ResourceDescription, exclude.ResourceDescription) {
|
||||
match := rule.MatchResources
|
||||
if !checkAutogenSupport(&needed, match.ResourceDescription) {
|
||||
debug.Info("skip generating rule on pod controllers: Name / Selector in resource description may not be applicable.", "rule", rule.Name)
|
||||
return false, sets.New[string]()
|
||||
}
|
||||
|
@ -94,16 +94,22 @@ func CanAutoGen(spec *kyvernov1.Spec) (applyAutoGen bool, controllers sets.Set[s
|
|||
return false, sets.New[string]()
|
||||
}
|
||||
}
|
||||
for _, value := range exclude.Any {
|
||||
if !checkAutogenSupport(&needed, value.ResourceDescription) {
|
||||
debug.Info("skip generating rule on pod controllers: Name / Selector in exclude any block is not applicable.", "rule", rule.Name)
|
||||
if exclude := rule.ExcludeResources; exclude != nil {
|
||||
if !checkAutogenSupport(&needed, exclude.ResourceDescription) {
|
||||
debug.Info("skip generating rule on pod controllers: Name / Selector in resource description may not be applicable.", "rule", rule.Name)
|
||||
return false, sets.New[string]()
|
||||
}
|
||||
}
|
||||
for _, value := range exclude.All {
|
||||
if !checkAutogenSupport(&needed, value.ResourceDescription) {
|
||||
debug.Info("skip generating rule on pod controllers: Name / Selector in exclud all block is not applicable.", "rule", rule.Name)
|
||||
return false, sets.New[string]()
|
||||
for _, value := range exclude.Any {
|
||||
if !checkAutogenSupport(&needed, value.ResourceDescription) {
|
||||
debug.Info("skip generating rule on pod controllers: Name / Selector in exclude any block is not applicable.", "rule", rule.Name)
|
||||
return false, sets.New[string]()
|
||||
}
|
||||
}
|
||||
for _, value := range exclude.All {
|
||||
if !checkAutogenSupport(&needed, value.ResourceDescription) {
|
||||
debug.Info("skip generating rule on pod controllers: Name / Selector in exclud all block is not applicable.", "rule", rule.Name)
|
||||
return false, sets.New[string]()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +216,7 @@ func convertRule(rule kyvernoRule, kind string) (*kyvernov1.Rule, error) {
|
|||
out.MatchResources = *rule.MatchResources
|
||||
}
|
||||
if rule.ExcludeResources != nil {
|
||||
out.ExcludeResources = *rule.ExcludeResources
|
||||
out.ExcludeResources = rule.ExcludeResources
|
||||
}
|
||||
if rule.Context != nil {
|
||||
out.Context = *rule.Context
|
||||
|
|
|
@ -42,7 +42,7 @@ func createRule(rule *kyvernov1.Rule) *kyvernoRule {
|
|||
if !datautils.DeepEqual(rule.MatchResources, kyvernov1.MatchResources{}) {
|
||||
jsonFriendlyStruct.MatchResources = rule.MatchResources.DeepCopy()
|
||||
}
|
||||
if !datautils.DeepEqual(rule.ExcludeResources, kyvernov1.MatchResources{}) {
|
||||
if rule.ExcludeResources != nil && !datautils.DeepEqual(*rule.ExcludeResources, kyvernov1.MatchResources{}) {
|
||||
jsonFriendlyStruct.ExcludeResources = rule.ExcludeResources.DeepCopy()
|
||||
}
|
||||
if !datautils.DeepEqual(rule.Mutation, kyvernov1.Mutation{}) {
|
||||
|
@ -84,13 +84,15 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
|
|||
} else {
|
||||
rule.MatchResources.Kinds = kinds
|
||||
}
|
||||
if len(rule.ExcludeResources.Any) > 0 {
|
||||
rule.ExcludeResources.Any = grf(rule.ExcludeResources.Any, kinds)
|
||||
} else if len(rule.ExcludeResources.All) > 0 {
|
||||
rule.ExcludeResources.All = grf(rule.ExcludeResources.All, kinds)
|
||||
} else {
|
||||
if len(rule.ExcludeResources.Kinds) != 0 {
|
||||
rule.ExcludeResources.Kinds = kinds
|
||||
if rule.ExcludeResources != nil {
|
||||
if len(rule.ExcludeResources.Any) > 0 {
|
||||
rule.ExcludeResources.Any = grf(rule.ExcludeResources.Any, kinds)
|
||||
} else if len(rule.ExcludeResources.All) > 0 {
|
||||
rule.ExcludeResources.All = grf(rule.ExcludeResources.All, kinds)
|
||||
} else {
|
||||
if len(rule.ExcludeResources.Kinds) != 0 {
|
||||
rule.ExcludeResources.Kinds = kinds
|
||||
}
|
||||
}
|
||||
}
|
||||
if target := rule.Mutation.GetPatchStrategicMerge(); target != nil {
|
||||
|
@ -255,8 +257,12 @@ func generateRuleForControllers(rule *kyvernov1.Rule, controllers string) *kyver
|
|||
return nil
|
||||
}
|
||||
debug.Info("processing rule", "rulename", rule.Name)
|
||||
match, exclude := rule.MatchResources, rule.ExcludeResources
|
||||
matchKinds, excludeKinds := match.GetKinds(), exclude.GetKinds()
|
||||
match := rule.MatchResources
|
||||
matchKinds := match.GetKinds()
|
||||
var excludeKinds []string
|
||||
if exclude := rule.ExcludeResources; exclude != nil {
|
||||
excludeKinds = exclude.GetKinds()
|
||||
}
|
||||
if !kubeutils.ContainsKind(matchKinds, "Pod") || (len(excludeKinds) != 0 && !kubeutils.ContainsKind(excludeKinds, "Pod")) {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ func TestAddOperationsForValidatingWebhookConf(t *testing.T) {
|
|||
Kinds: []string{"ConfigMap"},
|
||||
},
|
||||
},
|
||||
ExcludeResources: kyverno.MatchResources{
|
||||
ExcludeResources: &kyverno.MatchResources{
|
||||
ResourceDescription: kyverno.ResourceDescription{
|
||||
Operations: []kyverno.AdmissionOperation{"DELETE", "CONNECT", "CREATE"},
|
||||
},
|
||||
|
@ -263,7 +263,7 @@ func TestAddOperationsForMutatingtingWebhookConf(t *testing.T) {
|
|||
Kinds: []string{"Secret"},
|
||||
},
|
||||
},
|
||||
ExcludeResources: kyverno.MatchResources{
|
||||
ExcludeResources: &kyverno.MatchResources{
|
||||
ResourceDescription: kyverno.ResourceDescription{
|
||||
Operations: []kyverno.AdmissionOperation{"UPDATE"},
|
||||
},
|
||||
|
|
|
@ -263,16 +263,18 @@ func computeOperationsForValidatingWebhookConf(r kyvernov1.Rule, operationStatus
|
|||
operationStatusMap[webhookConnect] = true
|
||||
operationStatusMap[webhookDelete] = true
|
||||
}
|
||||
if r.ExcludeResources.ResourceDescription.Operations != nil {
|
||||
for _, o := range r.ExcludeResources.ResourceDescription.Operations {
|
||||
operationStatusMap[string(o)] = false
|
||||
if r.ExcludeResources != nil {
|
||||
if r.ExcludeResources.ResourceDescription.Operations != nil {
|
||||
for _, o := range r.ExcludeResources.ResourceDescription.Operations {
|
||||
operationStatusMap[string(o)] = false
|
||||
}
|
||||
}
|
||||
if len(r.ExcludeResources.Any) != 0 {
|
||||
_, operationStatusMap = scanResourceFilterForExclude(r.ExcludeResources.Any, operationStatusMap)
|
||||
}
|
||||
if len(r.ExcludeResources.All) != 0 {
|
||||
_, operationStatusMap = scanResourceFilterForExclude(r.ExcludeResources.All, operationStatusMap)
|
||||
}
|
||||
}
|
||||
if len(r.ExcludeResources.Any) != 0 {
|
||||
_, operationStatusMap = scanResourceFilterForExclude(r.ExcludeResources.Any, operationStatusMap)
|
||||
}
|
||||
if len(r.ExcludeResources.All) != 0 {
|
||||
_, operationStatusMap = scanResourceFilterForExclude(r.ExcludeResources.All, operationStatusMap)
|
||||
}
|
||||
return operationStatusMap
|
||||
}
|
||||
|
@ -307,16 +309,18 @@ func computeOperationsForMutatingWebhookConf(r kyvernov1.Rule, operationStatusMa
|
|||
operationStatusMap[webhookCreate] = true
|
||||
operationStatusMap[webhookUpdate] = true
|
||||
}
|
||||
if r.ExcludeResources.ResourceDescription.Operations != nil {
|
||||
for _, o := range r.ExcludeResources.ResourceDescription.Operations {
|
||||
operationStatusMap[string(o)] = false
|
||||
if r.ExcludeResources != nil {
|
||||
if r.ExcludeResources.ResourceDescription.Operations != nil {
|
||||
for _, o := range r.ExcludeResources.ResourceDescription.Operations {
|
||||
operationStatusMap[string(o)] = false
|
||||
}
|
||||
}
|
||||
if len(r.ExcludeResources.Any) != 0 {
|
||||
_, operationStatusMap = scanResourceFilterForExclude(r.ExcludeResources.Any, operationStatusMap)
|
||||
}
|
||||
if len(r.ExcludeResources.All) != 0 {
|
||||
_, operationStatusMap = scanResourceFilterForExclude(r.ExcludeResources.All, operationStatusMap)
|
||||
}
|
||||
}
|
||||
if len(r.ExcludeResources.Any) != 0 {
|
||||
_, operationStatusMap = scanResourceFilterForExclude(r.ExcludeResources.Any, operationStatusMap)
|
||||
}
|
||||
if len(r.ExcludeResources.All) != 0 {
|
||||
_, operationStatusMap = scanResourceFilterForExclude(r.ExcludeResources.All, operationStatusMap)
|
||||
}
|
||||
}
|
||||
return operationStatusMap
|
||||
|
@ -375,17 +379,19 @@ func computeResourcesOfRule(r kyvernov1.Rule) []string {
|
|||
if len(r.MatchResources.All) != 0 {
|
||||
resources = scanResourceFilterForResources(r.MatchResources.Any)
|
||||
}
|
||||
if len(r.ExcludeResources.Any) != 0 {
|
||||
resources = scanResourceFilterForResources(r.MatchResources.Any)
|
||||
}
|
||||
if len(r.ExcludeResources.All) != 0 {
|
||||
resources = scanResourceFilterForResources(r.MatchResources.Any)
|
||||
}
|
||||
if r.MatchResources.ResourceDescription.Kinds != nil {
|
||||
resources = append(resources, r.MatchResources.ResourceDescription.Kinds...)
|
||||
}
|
||||
if r.ExcludeResources.ResourceDescription.Kinds != nil {
|
||||
resources = append(resources, r.ExcludeResources.ResourceDescription.Kinds...)
|
||||
if r.ExcludeResources != nil {
|
||||
if len(r.ExcludeResources.Any) != 0 {
|
||||
resources = scanResourceFilterForResources(r.MatchResources.Any)
|
||||
}
|
||||
if len(r.ExcludeResources.All) != 0 {
|
||||
resources = scanResourceFilterForResources(r.MatchResources.Any)
|
||||
}
|
||||
if r.ExcludeResources.ResourceDescription.Kinds != nil {
|
||||
resources = append(resources, r.ExcludeResources.ResourceDescription.Kinds...)
|
||||
}
|
||||
}
|
||||
return resources
|
||||
}
|
||||
|
|
|
@ -241,14 +241,14 @@ func TestComputeOperationsForMutatingWebhookConf(t *testing.T) {
|
|||
PatchesJSON6902: "add",
|
||||
},
|
||||
MatchResources: kyvernov1.MatchResources{},
|
||||
ExcludeResources: kyvernov1.MatchResources{},
|
||||
ExcludeResources: &kyvernov1.MatchResources{},
|
||||
},
|
||||
{
|
||||
Mutation: kyvernov1.Mutation{
|
||||
PatchesJSON6902: "add",
|
||||
},
|
||||
MatchResources: kyvernov1.MatchResources{},
|
||||
ExcludeResources: kyvernov1.MatchResources{},
|
||||
ExcludeResources: &kyvernov1.MatchResources{},
|
||||
},
|
||||
},
|
||||
expectedResult: map[string]bool{
|
||||
|
@ -264,7 +264,7 @@ func TestComputeOperationsForMutatingWebhookConf(t *testing.T) {
|
|||
PatchesJSON6902: "add",
|
||||
},
|
||||
MatchResources: kyvernov1.MatchResources{},
|
||||
ExcludeResources: kyvernov1.MatchResources{
|
||||
ExcludeResources: &kyvernov1.MatchResources{
|
||||
ResourceDescription: kyvernov1.ResourceDescription{
|
||||
Operations: []kyvernov1.AdmissionOperation{webhookCreate},
|
||||
},
|
||||
|
@ -317,7 +317,7 @@ func TestComputeOperationsForValidatingWebhookConf(t *testing.T) {
|
|||
rules: []kyvernov1.Rule{
|
||||
{
|
||||
MatchResources: kyvernov1.MatchResources{},
|
||||
ExcludeResources: kyvernov1.MatchResources{},
|
||||
ExcludeResources: &kyvernov1.MatchResources{},
|
||||
},
|
||||
},
|
||||
expectedResult: map[string]bool{
|
||||
|
@ -336,7 +336,7 @@ func TestComputeOperationsForValidatingWebhookConf(t *testing.T) {
|
|||
Operations: []kyvernov1.AdmissionOperation{webhookCreate, webhookUpdate},
|
||||
},
|
||||
},
|
||||
ExcludeResources: kyvernov1.MatchResources{
|
||||
ExcludeResources: &kyvernov1.MatchResources{
|
||||
ResourceDescription: kyvernov1.ResourceDescription{
|
||||
Operations: []kyvernov1.AdmissionOperation{webhookDelete},
|
||||
},
|
||||
|
|
|
@ -25,21 +25,22 @@ func matchResource(resource unstructured.Unstructured, rule kyvernov1.Rule) bool
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if rule.ExcludeResources.All != nil || rule.ExcludeResources.Any != nil {
|
||||
excluded := match.CheckMatchesResources(
|
||||
resource,
|
||||
kyvernov2beta1.MatchResources{
|
||||
Any: rule.ExcludeResources.Any,
|
||||
All: rule.ExcludeResources.All,
|
||||
},
|
||||
make(map[string]string),
|
||||
kyvernov2.RequestInfo{},
|
||||
resource.GroupVersionKind(),
|
||||
"",
|
||||
)
|
||||
if excluded == nil {
|
||||
return false
|
||||
if rule.ExcludeResources != nil {
|
||||
if rule.ExcludeResources.All != nil || rule.ExcludeResources.Any != nil {
|
||||
excluded := match.CheckMatchesResources(
|
||||
resource,
|
||||
kyvernov2beta1.MatchResources{
|
||||
Any: rule.ExcludeResources.Any,
|
||||
All: rule.ExcludeResources.All,
|
||||
},
|
||||
make(map[string]string),
|
||||
kyvernov2.RequestInfo{},
|
||||
resource.GroupVersionKind(),
|
||||
"",
|
||||
)
|
||||
if excluded == nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -209,7 +209,7 @@ func MatchesResourceDescription(
|
|||
}
|
||||
|
||||
// check exlude conditions only if match succeeds
|
||||
if len(reasonsForFailure) == 0 {
|
||||
if len(reasonsForFailure) == 0 && rule.ExcludeResources != nil {
|
||||
if len(rule.ExcludeResources.Any) > 0 {
|
||||
// exclude the object if ANY of the criteria match
|
||||
for _, rer := range rule.ExcludeResources.Any {
|
||||
|
|
|
@ -1963,7 +1963,7 @@ func TestResourceDescriptionMatch_ExcludeDefaultGroups(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}},
|
||||
ExcludeResources: v1.MatchResources{},
|
||||
ExcludeResources: &v1.MatchResources{},
|
||||
}
|
||||
|
||||
// this is the request info that was also passed with the mocked pod
|
||||
|
@ -1996,7 +1996,7 @@ func TestResourceDescriptionMatch_ExcludeDefaultGroups(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}},
|
||||
ExcludeResources: v1.MatchResources{Any: v1.ResourceFilters{}},
|
||||
ExcludeResources: &v1.MatchResources{Any: v1.ResourceFilters{}},
|
||||
}
|
||||
|
||||
// Second test: confirm that matching this rule does not create any errors (and raise if err != nil)
|
||||
|
@ -2005,7 +2005,7 @@ func TestResourceDescriptionMatch_ExcludeDefaultGroups(t *testing.T) {
|
|||
}
|
||||
|
||||
// Now we extend the previous rule to have an Exclude part. Making it 'not-empty' should make the exclude-code run.
|
||||
rule2.ExcludeResources = v1.MatchResources{Any: v1.ResourceFilters{
|
||||
rule2.ExcludeResources = &v1.MatchResources{Any: v1.ResourceFilters{
|
||||
v1.ResourceFilter{
|
||||
ResourceDescription: v1.ResourceDescription{
|
||||
Kinds: []string{"Pod"},
|
||||
|
@ -2461,7 +2461,7 @@ func TestResourceDescriptionExclude_Label_Expression_Match(t *testing.T) {
|
|||
|
||||
rule := v1.Rule{
|
||||
MatchResources: v1.MatchResources{ResourceDescription: resourceDescription},
|
||||
ExcludeResources: v1.MatchResources{ResourceDescription: resourceDescriptionExclude},
|
||||
ExcludeResources: &v1.MatchResources{ResourceDescription: resourceDescriptionExclude},
|
||||
}
|
||||
|
||||
if err := MatchesResourceDescription(*resource, rule, v2.RequestInfo{}, nil, "", resource.GroupVersionKind(), "", "CREATE"); err == nil {
|
||||
|
|
|
@ -179,7 +179,7 @@ func createRule(f *fuzz.ConsumeFuzzer) (*kyvernov1.Rule, error) {
|
|||
if err != nil {
|
||||
return rule, err
|
||||
}
|
||||
rule.ExcludeResources = *er
|
||||
rule.ExcludeResources = er
|
||||
}
|
||||
|
||||
setRawAnyAllConditions, err := f.GetBool()
|
||||
|
|
|
@ -57,21 +57,22 @@ func BuildValidatingAdmissionPolicy(
|
|||
}
|
||||
|
||||
// convert the exclude block
|
||||
exclude := rule.ExcludeResources
|
||||
if !exclude.ResourceDescription.IsEmpty() {
|
||||
if err := translateResource(discoveryClient, &matchResources, &excludeRules, exclude.ResourceDescription, false); err != nil {
|
||||
return err
|
||||
if exclude := rule.ExcludeResources; exclude != nil {
|
||||
if !exclude.ResourceDescription.IsEmpty() {
|
||||
if err := translateResource(discoveryClient, &matchResources, &excludeRules, exclude.ResourceDescription, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if exclude.Any != nil {
|
||||
if err := translateResourceFilters(discoveryClient, &matchResources, &excludeRules, exclude.Any, false); err != nil {
|
||||
return err
|
||||
if exclude.Any != nil {
|
||||
if err := translateResourceFilters(discoveryClient, &matchResources, &excludeRules, exclude.Any, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if exclude.All != nil {
|
||||
if err := translateResourceFilters(discoveryClient, &matchResources, &excludeRules, exclude.All, false); err != nil {
|
||||
return err
|
||||
if exclude.All != nil {
|
||||
if err := translateResourceFilters(discoveryClient, &matchResources, &excludeRules, exclude.All, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,25 +72,16 @@ func checkPolicy(spec *kyvernov1.Spec) (bool, string) {
|
|||
}
|
||||
|
||||
// check the matched/excluded resources of the CEL rule.
|
||||
match, exclude := rule.MatchResources, rule.ExcludeResources
|
||||
match := rule.MatchResources
|
||||
if ok, msg := checkUserInfo(match.UserInfo); !ok {
|
||||
return false, msg
|
||||
}
|
||||
if ok, msg := checkUserInfo(exclude.UserInfo); !ok {
|
||||
return false, msg
|
||||
}
|
||||
|
||||
if ok, msg := checkResources(match.ResourceDescription, true); !ok {
|
||||
return false, msg
|
||||
}
|
||||
if ok, msg := checkResources(exclude.ResourceDescription, false); !ok {
|
||||
return false, msg
|
||||
}
|
||||
|
||||
if ok, msg := checkResourceFilter(match.Any, true); !ok {
|
||||
return false, msg
|
||||
}
|
||||
|
||||
if len(match.All) > 1 {
|
||||
msg = "skip generating ValidatingAdmissionPolicy: multiple 'all' in the match block is not applicable."
|
||||
return false, msg
|
||||
|
@ -98,17 +89,24 @@ func checkPolicy(spec *kyvernov1.Spec) (bool, string) {
|
|||
if ok, msg := checkResourceFilter(match.All, true); !ok {
|
||||
return false, msg
|
||||
}
|
||||
|
||||
if ok, msg := checkResourceFilter(exclude.Any, false); !ok {
|
||||
return false, msg
|
||||
}
|
||||
|
||||
if len(exclude.All) > 1 {
|
||||
msg = "skip generating ValidatingAdmissionPolicy: multiple 'all' in the exclude block is not applicable."
|
||||
return false, msg
|
||||
}
|
||||
if ok, msg := checkResourceFilter(exclude.All, false); !ok {
|
||||
return false, msg
|
||||
if rule.ExcludeResources != nil {
|
||||
exclude := rule.ExcludeResources
|
||||
if ok, msg := checkUserInfo(exclude.UserInfo); !ok {
|
||||
return false, msg
|
||||
}
|
||||
if ok, msg := checkResources(exclude.ResourceDescription, false); !ok {
|
||||
return false, msg
|
||||
}
|
||||
if ok, msg := checkResourceFilter(exclude.Any, false); !ok {
|
||||
return false, msg
|
||||
}
|
||||
if len(exclude.All) > 1 {
|
||||
msg = "skip generating ValidatingAdmissionPolicy: multiple 'all' in the exclude block is not applicable."
|
||||
return false, msg
|
||||
}
|
||||
if ok, msg := checkResourceFilter(exclude.All, false); !ok {
|
||||
return false, msg
|
||||
}
|
||||
}
|
||||
|
||||
return true, msg
|
||||
|
|
|
@ -43,11 +43,6 @@ func hasUserMatchExclude(idx int, rule *kyvernov1.Rule) error {
|
|||
if path := userInfoDefined(rule.MatchResources.UserInfo); path != "" {
|
||||
return fmt.Errorf("invalid variable used at path: spec/rules[%d]/match/%s", idx, path)
|
||||
}
|
||||
|
||||
if path := userInfoDefined(rule.ExcludeResources.UserInfo); path != "" {
|
||||
return fmt.Errorf("invalid variable used at path: spec/rules[%d]/exclude/%s", idx, path)
|
||||
}
|
||||
|
||||
if len(rule.MatchResources.Any) > 0 {
|
||||
for i, value := range rule.MatchResources.Any {
|
||||
if path := userInfoDefined(value.UserInfo); path != "" {
|
||||
|
@ -55,7 +50,6 @@ func hasUserMatchExclude(idx int, rule *kyvernov1.Rule) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(rule.MatchResources.All) > 0 {
|
||||
for i, value := range rule.MatchResources.All {
|
||||
if path := userInfoDefined(value.UserInfo); path != "" {
|
||||
|
@ -63,23 +57,25 @@ func hasUserMatchExclude(idx int, rule *kyvernov1.Rule) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(rule.ExcludeResources.All) > 0 {
|
||||
for i, value := range rule.ExcludeResources.All {
|
||||
if path := userInfoDefined(value.UserInfo); path != "" {
|
||||
return fmt.Errorf("invalid variable used at path: spec/rules[%d]/exclude/all[%d]/%s", idx, i, path)
|
||||
if rule.ExcludeResources != nil {
|
||||
if path := userInfoDefined(rule.ExcludeResources.UserInfo); path != "" {
|
||||
return fmt.Errorf("invalid variable used at path: spec/rules[%d]/exclude/%s", idx, path)
|
||||
}
|
||||
if len(rule.ExcludeResources.All) > 0 {
|
||||
for i, value := range rule.ExcludeResources.All {
|
||||
if path := userInfoDefined(value.UserInfo); path != "" {
|
||||
return fmt.Errorf("invalid variable used at path: spec/rules[%d]/exclude/all[%d]/%s", idx, i, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(rule.ExcludeResources.Any) > 0 {
|
||||
for i, value := range rule.ExcludeResources.Any {
|
||||
if path := userInfoDefined(value.UserInfo); path != "" {
|
||||
return fmt.Errorf("invalid variable used at path: spec/rules[%d]/exclude/any[%d]/%s", idx, i, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(rule.ExcludeResources.Any) > 0 {
|
||||
for i, value := range rule.ExcludeResources.Any {
|
||||
if path := userInfoDefined(value.UserInfo); path != "" {
|
||||
return fmt.Errorf("invalid variable used at path: spec/rules[%d]/exclude/any[%d]/%s", idx, i, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -236,7 +236,6 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
|
|||
|
||||
for i, rule := range rules {
|
||||
match := rule.MatchResources
|
||||
exclude := rule.ExcludeResources
|
||||
for j, value := range match.Any {
|
||||
if err := validateKinds(value.ResourceDescription.Kinds, rule, mock, background, client); err != nil {
|
||||
return warnings, fmt.Errorf("path: spec.rules[%d].match.any[%d].kinds: %v", i, j, err)
|
||||
|
@ -247,23 +246,23 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
|
|||
return warnings, fmt.Errorf("path: spec.rules[%d].match.all[%d].kinds: %v", i, j, err)
|
||||
}
|
||||
}
|
||||
for j, value := range exclude.Any {
|
||||
if err := validateKinds(value.ResourceDescription.Kinds, rule, mock, background, client); err != nil {
|
||||
return warnings, fmt.Errorf("path: spec.rules[%d].exclude.any[%d].kinds: %v", i, j, err)
|
||||
}
|
||||
}
|
||||
for j, value := range exclude.All {
|
||||
if err := validateKinds(value.ResourceDescription.Kinds, rule, mock, background, client); err != nil {
|
||||
return warnings, fmt.Errorf("path: spec.rules[%d].exclude.all[%d].kinds: %v", i, j, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateKinds(rule.MatchResources.Kinds, rule, mock, background, client); err != nil {
|
||||
return warnings, fmt.Errorf("path: spec.rules[%d].match.kinds: %v", i, err)
|
||||
}
|
||||
|
||||
if err := validateKinds(rule.ExcludeResources.Kinds, rule, mock, background, client); err != nil {
|
||||
return warnings, fmt.Errorf("path: spec.rules[%d].exclude.kinds: %v", i, err)
|
||||
if exclude := rule.ExcludeResources; exclude != nil {
|
||||
for j, value := range exclude.Any {
|
||||
if err := validateKinds(value.ResourceDescription.Kinds, rule, mock, background, client); err != nil {
|
||||
return warnings, fmt.Errorf("path: spec.rules[%d].exclude.any[%d].kinds: %v", i, j, err)
|
||||
}
|
||||
}
|
||||
for j, value := range exclude.All {
|
||||
if err := validateKinds(value.ResourceDescription.Kinds, rule, mock, background, client); err != nil {
|
||||
return warnings, fmt.Errorf("path: spec.rules[%d].exclude.all[%d].kinds: %v", i, j, err)
|
||||
}
|
||||
}
|
||||
if err := validateKinds(exclude.Kinds, rule, mock, background, client); err != nil {
|
||||
return warnings, fmt.Errorf("path: spec.rules[%d].exclude.kinds: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,12 +376,13 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
|
|||
}
|
||||
|
||||
match := rule.MatchResources
|
||||
exclude := rule.ExcludeResources
|
||||
matchKinds := match.GetKinds()
|
||||
excludeKinds := exclude.GetKinds()
|
||||
allKinds := make([]string, 0, len(matchKinds)+len(excludeKinds))
|
||||
var allKinds []string
|
||||
allKinds = append(allKinds, matchKinds...)
|
||||
allKinds = append(allKinds, excludeKinds...)
|
||||
if exclude := rule.ExcludeResources; exclude != nil {
|
||||
excludeKinds := exclude.GetKinds()
|
||||
allKinds = append(allKinds, excludeKinds...)
|
||||
}
|
||||
if rule.HasValidate() {
|
||||
validationElem := rule.Validation.DeepCopy()
|
||||
if validationElem.Deny != nil {
|
||||
|
@ -691,17 +691,16 @@ func jsonPatchPathHasVariables(patch string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func objectHasVariables(object interface{}) error {
|
||||
var err error
|
||||
objectJSON, err := json.Marshal(object)
|
||||
if err != nil {
|
||||
return err
|
||||
func objectHasVariables(object any) error {
|
||||
if object != nil {
|
||||
objectJSON, err := json.Marshal(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(regexVariables.FindAllStringSubmatch(string(objectJSON), -1)) > 0 {
|
||||
return fmt.Errorf("invalid variables")
|
||||
}
|
||||
}
|
||||
|
||||
if len(regexVariables.FindAllStringSubmatch(string(objectJSON), -1)) > 0 {
|
||||
return fmt.Errorf("invalid variables")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -963,22 +962,22 @@ func ruleOnlyDealsWithResourceMetaData(rule kyvernov1.Rule) bool {
|
|||
|
||||
func validateResources(path *field.Path, rule kyvernov1.Rule) (string, error) {
|
||||
// validate userInfo in match and exclude
|
||||
if errs := rule.ExcludeResources.UserInfo.Validate(path.Child("exclude")); len(errs) != 0 {
|
||||
return "exclude", errs.ToAggregate()
|
||||
if exclude := rule.ExcludeResources; exclude != nil {
|
||||
if errs := exclude.UserInfo.Validate(path.Child("exclude")); len(errs) != 0 {
|
||||
return "exclude", errs.ToAggregate()
|
||||
}
|
||||
if (len(exclude.Any) > 0 || len(exclude.All) > 0) && !datautils.DeepEqual(exclude.ResourceDescription, kyvernov1.ResourceDescription{}) {
|
||||
return "exclude.", fmt.Errorf("can't specify any/all together with exclude resources")
|
||||
}
|
||||
if len(exclude.Any) > 0 && len(exclude.All) > 0 {
|
||||
return "match.", fmt.Errorf("can't specify any and all together")
|
||||
}
|
||||
}
|
||||
|
||||
if (len(rule.MatchResources.Any) > 0 || len(rule.MatchResources.All) > 0) && !datautils.DeepEqual(rule.MatchResources.ResourceDescription, kyvernov1.ResourceDescription{}) {
|
||||
return "match.", fmt.Errorf("can't specify any/all together with match resources")
|
||||
}
|
||||
|
||||
if (len(rule.ExcludeResources.Any) > 0 || len(rule.ExcludeResources.All) > 0) && !datautils.DeepEqual(rule.ExcludeResources.ResourceDescription, kyvernov1.ResourceDescription{}) {
|
||||
return "exclude.", fmt.Errorf("can't specify any/all together with exclude resources")
|
||||
}
|
||||
|
||||
if len(rule.ExcludeResources.Any) > 0 && len(rule.ExcludeResources.All) > 0 {
|
||||
return "match.", fmt.Errorf("can't specify any and all together")
|
||||
}
|
||||
|
||||
if len(rule.MatchResources.Any) > 0 {
|
||||
for _, rmr := range rule.MatchResources.Any {
|
||||
// matched resources
|
||||
|
|
Loading…
Reference in a new issue