validation.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. Copyright 2018 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package validation
  14. import (
  15. "strings"
  16. genericvalidation "k8s.io/apimachinery/pkg/api/validation"
  17. "k8s.io/apimachinery/pkg/util/sets"
  18. "k8s.io/apimachinery/pkg/util/validation/field"
  19. "k8s.io/apiserver/pkg/util/webhook"
  20. "k8s.io/kubernetes/pkg/apis/auditregistration"
  21. )
  22. // ValidateAuditSink validates the AuditSinks
  23. func ValidateAuditSink(as *auditregistration.AuditSink) field.ErrorList {
  24. allErrs := genericvalidation.ValidateObjectMeta(&as.ObjectMeta, false, genericvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
  25. allErrs = append(allErrs, ValidateAuditSinkSpec(as.Spec, field.NewPath("spec"))...)
  26. return allErrs
  27. }
  28. // ValidateAuditSinkSpec validates the sink spec for audit
  29. func ValidateAuditSinkSpec(s auditregistration.AuditSinkSpec, fldPath *field.Path) field.ErrorList {
  30. var allErrs field.ErrorList
  31. allErrs = append(allErrs, ValidatePolicy(s.Policy, fldPath.Child("policy"))...)
  32. allErrs = append(allErrs, ValidateWebhook(s.Webhook, fldPath.Child("webhook"))...)
  33. return allErrs
  34. }
  35. // ValidateWebhook validates the webhook
  36. func ValidateWebhook(w auditregistration.Webhook, fldPath *field.Path) field.ErrorList {
  37. var allErrs field.ErrorList
  38. if w.Throttle != nil {
  39. allErrs = append(allErrs, ValidateWebhookThrottleConfig(w.Throttle, fldPath.Child("throttle"))...)
  40. }
  41. cc := w.ClientConfig
  42. switch {
  43. case (cc.URL == nil) == (cc.Service == nil):
  44. allErrs = append(allErrs, field.Required(fldPath.Child("clientConfig"), "exactly one of url or service is required"))
  45. case cc.URL != nil:
  46. allErrs = append(allErrs, webhook.ValidateWebhookURL(fldPath.Child("clientConfig").Child("url"), *cc.URL, false)...)
  47. case cc.Service != nil:
  48. allErrs = append(allErrs, webhook.ValidateWebhookService(fldPath.Child("clientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path, cc.Service.Port)...)
  49. }
  50. return allErrs
  51. }
  52. // ValidateWebhookThrottleConfig validates the throttle config
  53. func ValidateWebhookThrottleConfig(c *auditregistration.WebhookThrottleConfig, fldPath *field.Path) field.ErrorList {
  54. var allErrs field.ErrorList
  55. if c.QPS != nil && *c.QPS <= 0 {
  56. allErrs = append(allErrs, field.Invalid(fldPath.Child("qps"), c.QPS, "qps must be a positive number"))
  57. }
  58. if c.Burst != nil && *c.Burst <= 0 {
  59. allErrs = append(allErrs, field.Invalid(fldPath.Child("burst"), c.Burst, "burst must be a positive number"))
  60. }
  61. return allErrs
  62. }
  63. // ValidatePolicy validates the audit policy
  64. func ValidatePolicy(policy auditregistration.Policy, fldPath *field.Path) field.ErrorList {
  65. var allErrs field.ErrorList
  66. allErrs = append(allErrs, validateStages(policy.Stages, fldPath.Child("stages"))...)
  67. allErrs = append(allErrs, validateLevel(policy.Level, fldPath.Child("level"))...)
  68. if policy.Level != auditregistration.LevelNone && len(policy.Stages) == 0 {
  69. return field.ErrorList{field.Required(fldPath.Child("stages"), "")}
  70. }
  71. return allErrs
  72. }
  73. var validLevels = sets.NewString(
  74. string(auditregistration.LevelNone),
  75. string(auditregistration.LevelMetadata),
  76. string(auditregistration.LevelRequest),
  77. string(auditregistration.LevelRequestResponse),
  78. )
  79. var validStages = sets.NewString(
  80. string(auditregistration.StageRequestReceived),
  81. string(auditregistration.StageResponseStarted),
  82. string(auditregistration.StageResponseComplete),
  83. string(auditregistration.StagePanic),
  84. )
  85. func validateLevel(level auditregistration.Level, fldPath *field.Path) field.ErrorList {
  86. if string(level) == "" {
  87. return field.ErrorList{field.Required(fldPath, "")}
  88. }
  89. if !validLevels.Has(string(level)) {
  90. return field.ErrorList{field.NotSupported(fldPath, level, validLevels.List())}
  91. }
  92. return nil
  93. }
  94. func validateStages(stages []auditregistration.Stage, fldPath *field.Path) field.ErrorList {
  95. var allErrs field.ErrorList
  96. for i, stage := range stages {
  97. if !validStages.Has(string(stage)) {
  98. allErrs = append(allErrs, field.Invalid(fldPath.Index(i), string(stage), "allowed stages are "+strings.Join(validStages.List(), ",")))
  99. }
  100. }
  101. return allErrs
  102. }
  103. // ValidateAuditSinkUpdate validates an update to the object
  104. func ValidateAuditSinkUpdate(newC, oldC *auditregistration.AuditSink) field.ErrorList {
  105. return ValidateAuditSink(newC)
  106. }