mirror of https://github.com/k3s-io/k3s
124 lines
4.6 KiB
Go
124 lines
4.6 KiB
Go
/*
|
|
Copyright 2018 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.
|
|
*/
|
|
|
|
package validation
|
|
|
|
import (
|
|
"strings"
|
|
|
|
genericvalidation "k8s.io/apimachinery/pkg/api/validation"
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
|
"k8s.io/apiserver/pkg/util/webhook"
|
|
"k8s.io/kubernetes/pkg/apis/auditregistration"
|
|
)
|
|
|
|
// ValidateAuditSink validates the AuditSinks
|
|
func ValidateAuditSink(as *auditregistration.AuditSink) field.ErrorList {
|
|
allErrs := genericvalidation.ValidateObjectMeta(&as.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
|
|
allErrs = append(allErrs, ValidateAuditSinkSpec(as.Spec, field.NewPath("spec"))...)
|
|
return allErrs
|
|
}
|
|
|
|
// ValidateAuditSinkSpec validates the sink spec for audit
|
|
func ValidateAuditSinkSpec(s auditregistration.AuditSinkSpec, fldPath *field.Path) field.ErrorList {
|
|
var allErrs field.ErrorList
|
|
allErrs = append(allErrs, ValidatePolicy(s.Policy, fldPath.Child("policy"))...)
|
|
allErrs = append(allErrs, ValidateWebhook(s.Webhook, fldPath.Child("webhook"))...)
|
|
return allErrs
|
|
}
|
|
|
|
// ValidateWebhook validates the webhook
|
|
func ValidateWebhook(w auditregistration.Webhook, fldPath *field.Path) field.ErrorList {
|
|
var allErrs field.ErrorList
|
|
if w.Throttle != nil {
|
|
allErrs = append(allErrs, ValidateWebhookThrottleConfig(w.Throttle, fldPath.Child("throttle"))...)
|
|
}
|
|
|
|
cc := w.ClientConfig
|
|
switch {
|
|
case (cc.URL == nil) == (cc.Service == nil):
|
|
allErrs = append(allErrs, field.Required(fldPath.Child("clientConfig"), "exactly one of url or service is required"))
|
|
case cc.URL != nil:
|
|
allErrs = append(allErrs, webhook.ValidateWebhookURL(fldPath.Child("clientConfig").Child("url"), *cc.URL, false)...)
|
|
case cc.Service != nil:
|
|
allErrs = append(allErrs, webhook.ValidateWebhookService(fldPath.Child("clientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path, cc.Service.Port)...)
|
|
}
|
|
return allErrs
|
|
}
|
|
|
|
// ValidateWebhookThrottleConfig validates the throttle config
|
|
func ValidateWebhookThrottleConfig(c *auditregistration.WebhookThrottleConfig, fldPath *field.Path) field.ErrorList {
|
|
var allErrs field.ErrorList
|
|
if c.QPS != nil && *c.QPS <= 0 {
|
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("qps"), c.QPS, "qps must be a positive number"))
|
|
}
|
|
if c.Burst != nil && *c.Burst <= 0 {
|
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("burst"), c.Burst, "burst must be a positive number"))
|
|
}
|
|
return allErrs
|
|
}
|
|
|
|
// ValidatePolicy validates the audit policy
|
|
func ValidatePolicy(policy auditregistration.Policy, fldPath *field.Path) field.ErrorList {
|
|
var allErrs field.ErrorList
|
|
allErrs = append(allErrs, validateStages(policy.Stages, fldPath.Child("stages"))...)
|
|
allErrs = append(allErrs, validateLevel(policy.Level, fldPath.Child("level"))...)
|
|
if policy.Level != auditregistration.LevelNone && len(policy.Stages) == 0 {
|
|
return field.ErrorList{field.Required(fldPath.Child("stages"), "")}
|
|
}
|
|
return allErrs
|
|
}
|
|
|
|
var validLevels = sets.NewString(
|
|
string(auditregistration.LevelNone),
|
|
string(auditregistration.LevelMetadata),
|
|
string(auditregistration.LevelRequest),
|
|
string(auditregistration.LevelRequestResponse),
|
|
)
|
|
|
|
var validStages = sets.NewString(
|
|
string(auditregistration.StageRequestReceived),
|
|
string(auditregistration.StageResponseStarted),
|
|
string(auditregistration.StageResponseComplete),
|
|
string(auditregistration.StagePanic),
|
|
)
|
|
|
|
func validateLevel(level auditregistration.Level, fldPath *field.Path) field.ErrorList {
|
|
if string(level) == "" {
|
|
return field.ErrorList{field.Required(fldPath, "")}
|
|
}
|
|
if !validLevels.Has(string(level)) {
|
|
return field.ErrorList{field.NotSupported(fldPath, level, validLevels.List())}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateStages(stages []auditregistration.Stage, fldPath *field.Path) field.ErrorList {
|
|
var allErrs field.ErrorList
|
|
for i, stage := range stages {
|
|
if !validStages.Has(string(stage)) {
|
|
allErrs = append(allErrs, field.Invalid(fldPath.Index(i), string(stage), "allowed stages are "+strings.Join(validStages.List(), ",")))
|
|
}
|
|
}
|
|
return allErrs
|
|
}
|
|
|
|
// ValidateAuditSinkUpdate validates an update to the object
|
|
func ValidateAuditSinkUpdate(newC, oldC *auditregistration.AuditSink) field.ErrorList {
|
|
return ValidateAuditSink(newC)
|
|
}
|