k3s icon indicating copy to clipboard operation
k3s copied to clipboard

OpenAPIV3Schema validation in CustomResourceDefinition is not applied

Open reegnz opened this issue 6 years ago • 4 comments

When a CRD contains an OpenAPIV3Schema validation spec, the validation is not executed in k3s, and invalid resources are accepted by the API Server.

To Reproduce test-crd.yaml:

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: examplecrds.example.com
spec:
  scope: Namespaced
  group: example.com
  versions:
  - name: v1
    served: true
    storage: true
  names:
    kind: ExampleCRD
    plural: examplecrds
    singular: examplecrd
  validation:
    openAPIV3Schema:
      required: [spec]
      properties:
        spec:
          required: [musthave]
          properties:
            musthave:
              enum: [one,two,three]
            irrelevant:
              enum: [something]

valid-resource.yaml:

apiVersion: example.com/v1
kind: ExampleCRD
metadata:
  name: test
spec:
  musthave: two

invalid-resources.yaml:

---
apiVersion: example.com/v1
kind: ExampleCRD
metadata:
  name: invalid1
spec:
  musthave: four
---
apiVersion: example.com/v1
kind: ExampleCRD
metadata:
  name: invalid2
spec:
  musthave: three
  irrelevant: bad
---
apiVersion: example.com/v1
kind: ExampleCRD
metadata:
  name: invalid3
spec:
  irrelevant: something

Expected behavior

➜ kubectl apply -f test-crd.yaml
customresourcedefinition.apiextensions.k8s.io/examplecrds.example.com created

➜ kubectl apply -f valid-resource.yaml
examplecrd.example.com/test created

➜ kubectl apply -f invalid-resources.yaml
Error from server (Invalid): error when creating "invalid-resources.yaml": ExampleCRD.example.com "invalid1" is invalid: []: Invalid value: map[string]interface {}{"apiVersion":"example.com/v1", "kind":"ExampleCRD", "metadata":map[string]interface {}{"name":"invalid1", "namespace":"db", "creationTimestamp":"2019-05-03T14:05:10Z", "annotations":map[string]interface {}{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"example.com/v1\",\"kind\":\"ExampleCRD\",\"metadata\":{\"annotations\":{},\"name\":\"invalid1\",\"namespace\":\"db\"},\"spec\":{\"musthave\":\"four\"}}\n"}, "generation":1, "uid":"76e5ce1d-6dac-11e9-9968-021ac63aea36"}, "spec":map[string]interface {}{"musthave":"four"}}: validation failure list:
spec.musthave in body should be one of [one two three]
Error from server (Invalid): error when creating "invalid-resources.yaml": ExampleCRD.example.com "invalid2" is invalid: []: Invalid value: map[string]interface {}{"apiVersion":"example.com/v1", "kind":"ExampleCRD", "metadata":map[string]interface {}{"generation":1, "uid":"77403101-6dac-11e9-9968-021ac63aea36", "name":"invalid2", "namespace":"db", "creationTimestamp":"2019-05-03T14:05:11Z", "annotations":map[string]interface {}{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"example.com/v1\",\"kind\":\"ExampleCRD\",\"metadata\":{\"annotations\":{},\"name\":\"invalid2\",\"namespace\":\"db\"},\"spec\":{\"irrelevant\":\"bad\",\"musthave\":\"three\"}}\n"}}, "spec":map[string]interface {}{"irrelevant":"bad", "musthave":"three"}}: validation failure list:
spec.irrelevant in body should be one of [something]
Error from server (Invalid): error when creating "invalid-resources.yaml": ExampleCRD.example.com "invalid3" is invalid: []: Invalid value: map[string]interface {}{"kind":"ExampleCRD", "metadata":map[string]interface {}{"creationTimestamp":"2019-05-03T14:05:11Z", "annotations":map[string]interface {}{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"example.com/v1\",\"kind\":\"ExampleCRD\",\"metadata\":{\"annotations\":{},\"name\":\"invalid3\",\"namespace\":\"db\"},\"spec\":{\"irrelevant\":\"something\"}}\n"}, "generation":1, "uid":"77982fb8-6dac-11e9-9968-021ac63aea36", "name":"invalid3", "namespace":"db"}, "spec":map[string]interface {}{"irrelevant":"something"}, "apiVersion":"example.com/v1"}: validation failure list:
spec.musthave in body is required

Actual Output

➜ kubectl apply -f test-crd.yaml
customresourcedefinition.apiextensions.k8s.io/examplecrds.example.com created

➜ kubectl apply -f valid-resource.yaml
examplecrd.example.com/test created

➜ kubectl apply -f invalid-resources.yaml
examplecrd.example.com/invalid1 created
examplecrd.example.com/invalid2 created
examplecrd.example.com/invalid3 created

reegnz avatar May 03 '19 14:05 reegnz

OpenAPI support does not exist in k3s atm. OpenAPI adds a huge amount of bloat so we are working on a solution here. Right now the openapi schema that k3s serves up is a static file.

CRD validation and serving openapi for aggregated APIs are the known broken areas for k3s. K8s 1.15 will introduce more features that require openapi so we are working on this.

ibuildthecloud avatar May 03 '19 16:05 ibuildthecloud

Good to know. Jusy started experimenting with this part of CRD-s, so it's no biggie (not a deal breaker). I am playing with k3s for local development and I tend to do k8s experiments mainly with k3s (fastest way to bootstrap a cluster I know of). But I guess this could surprise some people who rely on it more than I do and I want k3s to succeed. :)

reegnz avatar May 03 '19 19:05 reegnz

Using apiextensions.k8s.io/v1 crds instead of v1beta1 might resolve this. I'd noticed invalid extra fields weren't being rejected in k3s for my v1beta1 crd. I started seeing expected rejections after switching to v1 (in order to use CustomResourceDefaulting)

wilsonianb avatar Apr 20 '20 22:04 wilsonianb

I was able to resolve it for yamls after referring to this example: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#specify-multiple-versions and this guide: https://kubernetes.io/docs/reference/using-api/deprecation-guide/#customresourcedefinition-v122

prnvkv avatar Jul 12 '22 12:07 prnvkv

Closing due to age

caroline-suse-rancher avatar Jun 21 '23 21:06 caroline-suse-rancher