Commit 4bf994c7 authored by Dr. Stefan Schimanski's avatar Dr. Stefan Schimanski

apiextensions: forbid x-kubernetes-embedded-resource inside of resource meta fields

parent e2fd72ca
......@@ -640,6 +640,8 @@ func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiext
return allErrs
}
var metaFields = sets.NewString("metadata", "apiVersion", "kind")
// ValidateCustomResourceDefinitionOpenAPISchema statically validates
func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSchemaProps, fldPath *field.Path, ssv specStandardValidator, isRoot bool) field.ErrorList {
allErrs := field.ErrorList{}
......@@ -682,7 +684,7 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch
if len(schema.Properties) != 0 {
for property, jsonSchema := range schema.Properties {
subSsv := ssv
if (isRoot || schema.XEmbeddedResource) && property == "metadata" {
if (isRoot || schema.XEmbeddedResource) && metaFields.Has(property) {
// we recurse into the schema that applies to ObjectMeta.
subSsv = ssv.withInsideResourceMeta()
if isRoot {
......@@ -846,6 +848,10 @@ func (v *specStandardValidatorV3) validate(schema *apiextensions.JSONSchemaProps
allErrs = append(allErrs, field.Forbidden(fldPath.Child("items"), "items must be a schema object and not an array"))
}
if v.isInsideResourceMeta && schema.XEmbeddedResource {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("x-kubernetes-embedded-resource"), "must not be used inside of resource meta"))
}
return allErrs
}
......
......@@ -1568,6 +1568,71 @@ func TestValidateCustomResourceDefinition(t *testing.T) {
},
},
{
name: "x-kubernetes-embedded-resource inside resource meta",
resource: &apiextensions.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
Spec: apiextensions.CustomResourceDefinitionSpec{
Group: "group.com",
Version: "version",
Versions: singleVersionList,
Scope: apiextensions.NamespaceScoped,
Names: apiextensions.CustomResourceDefinitionNames{
Plural: "plural",
Singular: "singular",
Kind: "Plural",
ListKind: "PluralList",
},
Validation: &apiextensions.CustomResourceValidation{
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
Type: "object",
Properties: map[string]apiextensions.JSONSchemaProps{
"embedded": {
Type: "object",
XEmbeddedResource: true,
Properties: map[string]apiextensions.JSONSchemaProps{
"metadata": {
Type: "object",
XEmbeddedResource: true,
XPreserveUnknownFields: pointer.BoolPtr(true),
},
"apiVersion": {
Type: "string",
Properties: map[string]apiextensions.JSONSchemaProps{
"foo": {
Type: "object",
XEmbeddedResource: true,
XPreserveUnknownFields: pointer.BoolPtr(true),
},
},
},
"kind": {
Type: "string",
Properties: map[string]apiextensions.JSONSchemaProps{
"foo": {
Type: "object",
XEmbeddedResource: true,
XPreserveUnknownFields: pointer.BoolPtr(true),
},
},
},
},
},
},
},
},
PreserveUnknownFields: pointer.BoolPtr(true),
},
Status: apiextensions.CustomResourceDefinitionStatus{
StoredVersions: []string{"version"},
},
},
errors: []validationMatch{
forbidden("spec", "validation", "openAPIV3Schema", "properties[embedded]", "properties[metadata]", "x-kubernetes-embedded-resource"),
forbidden("spec", "validation", "openAPIV3Schema", "properties[embedded]", "properties[apiVersion]", "properties[foo]", "x-kubernetes-embedded-resource"),
forbidden("spec", "validation", "openAPIV3Schema", "properties[embedded]", "properties[kind]", "properties[foo]", "x-kubernetes-embedded-resource"),
},
},
{
name: "defaults with enabled feature gate, unstructural schema",
resource: &apiextensions.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
......
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