Commit 80a53d52 authored by Chao Xu's avatar Chao Xu

do not allow subresources in initializer rules

parent ab3e7a73
......@@ -64,6 +64,7 @@ type Initializer struct {
// Rules describes what resources/subresources the initializer cares about.
// The initializer cares about an operation if it matches _any_ Rule.
// Rule.Resources must not include subresources.
Rules []Rule
// FailurePolicy defines what happens if the responsible initializer controller
......@@ -97,7 +98,10 @@ type Rule struct {
// '*/scale' means all scale subresources.
// '*/*' means all resources and their subresources.
//
// If '*' or '*/*' is present, the length of the slice must be one.
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.
//
// Depending on the enclosing object, subresources might not be allowed.
// Required.
Resources []string
}
......
......@@ -66,6 +66,7 @@ type Initializer struct {
// Rules describes what resources/subresources the initializer cares about.
// The initializer cares about an operation if it matches _any_ Rule.
// Rule.Resources must not include subresources.
Rules []Rule `json:"rules,omitempty" protobuf:"bytes,2,rep,name=rules"`
// FailurePolicy defines what happens if the responsible initializer controller
......@@ -99,7 +100,10 @@ type Rule struct {
// '*/scale' means all scale subresources.
// '*/*' means all resources and their subresources.
//
// If '*' or '*/*' is present, the length of the slice must be one.
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.
//
// Depending on the enclosing object, subresources might not be allowed.
// Required.
Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"`
}
......
......@@ -49,7 +49,8 @@ func validateInitializer(initializer *admissionregistration.Initializer, fldPath
}
for i, rule := range initializer.Rules {
allErrors = append(allErrors, validateRule(&rule, fldPath.Child("rules").Index(i))...)
notAllowSubresources := false
allErrors = append(allErrors, validateRule(&rule, fldPath.Child("rules").Index(i), notAllowSubresources)...)
}
// TODO: relax the validation rule when admissionregistration is beta.
if initializer.FailurePolicy != nil && *initializer.FailurePolicy != admissionregistration.Ignore {
......@@ -102,10 +103,10 @@ func validateResources(resources []string, fldPath *field.Path) field.ErrorList
}
res, sub := parts[0], parts[1]
if _, ok := resourcesWithWildcardSubresoures[res]; ok {
allErrors = append(allErrors, field.Invalid(fldPath.Index(i), resources[i], fmt.Sprintf("if '%s/*' is present, must not specify %s", res, resources[i])))
allErrors = append(allErrors, field.Invalid(fldPath.Index(i), resSub, fmt.Sprintf("if '%s/*' is present, must not specify %s", res, resSub)))
}
if _, ok := subResoucesWithWildcardResource[sub]; ok {
allErrors = append(allErrors, field.Invalid(fldPath.Index(i), resources[i], fmt.Sprintf("if '*/%s' is present, must not specify %s", sub, resources[i])))
allErrors = append(allErrors, field.Invalid(fldPath.Index(i), resSub, fmt.Sprintf("if '*/%s' is present, must not specify %s", sub, resSub)))
}
if sub == "*" {
resourcesWithWildcardSubresoures[res] = struct{}{}
......@@ -123,7 +124,26 @@ func validateResources(resources []string, fldPath *field.Path) field.ErrorList
return allErrors
}
func validateRule(rule *admissionregistration.Rule, fldPath *field.Path) field.ErrorList {
func validateResourcesNoSubResources(resources []string, fldPath *field.Path) field.ErrorList {
var allErrors field.ErrorList
if len(resources) == 0 {
allErrors = append(allErrors, field.Required(fldPath, ""))
}
for i, resource := range resources {
if resource == "" {
allErrors = append(allErrors, field.Required(fldPath.Index(i), ""))
}
if strings.Contains(resource, "/") {
allErrors = append(allErrors, field.Invalid(fldPath.Index(i), resource, "must not specify subresources"))
}
}
if len(resources) > 1 && hasWildcard(resources) {
allErrors = append(allErrors, field.Invalid(fldPath, resources, "if '*' is present, must not specify other resources"))
}
return allErrors
}
func validateRule(rule *admissionregistration.Rule, fldPath *field.Path, allowSubResource bool) field.ErrorList {
var allErrors field.ErrorList
if len(rule.APIGroups) == 0 {
allErrors = append(allErrors, field.Required(fldPath.Child("apiGroups"), ""))
......@@ -143,7 +163,11 @@ func validateRule(rule *admissionregistration.Rule, fldPath *field.Path) field.E
allErrors = append(allErrors, field.Required(fldPath.Child("apiVersions").Index(i), ""))
}
}
allErrors = append(allErrors, validateResources(rule.Resources, fldPath.Child("resources"))...)
if allowSubResource {
allErrors = append(allErrors, validateResources(rule.Resources, fldPath.Child("resources"))...)
} else {
allErrors = append(allErrors, validateResourcesNoSubResources(rule.Resources, fldPath.Child("resources"))...)
}
return allErrors
}
......@@ -154,7 +178,7 @@ func ValidateInitializerConfigurationUpdate(newIC, oldIC *admissionregistration.
func ValidateExternalAdmissionHookConfiguration(e *admissionregistration.ExternalAdmissionHookConfiguration) field.ErrorList {
allErrors := genericvalidation.ValidateObjectMeta(&e.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
for i, hook := range e.ExternalAdmissionHooks {
allErrors = append(allErrors, validateExternalAdmissionHook(&hook, field.NewPath("externalAdmissionHook").Index(i))...)
allErrors = append(allErrors, validateExternalAdmissionHook(&hook, field.NewPath("externalAdmissionHooks").Index(i))...)
}
return allErrors
}
......@@ -212,7 +236,8 @@ func validateRuleWithOperations(ruleWithOperations *admissionregistration.RuleWi
allErrors = append(allErrors, field.NotSupported(fldPath.Child("operations").Index(i), operation, supportedOperations.List()))
}
}
allErrors = append(allErrors, validateRule(&ruleWithOperations.Rule, fldPath)...)
allowSubResource := true
allErrors = append(allErrors, validateRule(&ruleWithOperations.Rule, fldPath, allowSubResource)...)
return allErrors
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment