From d76d945678c10cd2ece434c8413842150e26b547 Mon Sep 17 00:00:00 2001 From: Cindy Bang Date: Wed, 27 Mar 2024 14:00:00 -0400 Subject: [PATCH] fix: add name validation for custom resources This propagates the label constraints of Linode resources to their associated CustomResourceDefinitions via the Kubernetes Validation Rules feature. When a custom resource is created, the Kubernetes object name is validated against the label constraints of its backing Linode resources. This allows CAPL-managed resources to maintain a human-readable naming scheme between its Kubernetes representation and the backing Linode implementation. Validation rules are implemented via Kustomize JSON patches due to limitations with Kubebuilder and Strategic Merge Patching with CRDs in Kubernetes. See: - https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules - https://www.github.com/kubernetes/kubernetes/issues/74620 - https://www.github.com/kubernetes-sigs/kubebuilder/issues/1074 - https://www.github.com/kubernetes/kubernetes/issues/113223 --- config/crd/kustomization.yaml | 21 +++++++++++++++ .../patches/validation_in_linodeclusters.yaml | 11 ++++++++ .../patches/validation_in_linodemachines.yaml | 26 +++++++++++++++++++ .../crd/patches/validation_in_linodevpcs.yaml | 25 ++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 config/crd/patches/validation_in_linodeclusters.yaml create mode 100644 config/crd/patches/validation_in_linodemachines.yaml create mode 100644 config/crd/patches/validation_in_linodevpcs.yaml diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 6ced66145..b157b0957 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -35,6 +35,27 @@ patches: #- path: patches/cainjection_in_linodeobjectstoragebuckets.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch +# [VALIDATION] +# patches here are for additional validation for each CRD +- target: + group: apiextensions.k8s.io + version: v1 + kind: CustomResourceDefinition + name: linodeclusters.infrastructure.cluster.x-k8s.io + path: patches/validation_in_linodeclusters.yaml +- target: + group: apiextensions.k8s.io + version: v1 + kind: CustomResourceDefinition + name: linodemachines.infrastructure.cluster.x-k8s.io + path: patches/validation_in_linodemachines.yaml +- target: + group: apiextensions.k8s.io + version: v1 + kind: CustomResourceDefinition + name: linodevpcs.infrastructure.cluster.x-k8s.io + path: patches/validation_in_linodevpcs.yaml + # the following config is for teaching kustomize how to do kustomization for CRDs. configurations: - kustomizeconfig.yaml diff --git a/config/crd/patches/validation_in_linodeclusters.yaml b/config/crd/patches/validation_in_linodeclusters.yaml new file mode 100644 index 000000000..05e57e64e --- /dev/null +++ b/config/crd/patches/validation_in_linodeclusters.yaml @@ -0,0 +1,11 @@ +# The following patch adds additional constraints after the built-in name validation for the CRD +- op: add + path: /spec/versions/0/schema/openAPIV3Schema/properties/metadata/properties + value: + name: + type: string + x-kubernetes-validations: + - rule: 3 <= size(self) && size(self) <= 32 + message: >- + custom validation: + linode nodebalancer: labels must be between 3..32 characters diff --git a/config/crd/patches/validation_in_linodemachines.yaml b/config/crd/patches/validation_in_linodemachines.yaml new file mode 100644 index 000000000..75e986016 --- /dev/null +++ b/config/crd/patches/validation_in_linodemachines.yaml @@ -0,0 +1,26 @@ +# The following patch adds additional constraints after the built-in name validation for the CRD +- op: add + path: /spec/versions/0/schema/openAPIV3Schema/properties/metadata/properties + value: + name: + type: string + x-kubernetes-validations: + - rule: 3 <= size(self) && size(self) <= 64 + message: >- + custom validation: + linode instance: labels must be between 3..64 characters + - rule: self.matches('^[[:alnum:]]([-_.[:alnum:]]+[[:alnum:]])*$') + message: >- + custom validation: + linode instance: labels: + must begin and end with an alphanumeric character, + may only consist of alphanumeric characters, hyphens (-), underscores (_) or periods (.), + cannot have two hyphens (--), underscores (__) or periods (..) in a row, + regex used for validation is: '^[[:alnum:]]([-_.[:alnum:]]+[[:alnum:]])*$', + see: https://www.linode.com/docs/api/linode-instances/#linode-create + # TODO: Consider combining this into the regex above to minimize time complexity + # See: https://github.com/google/cel-spec/blob/master/doc/langdef.md#time-complexity + - rule: "!(self.contains('--') || self.contains('__') || self.contains('..'))" + message: >- + custom validation: + linode instance: labels cannot have two hyphens (--), underscores (__) or periods (..) in a row diff --git a/config/crd/patches/validation_in_linodevpcs.yaml b/config/crd/patches/validation_in_linodevpcs.yaml new file mode 100644 index 000000000..bd4442547 --- /dev/null +++ b/config/crd/patches/validation_in_linodevpcs.yaml @@ -0,0 +1,25 @@ +# The following patch adds additional constraints after the built-in name validation for the CRD +- op: add + path: /spec/versions/0/schema/openAPIV3Schema/properties/metadata/properties + value: + name: + type: string + x-kubernetes-validations: + - rule: 1 <= size(self) && size(self) <= 64 + message: >- + custom validation: + linode vpc: labels must be between 3..64 characters + - rule: self.matches('^[-[:alnum:]]*$') + message: >- + custom validation: + linode vpc: labels: + can only contain ASCII letters, numbers, and hyphens (-), + cannot have two consecutive hyphens (--), + regex used for validation is: '^[-[:alnum:]]*$', + see: https://www.linode.com/docs/api/vpcs/#vpc-create + # TODO: Consider combining this into the regex above to minimize time complexity + # See: https://github.com/google/cel-spec/blob/master/doc/langdef.md#time-complexity + - rule: "!self.contains('--')" + message: >- + custom validation: + linode vpc: labels cannot have two consecutive hyphens (--)