Skip to content

Commit

Permalink
properly deserialize anyPattern
Browse files Browse the repository at this point in the history
  • Loading branch information
realshuting committed Nov 14, 2020
1 parent 365dd6e commit 943935e
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 31 deletions.
2 changes: 0 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 22 additions & 2 deletions pkg/api/kyverno/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 24 additions & 2 deletions pkg/api/policyreport/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion pkg/engine/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 11 additions & 2 deletions pkg/policy/background.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -67,6 +75,7 @@ func ContainsVariablesOtherThanObject(policy kyverno.ClusterPolicy) error {
}
}
}

return nil
}

Expand Down
33 changes: 21 additions & 12 deletions pkg/policy/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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{})
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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" {
Expand Down
14 changes: 10 additions & 4 deletions pkg/policy/validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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)")
}

Expand Down
11 changes: 8 additions & 3 deletions pkg/policymutation/cronjob.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}) {
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 7 additions & 2 deletions pkg/policymutation/policymutation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion pkg/policyreport/reportrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down

0 comments on commit 943935e

Please sign in to comment.