@@ -24,9 +24,11 @@ import (
24
24
metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
25
25
"k8s.io/apimachinery/pkg/util/sets"
26
26
"k8s.io/apimachinery/pkg/util/validation"
27
+ utilvalidation "k8s.io/apimachinery/pkg/util/validation"
27
28
"k8s.io/apimachinery/pkg/util/validation/field"
28
29
"k8s.io/apiserver/pkg/util/webhook"
29
30
"k8s.io/kubernetes/pkg/apis/admissionregistration"
31
+ "k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1"
30
32
)
31
33
32
34
func hasWildcard (slice []string ) bool {
@@ -150,18 +152,71 @@ func validateRule(rule *admissionregistration.Rule, fldPath *field.Path, allowSu
150
152
return allErrors
151
153
}
152
154
155
+ var AcceptedAdmissionReviewVersions = []string {v1beta1 .SchemeGroupVersion .Version }
156
+
157
+ func isAcceptedAdmissionReviewVersion (v string ) bool {
158
+ for _ , version := range AcceptedAdmissionReviewVersions {
159
+ if v == version {
160
+ return true
161
+ }
162
+ }
163
+ return false
164
+ }
165
+
166
+ func validateAdmissionReviewVersions (versions []string , requireRecognizedVersion bool , fldPath * field.Path ) field.ErrorList {
167
+ allErrors := field.ErrorList {}
168
+
169
+ // Currently only v1beta1 accepted in AdmissionReviewVersions
170
+ if len (versions ) < 1 {
171
+ allErrors = append (allErrors , field .Required (fldPath , "" ))
172
+ } else {
173
+ seen := map [string ]bool {}
174
+ hasAcceptedVersion := false
175
+ for i , v := range versions {
176
+ if seen [v ] {
177
+ allErrors = append (allErrors , field .Invalid (fldPath .Index (i ), v , "duplicate version" ))
178
+ continue
179
+ }
180
+ seen [v ] = true
181
+ for _ , errString := range utilvalidation .IsDNS1035Label (v ) {
182
+ allErrors = append (allErrors , field .Invalid (fldPath .Index (i ), v , errString ))
183
+ }
184
+ if isAcceptedAdmissionReviewVersion (v ) {
185
+ hasAcceptedVersion = true
186
+ }
187
+ }
188
+ if requireRecognizedVersion && ! hasAcceptedVersion {
189
+ allErrors = append (allErrors , field .Invalid (
190
+ fldPath , versions ,
191
+ fmt .Sprintf ("none of the versions accepted by this server. accepted version(s) are %v" ,
192
+ strings .Join (AcceptedAdmissionReviewVersions , ", " ))))
193
+ }
194
+ }
195
+ return allErrors
196
+ }
197
+
153
198
func ValidateValidatingWebhookConfiguration (e * admissionregistration.ValidatingWebhookConfiguration ) field.ErrorList {
199
+ return validateValidatingWebhookConfiguration (e , true )
200
+ }
201
+
202
+ func validateValidatingWebhookConfiguration (e * admissionregistration.ValidatingWebhookConfiguration , requireRecognizedVersion bool ) field.ErrorList {
154
203
allErrors := genericvalidation .ValidateObjectMeta (& e .ObjectMeta , false , genericvalidation .NameIsDNSSubdomain , field .NewPath ("metadata" ))
155
204
for i , hook := range e .Webhooks {
156
205
allErrors = append (allErrors , validateWebhook (& hook , field .NewPath ("webhooks" ).Index (i ))... )
206
+ allErrors = append (allErrors , validateAdmissionReviewVersions (hook .AdmissionReviewVersions , requireRecognizedVersion , field .NewPath ("webhooks" ).Index (i ).Child ("admissionReviewVersions" ))... )
157
207
}
158
208
return allErrors
159
209
}
160
210
161
211
func ValidateMutatingWebhookConfiguration (e * admissionregistration.MutatingWebhookConfiguration ) field.ErrorList {
212
+ return validateMutatingWebhookConfiguration (e , true )
213
+ }
214
+
215
+ func validateMutatingWebhookConfiguration (e * admissionregistration.MutatingWebhookConfiguration , requireRecognizedVersion bool ) field.ErrorList {
162
216
allErrors := genericvalidation .ValidateObjectMeta (& e .ObjectMeta , false , genericvalidation .NameIsDNSSubdomain , field .NewPath ("metadata" ))
163
217
for i , hook := range e .Webhooks {
164
218
allErrors = append (allErrors , validateWebhook (& hook , field .NewPath ("webhooks" ).Index (i ))... )
219
+ allErrors = append (allErrors , validateAdmissionReviewVersions (hook .AdmissionReviewVersions , requireRecognizedVersion , field .NewPath ("webhooks" ).Index (i ).Child ("admissionReviewVersions" ))... )
165
220
}
166
221
return allErrors
167
222
}
@@ -247,10 +302,28 @@ func validateRuleWithOperations(ruleWithOperations *admissionregistration.RuleWi
247
302
return allErrors
248
303
}
249
304
305
+ // hasAcceptedAdmissionReviewVersions returns true if all webhooks have at least one
306
+ // admission review version this apiserver accepts.
307
+ func hasAcceptedAdmissionReviewVersions (webhooks []admissionregistration.Webhook ) bool {
308
+ for _ , hook := range webhooks {
309
+ hasRecognizedVersion := false
310
+ for _ , version := range hook .AdmissionReviewVersions {
311
+ if isAcceptedAdmissionReviewVersion (version ) {
312
+ hasRecognizedVersion = true
313
+ break
314
+ }
315
+ }
316
+ if ! hasRecognizedVersion && len (hook .AdmissionReviewVersions ) > 0 {
317
+ return false
318
+ }
319
+ }
320
+ return true
321
+ }
322
+
250
323
func ValidateValidatingWebhookConfigurationUpdate (newC , oldC * admissionregistration.ValidatingWebhookConfiguration ) field.ErrorList {
251
- return ValidateValidatingWebhookConfiguration (newC )
324
+ return validateValidatingWebhookConfiguration (newC , hasAcceptedAdmissionReviewVersions ( oldC . Webhooks ) )
252
325
}
253
326
254
327
func ValidateMutatingWebhookConfigurationUpdate (newC , oldC * admissionregistration.MutatingWebhookConfiguration ) field.ErrorList {
255
- return ValidateMutatingWebhookConfiguration (newC )
328
+ return validateMutatingWebhookConfiguration (newC , hasAcceptedAdmissionReviewVersions ( oldC . Webhooks ) )
256
329
}
0 commit comments