1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-13 19:28:55 +00:00

properly deserialize anyPattern

This commit is contained in:
Shuting Zhao 2020-11-13 16:25:51 -08:00
parent 365dd6e408
commit 943935ee1b
10 changed files with 115 additions and 31 deletions

View file

@ -185,12 +185,10 @@ release:
kyverno-crd: controller-gen
$(CONTROLLER_GEN) crd paths=./pkg/api/kyverno/v1alpha1 output:dir=./definitions/crds
$(CONTROLLER_GEN) object paths=./pkg/api/kyverno/v1alpha1
$(CONTROLLER_GEN) crd paths=./pkg/api/kyverno/v1 output:dir=./definitions/crds
report-crd: controller-gen
$(CONTROLLER_GEN) crd paths=./pkg/api/policyreport/v1alpha1 output:dir=./definitions/crds
$(CONTROLLER_GEN) object paths=./pkg/api/policyreport/v1alpha1
# find or download controller-gen
# download controller-gen if necessary

View file

@ -1,12 +1,28 @@
// +build !ignore_autogenerated
// Code generated by controller-gen. DO NOT EDIT.
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha1
import (
policyreportv1alpha1 "github.com/kyverno/kyverno/pkg/api/policyreport/v1alpha1"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -38,6 +54,7 @@ func (in *ClusterReportChangeRequest) DeepCopyInto(out *ClusterReportChangeReque
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterReportChangeRequest.
@ -70,6 +87,7 @@ func (in *ClusterReportChangeRequestList) DeepCopyInto(out *ClusterReportChangeR
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterReportChangeRequestList.
@ -117,6 +135,7 @@ func (in *ReportChangeRequest) DeepCopyInto(out *ReportChangeRequest) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportChangeRequest.
@ -149,6 +168,7 @@ func (in *ReportChangeRequestList) DeepCopyInto(out *ReportChangeRequestList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportChangeRequestList.

View file

@ -1,11 +1,27 @@
// +build !ignore_autogenerated
// Code generated by controller-gen. DO NOT EDIT.
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha1
import (
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -37,6 +53,7 @@ func (in *ClusterPolicyReport) DeepCopyInto(out *ClusterPolicyReport) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPolicyReport.
@ -69,6 +86,7 @@ func (in *ClusterPolicyReportList) DeepCopyInto(out *ClusterPolicyReportList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPolicyReportList.
@ -116,6 +134,7 @@ func (in *PolicyReport) DeepCopyInto(out *PolicyReport) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReport.
@ -148,6 +167,7 @@ func (in *PolicyReportList) DeepCopyInto(out *PolicyReportList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportList.
@ -194,6 +214,7 @@ func (in *PolicyReportResult) DeepCopyInto(out *PolicyReportResult) {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportResult.
@ -209,6 +230,7 @@ func (in *PolicyReportResult) DeepCopy() *PolicyReportResult {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyReportSummary) DeepCopyInto(out *PolicyReportSummary) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportSummary.

View file

@ -291,7 +291,15 @@ func validatePatterns(log logr.Logger, ctx context.EvalInterface, resource unstr
var failedSubstitutionsErrors []error
var failedAnyPatternsErrors []error
var err error
for idx, pattern := range validationRule.AnyPattern {
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
resp.Success = false
resp.Message = fmt.Sprintf("Failed to deserialze anyPattern, expect type array: %v", err)
return resp
}
for idx, pattern := range anyPatterns {
if pattern, err = variables.SubstituteVars(logger, ctx, pattern); err != nil {
// variable subsitution failed
failedSubstitutionsErrors = append(failedSubstitutionsErrors, err)

View file

@ -48,14 +48,22 @@ func ContainsVariablesOtherThanObject(policy kyverno.ClusterPolicy) error {
return fmt.Errorf("invalid variable used at spec/rules[%d]/validate/pattern", idx)
}
}
for idx2, pattern := range rule.Validation.AnyPattern {
if rule.Validation.AnyPattern[idx2], err = variables.SubstituteVars(log.Log, ctx, pattern); !checkNotFoundErr(err) {
anyPattern, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
return fmt.Errorf("failed to deserialze anyPattern, expect array: %v", err)
}
for idx2, pattern := range anyPattern {
if anyPattern[idx2], err = variables.SubstituteVars(log.Log, ctx, pattern); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable used at spec/rules[%d]/validate/anyPattern[%d]", idx, idx2)
}
}
if _, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Message); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable used at spec/rules[%d]/validate/message", idx)
}
if rule.Validation.Deny != nil {
for i := range rule.Validation.Deny.Conditions {
if _, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Deny.Conditions[i].Key); !checkNotFoundErr(err) {
@ -67,6 +75,7 @@ func ContainsVariablesOtherThanObject(policy kyverno.ClusterPolicy) error {
}
}
}
return nil
}

View file

@ -7,16 +7,14 @@ import (
"reflect"
"strings"
"github.com/kyverno/kyverno/pkg/kyverno/common"
"github.com/minio/minio/pkg/wildcard"
"github.com/kyverno/kyverno/pkg/openapi"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
dclient "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/kyverno/common"
"github.com/kyverno/kyverno/pkg/openapi"
"github.com/minio/minio/pkg/wildcard"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
log "sigs.k8s.io/controller-runtime/pkg/log"
)
// Validate does some initial check to verify some conditions
@ -66,8 +64,8 @@ func Validate(policyRaw []byte, client *dclient.Client, mock bool, openAPIContro
return fmt.Errorf("path: spec.rules[%d]: %v", i, err)
}
// validate Cluster Resources in namespaced cluster policy
// For namespaced cluster policy, ClusterResource type field and values are not allowed in match and exclude
// validate Cluster Resources in namespaced policy
// For namespaced policy, ClusterResource type field and values are not allowed in match and exclude
if !mock && p.ObjectMeta.Namespace != "" {
var Empty struct{}
clusterResourcesMap := make(map[string]*struct{})
@ -147,7 +145,7 @@ func checkInvalidFields(policyRaw []byte) error {
}
mapData := data.(map[string]interface{})
// validate any new fields in the admission request against the supported fields and block the request with any new fields
for requestField, _ := range mapData {
for requestField := range mapData {
ok := false
for _, allowedField := range allowedKeys {
if requestField == allowedField {
@ -348,8 +346,13 @@ func isLabelAndAnnotationsString(rule kyverno.Rule) bool {
patternMap, ok := rule.Validation.Pattern.(map[string]interface{})
if ok {
return checkMetadata(patternMap)
} else if len(rule.Validation.AnyPattern) > 0 {
anyPatterns := rule.Validation.AnyPattern
} else if rule.Validation.AnyPattern != nil {
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
log.Log.Error(err, "failed to deserialze anyPattern, expect type array")
return false
}
for _, pattern := range anyPatterns {
patternMap, ok := pattern.(map[string]interface{})
if ok {
@ -384,7 +387,13 @@ func ruleOnlyDealsWithResourceMetaData(rule kyverno.Rule) bool {
}
}
for _, pattern := range rule.Validation.AnyPattern {
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
log.Log.Error(err, "failed to deserialze anyPattern, expect type array")
return false
}
for _, pattern := range anyPatterns {
patternMap, _ := pattern.(map[string]interface{})
for k := range patternMap {
if k != "metadata" {

View file

@ -36,8 +36,14 @@ func (v *Validate) Validate() (string, error) {
}
}
if len(rule.AnyPattern) != 0 {
for i, pattern := range rule.AnyPattern {
if rule.AnyPattern != nil {
// validation := &kyverno.Validation{}
// rule.DeepCopyInto(validation)
anyPattern, err := rule.DeserializeAnyPattern()
if err != nil {
return "anyPattern", fmt.Errorf("failed to deserialze anyPattern, expect array: %v", err)
}
for i, pattern := range anyPattern {
if path, err := common.ValidatePattern(pattern, "/", []commonAnchors.IsAnchor{commonAnchors.IsConditionAnchor, commonAnchors.IsExistenceAnchor, commonAnchors.IsEqualityAnchor, commonAnchors.IsNegationAnchor}); err != nil {
return fmt.Sprintf("anyPattern[%d].%s", i, path), err
}
@ -49,11 +55,11 @@ func (v *Validate) Validate() (string, error) {
// validateOverlayPattern checks one of pattern/anyPattern must exist
func (v *Validate) validateOverlayPattern() error {
rule := v.rule
if rule.Pattern == nil && len(rule.AnyPattern) == 0 && rule.Deny == nil {
if rule.Pattern == nil && rule.AnyPattern == nil && rule.Deny == nil {
return fmt.Errorf("pattern, anyPattern or deny must be specified")
}
if rule.Pattern != nil && len(rule.AnyPattern) != 0 {
if rule.Pattern != nil && rule.AnyPattern != nil {
return fmt.Errorf("only one operation allowed per validation rule(pattern or anyPattern)")
}

View file

@ -18,7 +18,7 @@ func generateCronJobRule(rule kyverno.Rule, controllers string, log logr.Logger)
return kyvernoRule{}
}
logger.V(3).Info("")
logger.V(3).Info("generating rule for cronJob")
jobRule := generateRuleForControllers(rule, "Job", logger)
if reflect.DeepEqual(jobRule, kyvernoRule{}) {
@ -70,9 +70,14 @@ func generateCronJobRule(rule kyverno.Rule, controllers string, log logr.Logger)
return *cronJobRule
}
if (jobRule.Validation != nil) && (len(jobRule.Validation.AnyPattern) != 0) {
if (jobRule.Validation != nil) && (jobRule.Validation.AnyPattern != nil) {
var patterns []interface{}
for _, pattern := range jobRule.Validation.AnyPattern {
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
logger.Error(err, "failed to deserialze anyPattern, expect tyepe array")
}
for _, pattern := range anyPatterns {
newPattern := map[string]interface{}{
"spec": map[string]interface{}{
"jobTemplate": pattern,

View file

@ -467,9 +467,14 @@ func generateRuleForControllers(rule kyverno.Rule, controllers string, log logr.
return *controllerRule
}
if len(rule.Validation.AnyPattern) != 0 {
if rule.Validation.AnyPattern != nil {
var patterns []interface{}
for _, pattern := range rule.Validation.AnyPattern {
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
logger.Error(err, "failed to deserialze anyPattern, expect type array")
}
for _, pattern := range anyPatterns {
newPattern := map[string]interface{}{
"spec": map[string]interface{}{
"template": pattern,

View file

@ -297,7 +297,9 @@ func (gen *Generator) sync(reportReq *unstructured.Unstructured, info Info) erro
if err != nil {
if apierrors.IsNotFound(err) {
if _, err = gen.dclient.CreateResource(reportReq.GetAPIVersion(), reportReq.GetKind(), config.KubePolicyNamespace, reportReq, false); err != nil {
return fmt.Errorf("failed to create ReportChangeRequest: %v", err)
if !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to create ReportChangeRequest: %v", err)
}
}
logger.V(3).Info("successfully created reportChangeRequest", "name", reportReq.GetName())