add validate for advanced audit policy

This change checks group name and non-resrouce URLs format for audit
policy.
This commit is contained in:
Cao Shufeng
2017-06-20 16:57:12 +08:00
parent 11b5956f7a
commit 7437b88386
3 changed files with 72 additions and 1 deletions

View File

@@ -21,6 +21,7 @@ go_library(
srcs = ["validation.go"], srcs = ["validation.go"],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library",
], ],

View File

@@ -17,6 +17,9 @@ limitations under the License.
package validation package validation
import ( import (
"strings"
"k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/apis/audit"
) )
@@ -33,6 +36,8 @@ func ValidatePolicy(policy *audit.Policy) field.ErrorList {
func validatePolicyRule(rule audit.PolicyRule, fldPath *field.Path) field.ErrorList { func validatePolicyRule(rule audit.PolicyRule, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList var allErrs field.ErrorList
allErrs = append(allErrs, validateLevel(rule.Level, fldPath.Child("level"))...) allErrs = append(allErrs, validateLevel(rule.Level, fldPath.Child("level"))...)
allErrs = append(allErrs, validateNonResourceURLs(rule.NonResourceURLs, fldPath.Child("nonResourceURLs"))...)
allErrs = append(allErrs, validateResources(rule.Resources, fldPath.Child("resources"))...)
if len(rule.NonResourceURLs) > 0 { if len(rule.NonResourceURLs) > 0 {
if len(rule.Resources) > 0 || len(rule.Namespaces) > 0 { if len(rule.Resources) > 0 || len(rule.Namespaces) > 0 {
@@ -60,3 +65,40 @@ func validateLevel(level audit.Level, fldPath *field.Path) field.ErrorList {
return field.ErrorList{field.NotSupported(fldPath, level, validLevels)} return field.ErrorList{field.NotSupported(fldPath, level, validLevels)}
} }
} }
func validateNonResourceURLs(urls []string, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
for i, url := range urls {
if url == "*" {
continue
}
if !strings.HasPrefix(url, "/") {
allErrs = append(allErrs, field.Invalid(fldPath.Index(i), url, "non-resource URL rules must begin with a '/' character"))
}
if url != "" && strings.ContainsRune(url[:len(url)-1], '*') {
allErrs = append(allErrs, field.Invalid(fldPath.Index(i), url, "non-resource URL wildcards '*' must be the final character of the rule"))
}
}
return allErrs
}
func validateResources(groupResources []audit.GroupResources, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
for _, groupResource := range groupResources {
// The empty string represents the core API group.
if len(groupResource.Group) == 0 {
continue
}
// Group names must be lower case and be valid DNS subdomains.
// reference: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md
// an error is returned for group name like rbac.authorization.k8s.io/v1beta1
// rbac.authorization.k8s.io is the valid one
if msgs := validation.NameIsDNSSubdomain(groupResource.Group, false); len(msgs) != 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), groupResource.Group, strings.Join(msgs, ",")))
}
}
return allErrs
}

View File

@@ -32,7 +32,7 @@ func TestValidatePolicy(t *testing.T) {
}, { // Specific request }, { // Specific request
Level: audit.LevelRequestResponse, Level: audit.LevelRequestResponse,
Verbs: []string{"get"}, Verbs: []string{"get"},
Resources: []audit.GroupResources{{Resources: []string{"secrets"}}}, Resources: []audit.GroupResources{{Group: "rbac.authorization.k8s.io", Resources: []string{"roles", "rolebindings"}}},
Namespaces: []string{"kube-system"}, Namespaces: []string{"kube-system"},
}, { // Some non-resource URLs }, { // Some non-resource URLs
Level: audit.LevelMetadata, Level: audit.LevelMetadata,
@@ -41,6 +41,7 @@ func TestValidatePolicy(t *testing.T) {
"/logs*", "/logs*",
"/healthz*", "/healthz*",
"/metrics", "/metrics",
"*",
}, },
}, },
} }
@@ -73,6 +74,33 @@ func TestValidatePolicy(t *testing.T) {
Level: audit.LevelMetadata, Level: audit.LevelMetadata,
Resources: []audit.GroupResources{{Resources: []string{"secrets"}}}, Resources: []audit.GroupResources{{Resources: []string{"secrets"}}},
NonResourceURLs: []string{"/logs*"}, NonResourceURLs: []string{"/logs*"},
}, { // invalid group name
Level: audit.LevelMetadata,
Resources: []audit.GroupResources{{Group: "rbac.authorization.k8s.io/v1beta1", Resources: []string{"roles"}}},
}, { // invalid non-resource URLs
Level: audit.LevelMetadata,
NonResourceURLs: []string{
"logs",
"/healthz*",
},
}, { // empty non-resource URLs
Level: audit.LevelMetadata,
NonResourceURLs: []string{
"",
"/healthz*",
},
}, { // invalid non-resource URLs with multi "*"
Level: audit.LevelMetadata,
NonResourceURLs: []string{
"/logs/*/*",
"/metrics",
},
}, { // invalid non-resrouce URLs with "*" not in the end
Level: audit.LevelMetadata,
NonResourceURLs: []string{
"/logs/*.log",
"/metrics",
},
}, },
} }
errorCases := []audit.Policy{} errorCases := []audit.Policy{}