From c8160c6c9a3a51d93c4548ac1a30c75713bec76a Mon Sep 17 00:00:00 2001 From: John Howard Date: Tue, 27 Aug 2024 16:39:24 -0700 Subject: [PATCH 1/2] Add CEL validation to SE and WG --- kubernetes/customresourcedefinitions.gen.yaml | 224 ++++++++++++++++++ networking/v1/service_entry_alias.gen.go | 5 + networking/v1/workload_group_alias.gen.go | 1 + networking/v1alpha3/service_entry.pb.go | 19 ++ networking/v1alpha3/service_entry.proto | 19 +- networking/v1alpha3/sidecar.pb.go | 3 + networking/v1alpha3/sidecar.proto | 3 + networking/v1alpha3/workload_group.pb.go | 25 +- networking/v1alpha3/workload_group.pb.html | 2 +- networking/v1alpha3/workload_group.proto | 16 +- networking/v1beta1/service_entry_alias.gen.go | 5 + .../v1beta1/workload_group_alias.gen.go | 1 + tests/testdata/serviceentry-invalid.yaml | 159 +++++++++++++ tests/testdata/serviceentry-valid.yaml | 52 ++++ tests/testdata/workloadgroup-invalid.yaml | 31 +++ tests/testdata/workloadgroup-valid.yaml | 45 ++++ 16 files changed, 600 insertions(+), 10 deletions(-) create mode 100644 tests/testdata/serviceentry-invalid.yaml create mode 100644 tests/testdata/serviceentry-valid.yaml create mode 100644 tests/testdata/workloadgroup-invalid.yaml create mode 100644 tests/testdata/workloadgroup-valid.yaml diff --git a/kubernetes/customresourcedefinitions.gen.yaml b/kubernetes/customresourcedefinitions.gen.yaml index f3f4a4eb5f0..3473f1e18ab 100644 --- a/kubernetes/customresourcedefinitions.gen.yaml +++ b/kubernetes/customresourcedefinitions.gen.yaml @@ -6152,9 +6152,14 @@ spec: properties: labels: additionalProperties: + maxLength: 63 type: string + x-kubernetes-validations: + - message: wildcard is not supported in selector + rule: '!self.contains(''*'')' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. + maxProperties: 256 type: object type: object type: object @@ -7157,7 +7162,9 @@ spec: addresses: description: The virtual IP addresses associated with the service. items: + maxLength: 64 type: string + maxItems: 256 type: array endpoints: description: One or more endpoints associated with the service. @@ -7232,6 +7239,11 @@ spec: description: The hosts associated with the ServiceEntry. items: type: string + x-kubernetes-validations: + - message: hostname cannot be wildcard + rule: self != '*' + maxItems: 256 + minItems: 1 type: array location: description: |- @@ -7248,14 +7260,19 @@ spec: properties: name: description: Label assigned to the port. + maxLength: 256 type: string number: description: A valid non-negative integer port number. maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 protocol: description: The protocol exposed on the port. + maxLength: 256 type: string targetPort: description: The port number on the endpoint where the traffic @@ -7263,11 +7280,21 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 required: - number - name type: object + maxItems: 256 type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: port number cannot be duplicated + rule: self.all(l1, self.exists_one(l2, l1.number == l2.number)) resolution: description: |- Service resolution mode for the hosts. @@ -7290,14 +7317,32 @@ spec: properties: labels: additionalProperties: + maxLength: 63 type: string + x-kubernetes-validations: + - message: wildcard is not supported in selector + rule: '!self.contains(''*'')' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. + maxProperties: 256 type: object type: object required: - hosts type: object + x-kubernetes-validations: + - message: only one of WorkloadSelector or Endpoints can be set + rule: (has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1 + - message: CIDR addresses are allowed only for NONE/STATIC resolution + types + rule: '!(has(self.addresses) && self.addresses.exists(k, k.contains(''/'')) + && (self.resolution != ''STATIC'' && self.resolution != ''STATIC''))' + - message: NONE mode cannot set endpoints + rule: '(!has(self.resolution) || self.resolution == ''NONE'') ? !has(self.endpoints) + : true' + - message: DNS_ROUND_ROBIN mode cannot have multiple endpoints + rule: '(has(self.resolution) && self.resolution == ''DNS_ROUND_ROBIN'') + ? (!has(self.endpoints) || size(self.endpoints) == 1) : true' status: properties: conditions: @@ -7369,6 +7414,10 @@ spec: type: array type: object x-kubernetes-preserve-unknown-fields: true + required: + - spec + - spec + - spec type: object served: true storage: false @@ -7407,7 +7456,9 @@ spec: addresses: description: The virtual IP addresses associated with the service. items: + maxLength: 64 type: string + maxItems: 256 type: array endpoints: description: One or more endpoints associated with the service. @@ -7482,6 +7533,11 @@ spec: description: The hosts associated with the ServiceEntry. items: type: string + x-kubernetes-validations: + - message: hostname cannot be wildcard + rule: self != '*' + maxItems: 256 + minItems: 1 type: array location: description: |- @@ -7498,14 +7554,19 @@ spec: properties: name: description: Label assigned to the port. + maxLength: 256 type: string number: description: A valid non-negative integer port number. maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 protocol: description: The protocol exposed on the port. + maxLength: 256 type: string targetPort: description: The port number on the endpoint where the traffic @@ -7513,11 +7574,21 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 required: - number - name type: object + maxItems: 256 type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: port number cannot be duplicated + rule: self.all(l1, self.exists_one(l2, l1.number == l2.number)) resolution: description: |- Service resolution mode for the hosts. @@ -7540,14 +7611,32 @@ spec: properties: labels: additionalProperties: + maxLength: 63 type: string + x-kubernetes-validations: + - message: wildcard is not supported in selector + rule: '!self.contains(''*'')' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. + maxProperties: 256 type: object type: object required: - hosts type: object + x-kubernetes-validations: + - message: only one of WorkloadSelector or Endpoints can be set + rule: (has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1 + - message: CIDR addresses are allowed only for NONE/STATIC resolution + types + rule: '!(has(self.addresses) && self.addresses.exists(k, k.contains(''/'')) + && (self.resolution != ''STATIC'' && self.resolution != ''STATIC''))' + - message: NONE mode cannot set endpoints + rule: '(!has(self.resolution) || self.resolution == ''NONE'') ? !has(self.endpoints) + : true' + - message: DNS_ROUND_ROBIN mode cannot have multiple endpoints + rule: '(has(self.resolution) && self.resolution == ''DNS_ROUND_ROBIN'') + ? (!has(self.endpoints) || size(self.endpoints) == 1) : true' status: properties: conditions: @@ -7619,6 +7708,10 @@ spec: type: array type: object x-kubernetes-preserve-unknown-fields: true + required: + - spec + - spec + - spec type: object served: true storage: false @@ -7657,7 +7750,9 @@ spec: addresses: description: The virtual IP addresses associated with the service. items: + maxLength: 64 type: string + maxItems: 256 type: array endpoints: description: One or more endpoints associated with the service. @@ -7732,6 +7827,11 @@ spec: description: The hosts associated with the ServiceEntry. items: type: string + x-kubernetes-validations: + - message: hostname cannot be wildcard + rule: self != '*' + maxItems: 256 + minItems: 1 type: array location: description: |- @@ -7748,14 +7848,19 @@ spec: properties: name: description: Label assigned to the port. + maxLength: 256 type: string number: description: A valid non-negative integer port number. maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 protocol: description: The protocol exposed on the port. + maxLength: 256 type: string targetPort: description: The port number on the endpoint where the traffic @@ -7763,11 +7868,21 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 required: - number - name type: object + maxItems: 256 type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: port number cannot be duplicated + rule: self.all(l1, self.exists_one(l2, l1.number == l2.number)) resolution: description: |- Service resolution mode for the hosts. @@ -7790,14 +7905,32 @@ spec: properties: labels: additionalProperties: + maxLength: 63 type: string + x-kubernetes-validations: + - message: wildcard is not supported in selector + rule: '!self.contains(''*'')' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. + maxProperties: 256 type: object type: object required: - hosts type: object + x-kubernetes-validations: + - message: only one of WorkloadSelector or Endpoints can be set + rule: (has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1 + - message: CIDR addresses are allowed only for NONE/STATIC resolution + types + rule: '!(has(self.addresses) && self.addresses.exists(k, k.contains(''/'')) + && (self.resolution != ''STATIC'' && self.resolution != ''STATIC''))' + - message: NONE mode cannot set endpoints + rule: '(!has(self.resolution) || self.resolution == ''NONE'') ? !has(self.endpoints) + : true' + - message: DNS_ROUND_ROBIN mode cannot have multiple endpoints + rule: '(has(self.resolution) && self.resolution == ''DNS_ROUND_ROBIN'') + ? (!has(self.endpoints) || size(self.endpoints) == 1) : true' status: properties: conditions: @@ -7869,6 +8002,10 @@ spec: type: array type: object x-kubernetes-preserve-unknown-fields: true + required: + - spec + - spec + - spec type: object served: true storage: true @@ -8349,9 +8486,14 @@ spec: properties: labels: additionalProperties: + maxLength: 63 type: string + x-kubernetes-validations: + - message: wildcard is not supported in selector + rule: '!self.contains(''*'')' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. + maxProperties: 256 type: object type: object type: object @@ -8882,9 +9024,14 @@ spec: properties: labels: additionalProperties: + maxLength: 63 type: string + x-kubernetes-validations: + - message: wildcard is not supported in selector + rule: '!self.contains(''*'')' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. + maxProperties: 256 type: object type: object type: object @@ -9415,9 +9562,14 @@ spec: properties: labels: additionalProperties: + maxLength: 63 type: string + x-kubernetes-validations: + - message: wildcard is not supported in selector + rule: '!self.contains(''*'')' description: One or more labels that indicate a specific set of pods/VMs on which the configuration should be applied. + maxProperties: 256 type: object type: object type: object @@ -13178,10 +13330,12 @@ spec: annotations: additionalProperties: type: string + maxProperties: 256 type: object labels: additionalProperties: type: string + maxProperties: 256 type: object type: object probe: @@ -13210,13 +13364,17 @@ spec: command: description: Command to run. items: + minLength: 1 type: string type: array + required: + - command type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. format: int32 + minimum: 0 type: integer httpGet: description: '`httpGet` is performed to a given endpoint and the @@ -13231,6 +13389,7 @@ spec: items: properties: name: + pattern: ^[-_A-Za-z0-9]+$ type: string value: type: string @@ -13244,8 +13403,14 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 scheme: type: string + x-kubernetes-validations: + - message: scheme must be one of [HTTP, HTTPS] + rule: self in ['', 'HTTP', 'HTTPS'] required: - port type: object @@ -13253,15 +13418,18 @@ spec: description: Number of seconds after the container has started before readiness probes are initiated. format: int32 + minimum: 0 type: integer periodSeconds: description: How often (in seconds) to perform the probe. format: int32 + minimum: 0 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. format: int32 + minimum: 0 type: integer tcpSocket: description: Health is determined by if the proxy is able to connect. @@ -13272,12 +13440,16 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 required: - port type: object timeoutSeconds: description: Number of seconds after which the probe times out. format: int32 + minimum: 0 type: integer type: object template: @@ -13414,6 +13586,10 @@ spec: type: array type: object x-kubernetes-preserve-unknown-fields: true + required: + - spec + - spec + - spec type: object served: true storage: false @@ -13442,10 +13618,12 @@ spec: annotations: additionalProperties: type: string + maxProperties: 256 type: object labels: additionalProperties: type: string + maxProperties: 256 type: object type: object probe: @@ -13474,13 +13652,17 @@ spec: command: description: Command to run. items: + minLength: 1 type: string type: array + required: + - command type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. format: int32 + minimum: 0 type: integer httpGet: description: '`httpGet` is performed to a given endpoint and the @@ -13495,6 +13677,7 @@ spec: items: properties: name: + pattern: ^[-_A-Za-z0-9]+$ type: string value: type: string @@ -13508,8 +13691,14 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 scheme: type: string + x-kubernetes-validations: + - message: scheme must be one of [HTTP, HTTPS] + rule: self in ['', 'HTTP', 'HTTPS'] required: - port type: object @@ -13517,15 +13706,18 @@ spec: description: Number of seconds after the container has started before readiness probes are initiated. format: int32 + minimum: 0 type: integer periodSeconds: description: How often (in seconds) to perform the probe. format: int32 + minimum: 0 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. format: int32 + minimum: 0 type: integer tcpSocket: description: Health is determined by if the proxy is able to connect. @@ -13536,12 +13728,16 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 required: - port type: object timeoutSeconds: description: Number of seconds after which the probe times out. format: int32 + minimum: 0 type: integer type: object template: @@ -13678,6 +13874,10 @@ spec: type: array type: object x-kubernetes-preserve-unknown-fields: true + required: + - spec + - spec + - spec type: object served: true storage: false @@ -13706,10 +13906,12 @@ spec: annotations: additionalProperties: type: string + maxProperties: 256 type: object labels: additionalProperties: type: string + maxProperties: 256 type: object type: object probe: @@ -13738,13 +13940,17 @@ spec: command: description: Command to run. items: + minLength: 1 type: string type: array + required: + - command type: object failureThreshold: description: Minimum consecutive failures for the probe to be considered failed after having succeeded. format: int32 + minimum: 0 type: integer httpGet: description: '`httpGet` is performed to a given endpoint and the @@ -13759,6 +13965,7 @@ spec: items: properties: name: + pattern: ^[-_A-Za-z0-9]+$ type: string value: type: string @@ -13772,8 +13979,14 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 scheme: type: string + x-kubernetes-validations: + - message: scheme must be one of [HTTP, HTTPS] + rule: self in ['', 'HTTP', 'HTTPS'] required: - port type: object @@ -13781,15 +13994,18 @@ spec: description: Number of seconds after the container has started before readiness probes are initiated. format: int32 + minimum: 0 type: integer periodSeconds: description: How often (in seconds) to perform the probe. format: int32 + minimum: 0 type: integer successThreshold: description: Minimum consecutive successes for the probe to be considered successful after having failed. format: int32 + minimum: 0 type: integer tcpSocket: description: Health is determined by if the proxy is able to connect. @@ -13800,12 +14016,16 @@ spec: maximum: 4294967295 minimum: 0 type: integer + x-kubernetes-validations: + - message: port must be between 1-65535 + rule: 0 < self && self <= 65535 required: - port type: object timeoutSeconds: description: Number of seconds after which the probe times out. format: int32 + minimum: 0 type: integer type: object template: @@ -13942,6 +14162,10 @@ spec: type: array type: object x-kubernetes-preserve-unknown-fields: true + required: + - spec + - spec + - spec type: object served: true storage: true diff --git a/networking/v1/service_entry_alias.gen.go b/networking/v1/service_entry_alias.gen.go index f2c11e52ecc..6b3db9def83 100644 --- a/networking/v1/service_entry_alias.gen.go +++ b/networking/v1/service_entry_alias.gen.go @@ -24,6 +24,7 @@ import "istio.io/api/networking/v1alpha3" // Clients may not set this value. It is represented in RFC3339 form and is in UTC. // Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" // +cue-gen:ServiceEntry:preserveUnknownFields:false +// +cue-gen:ServiceEntry:spec:required // --> // // +// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'STATIC'))" +// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" +// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" type ServiceEntry = v1alpha3.ServiceEntry // Location specifies whether the service is part of Istio mesh or diff --git a/networking/v1/workload_group_alias.gen.go b/networking/v1/workload_group_alias.gen.go index e8483c3981b..db22cee916d 100644 --- a/networking/v1/workload_group_alias.gen.go +++ b/networking/v1/workload_group_alias.gen.go @@ -21,6 +21,7 @@ import "istio.io/api/networking/v1alpha3" // Clients may not set this value. It is represented in RFC3339 form and is in UTC. // Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" // +cue-gen:WorkloadGroup:preserveUnknownFields:false +// +cue-gen:WorkloadGroup:spec:required // --> // // // // +// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'STATIC'))" +// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" +// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" type ServiceEntry struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -621,6 +626,10 @@ type ServiceEntry struct { // 1. subjectAltNames: In addition to verifying the SANs of the // service accounts associated with the pods of the service, the // SANs specified here will also be verified. + // + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=256 + // +protoc-gen-crd:list-value-validation:XValidation:message="hostname cannot be wildcard",rule="self != '*'" Hosts []string `protobuf:"bytes,1,rep,name=hosts,proto3" json:"hosts,omitempty"` // The virtual IP addresses associated with the service. Could be CIDR // prefix. For HTTP traffic, generated route configurations will include http route @@ -636,10 +645,16 @@ type ServiceEntry struct { // simple TCP proxy, forwarding incoming traffic on a specified port to // the specified destination endpoint IP/host. Unix domain socket // addresses are not supported in this field. + // +kubebuilder:validation:MaxItems=256 + // +protoc-gen-crd:list-value-validation:MaxLength=64 Addresses []string `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"` // The ports associated with the external service. If the // Endpoints are Unix domain socket addresses, there must be exactly one // port. + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=256 + // +kubebuilder:validation:XValidation:message="port number cannot be duplicated",rule="self.all(l1, self.exists_one(l2, l1.number == l2.number))" Ports []*ServicePort `protobuf:"bytes,3,rep,name=ports,proto3" json:"ports,omitempty"` // Specify whether the service should be considered external to the mesh // or part of the mesh. @@ -789,16 +804,20 @@ type ServicePort struct { unknownFields protoimpl.UnknownFields // A valid non-negative integer port number. + // +kubebuilder:validation:XValidation:message="port must be between 1-65535",rule="0 < self && self <= 65535" Number uint32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"` // The protocol exposed on the port. // MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP|TLS. // TLS implies the connection will be routed based on the SNI header to // the destination without terminating the TLS connection. + // +kubebuilder:validation:MaxLength=256 Protocol string `protobuf:"bytes,2,opt,name=protocol,proto3" json:"protocol,omitempty"` // Label assigned to the port. + // +kubebuilder:validation:MaxLength=256 Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` // The port number on the endpoint where the traffic will be // received. If unset, default to `number`. + // +kubebuilder:validation:XValidation:message="port must be between 1-65535",rule="0 < self && self <= 65535" TargetPort uint32 `protobuf:"varint,4,opt,name=target_port,json=targetPort,proto3" json:"target_port,omitempty"` } diff --git a/networking/v1alpha3/service_entry.proto b/networking/v1alpha3/service_entry.proto index 671c060c518..bb97761213f 100644 --- a/networking/v1alpha3/service_entry.proto +++ b/networking/v1alpha3/service_entry.proto @@ -427,6 +427,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // Clients may not set this value. It is represented in RFC3339 form and is in UTC. // Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" // +cue-gen:ServiceEntry:preserveUnknownFields:false +// +cue-gen:ServiceEntry:spec:required // --> // // +// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'STATIC'))" +// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" +// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" message ServiceEntry { // The hosts associated with the ServiceEntry. Could be a DNS // name with wildcard prefix. @@ -460,7 +465,9 @@ message ServiceEntry { // 1. subjectAltNames: In addition to verifying the SANs of the // service accounts associated with the pods of the service, the // SANs specified here will also be verified. - // + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=256 + // +protoc-gen-crd:list-value-validation:XValidation:message="hostname cannot be wildcard",rule="self != '*'" repeated string hosts = 1 [(google.api.field_behavior) = REQUIRED]; // The virtual IP addresses associated with the service. Could be CIDR @@ -477,11 +484,17 @@ message ServiceEntry { // simple TCP proxy, forwarding incoming traffic on a specified port to // the specified destination endpoint IP/host. Unix domain socket // addresses are not supported in this field. + // +kubebuilder:validation:MaxItems=256 + // +protoc-gen-crd:list-value-validation:MaxLength=64 repeated string addresses = 2; // The ports associated with the external service. If the // Endpoints are Unix domain socket addresses, there must be exactly one // port. + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=256 + // +kubebuilder:validation:XValidation:message="port number cannot be duplicated",rule="self.all(l1, self.exists_one(l2, l1.number == l2.number))" repeated ServicePort ports = 3; // Location specifies whether the service is part of Istio mesh or @@ -600,19 +613,23 @@ message ServiceEntry { // ServicePort describes the properties of a specific port of a service. message ServicePort { // A valid non-negative integer port number. + // +kubebuilder:validation:XValidation:message="port must be between 1-65535",rule="0 < self && self <= 65535" uint32 number = 1 [(google.api.field_behavior) = REQUIRED]; // The protocol exposed on the port. // MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP|TLS. // TLS implies the connection will be routed based on the SNI header to // the destination without terminating the TLS connection. + // +kubebuilder:validation:MaxLength=256 string protocol = 2; // Label assigned to the port. + // +kubebuilder:validation:MaxLength=256 string name = 3 [(google.api.field_behavior) = REQUIRED]; // The port number on the endpoint where the traffic will be // received. If unset, default to `number`. + // +kubebuilder:validation:XValidation:message="port must be between 1-65535",rule="0 < self && self <= 65535" uint32 target_port = 4; } diff --git a/networking/v1alpha3/sidecar.pb.go b/networking/v1alpha3/sidecar.pb.go index 56229218779..5261d19b914 100644 --- a/networking/v1alpha3/sidecar.pb.go +++ b/networking/v1alpha3/sidecar.pb.go @@ -875,6 +875,9 @@ type WorkloadSelector struct { // on which the configuration should be applied. The scope of // label search is restricted to the configuration namespace in which the // the resource is present. + // +kubebuilder:validation:MaxProperties=256 + // +protoc-gen-crd:map-value-validation:MaxLength=63 + // +protoc-gen-crd:map-value-validation:XValidation:message="wildcard is not supported in selector",rule="!self.contains('*')" Labels map[string]string `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } diff --git a/networking/v1alpha3/sidecar.proto b/networking/v1alpha3/sidecar.proto index 9a9dba1d227..3b4bf7c072a 100644 --- a/networking/v1alpha3/sidecar.proto +++ b/networking/v1alpha3/sidecar.proto @@ -552,6 +552,9 @@ message WorkloadSelector { // on which the configuration should be applied. The scope of // label search is restricted to the configuration namespace in which the // the resource is present. + // +kubebuilder:validation:MaxProperties=256 + // +protoc-gen-crd:map-value-validation:MaxLength=63 + // +protoc-gen-crd:map-value-validation:XValidation:message="wildcard is not supported in selector",rule="!self.contains('*')" map labels = 1; // $hide_from_docs diff --git a/networking/v1alpha3/workload_group.pb.go b/networking/v1alpha3/workload_group.pb.go index 0477b36754a..3e8c8de413d 100644 --- a/networking/v1alpha3/workload_group.pb.go +++ b/networking/v1alpha3/workload_group.pb.go @@ -106,6 +106,7 @@ const ( // Clients may not set this value. It is represented in RFC3339 form and is in UTC. // Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" // +cue-gen:WorkloadGroup:preserveUnknownFields:false +// +cue-gen:WorkloadGroup:spec:required // --> // // // // // // +// +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'STATIC'))" +// +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" +// +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" type ServiceEntry = v1alpha3.ServiceEntry // Location specifies whether the service is part of Istio mesh or diff --git a/networking/v1beta1/workload_group_alias.gen.go b/networking/v1beta1/workload_group_alias.gen.go index a9f5c06aaf7..dfa27c04e6a 100644 --- a/networking/v1beta1/workload_group_alias.gen.go +++ b/networking/v1beta1/workload_group_alias.gen.go @@ -21,6 +21,7 @@ import "istio.io/api/networking/v1alpha3" // Clients may not set this value. It is represented in RFC3339 form and is in UTC. // Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" // +cue-gen:WorkloadGroup:preserveUnknownFields:false +// +cue-gen:WorkloadGroup:spec:required // --> // // // +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" -// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'STATIC'))" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'NONE'))" // +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" // +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" type ServiceEntry = v1alpha3.ServiceEntry diff --git a/networking/v1alpha3/service_entry.pb.go b/networking/v1alpha3/service_entry.pb.go index 658f9a9d569..faedec46bb4 100644 --- a/networking/v1alpha3/service_entry.pb.go +++ b/networking/v1alpha3/service_entry.pb.go @@ -595,7 +595,7 @@ func (ServiceEntry_Resolution) EnumDescriptor() ([]byte, []int) { // istiostatus-override: ServiceEntryStatus: istio.io/api/networking/v1alpha3 // --> // +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" -// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'STATIC'))" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'NONE'))" // +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" // +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" type ServiceEntry struct { diff --git a/networking/v1alpha3/service_entry.proto b/networking/v1alpha3/service_entry.proto index bb97761213f..9665fe512d9 100644 --- a/networking/v1alpha3/service_entry.proto +++ b/networking/v1alpha3/service_entry.proto @@ -438,7 +438,7 @@ option go_package = "istio.io/api/networking/v1alpha3"; // istiostatus-override: ServiceEntryStatus: istio.io/api/networking/v1alpha3 // --> // +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" -// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'STATIC'))" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'NONE'))" // +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" // +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" message ServiceEntry { diff --git a/networking/v1beta1/service_entry_alias.gen.go b/networking/v1beta1/service_entry_alias.gen.go index ca09548ddc2..afcac7c6a79 100644 --- a/networking/v1beta1/service_entry_alias.gen.go +++ b/networking/v1beta1/service_entry_alias.gen.go @@ -35,7 +35,7 @@ import "istio.io/api/networking/v1alpha3" // istiostatus-override: ServiceEntryStatus: istio.io/api/networking/v1alpha3 // --> // +kubebuilder:validation:XValidation:message="only one of WorkloadSelector or Endpoints can be set",rule="(has(self.workloadSelector)?1:0)+(has(self.endpoints)?1:0)<=1" -// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'STATIC'))" +// +kubebuilder:validation:XValidation:message="CIDR addresses are allowed only for NONE/STATIC resolution types",rule="!(has(self.addresses) && self.addresses.exists(k, k.contains('/')) && (self.resolution != 'STATIC' && self.resolution != 'NONE'))" // +kubebuilder:validation:XValidation:message="NONE mode cannot set endpoints",rule="(!has(self.resolution) || self.resolution == 'NONE') ? !has(self.endpoints) : true" // +kubebuilder:validation:XValidation:message="DNS_ROUND_ROBIN mode cannot have multiple endpoints",rule="(has(self.resolution) && self.resolution == 'DNS_ROUND_ROBIN') ? (!has(self.endpoints) || size(self.endpoints) == 1) : true" type ServiceEntry = v1alpha3.ServiceEntry