From 9b6e45e61d9cc5c22a5de340ff1fd4af736bb8a2 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Mon, 22 Jan 2024 18:36:46 -0800 Subject: [PATCH] api: downstream client CACert validation (#2483) * api: downstream client CACert validation Relates to https://github.com/envoyproxy/gateway/issues/88 Signed-off-by: Arko Dasgupta * docs Signed-off-by: Arko Dasgupta * lint Signed-off-by: Arko Dasgupta * charts Signed-off-by: Arko Dasgupta --------- Signed-off-by: Arko Dasgupta --- api/v1alpha1/tls_types.go | 30 +++++++ api/v1alpha1/zz_generated.deepcopy.go | 25 ++++++ ...y.envoyproxy.io_clienttrafficpolicies.yaml | 83 +++++++++++++++++++ site/content/en/latest/api/extension_types.md | 17 ++++ 4 files changed, 155 insertions(+) diff --git a/api/v1alpha1/tls_types.go b/api/v1alpha1/tls_types.go index 250d1189f10..d6eb14c638f 100644 --- a/api/v1alpha1/tls_types.go +++ b/api/v1alpha1/tls_types.go @@ -5,6 +5,10 @@ package v1alpha1 +import ( + corev1 "k8s.io/api/core/v1" +) + // +kubebuilder:validation:XValidation:rule="has(self.minVersion) && self.minVersion == '1.3' ? !has(self.ciphers) : true", message="setting ciphers has no effect if the minimum possible TLS version is 1.3" // +kubebuilder:validation:XValidation:rule="has(self.minVersion) && has(self.maxVersion) ? {\"Auto\":0,\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4}[self.minVersion] <= {\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4,\"Auto\":5}[self.maxVersion] : !has(self.minVersion) && has(self.maxVersion) ? 3 <= {\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4,\"Auto\":5}[self.maxVersion] : true", message="minVersion must be smaller or equal to maxVersion" type TLSSettings struct { @@ -62,6 +66,11 @@ type TLSSettings struct { // // +optional ALPNProtocols []ALPNProtocol `json:"alpnProtocols,omitempty"` + + // ClientValidation specifies the configuration to validate the client + // initiating the TLS connection to the Gateway listener. + // +optional + ClientValidation *ClientValidationContext `json:"clientValidation,omitempty"` } // ALPNProtocol specifies the protocol to be negotiated using ALPN @@ -96,3 +105,24 @@ const ( // TLSv1.3 specifies TLS version 1.3 TLSv13 TLSVersion = "1.3" ) + +// ClientValidationContext holds configuration that can be used to validate the client initiating the TLS connection +// to the Gateway. +// By default, no client specific configuration is validated. +type ClientValidationContext struct { + // CACertificateRefs contains one or more references to + // Kubernetes objects that contain TLS certificates of + // the Certificate Authorities that can be used + // as a trust anchor to validate the certificates presented by the client. + // + // A single reference to a Kubernetes ConfigMap, + // with the CA certificate in a key named `ca.crt` is currently supported. + // + // References to a resource in different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. + // + // +kubebuilder:validation:MaxItems=8 + // +optional + CACertificateRefs []corev1.ObjectReference `json:"caCertificateRefs,omitempty"` +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index a8656454589..d9eadf8c2ee 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -388,6 +388,26 @@ func (in *ClientTrafficPolicyStatus) DeepCopy() *ClientTrafficPolicyStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientValidationContext) DeepCopyInto(out *ClientValidationContext) { + *out = *in + if in.CACertificateRefs != nil { + in, out := &in.CACertificateRefs, &out.CACertificateRefs + *out = make([]corev1.ObjectReference, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientValidationContext. +func (in *ClientValidationContext) DeepCopy() *ClientValidationContext { + if in == nil { + return nil + } + out := new(ClientValidationContext) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConsistentHash) DeepCopyInto(out *ConsistentHash) { *out = *in @@ -2893,6 +2913,11 @@ func (in *TLSSettings) DeepCopyInto(out *TLSSettings) { *out = make([]ALPNProtocol, len(*in)) copy(*out, *in) } + if in.ClientValidation != nil { + in, out := &in.ClientValidation, &out.ClientValidation + *out = new(ClientValidationContext) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSettings. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index 7267fb6c874..505683d5c8a 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -187,6 +187,89 @@ spec: items: type: string type: array + clientValidation: + description: ClientValidation specifies the configuration to validate + the client initiating the TLS connection to the Gateway listener. + properties: + caCertificateRefs: + description: "CACertificateRefs contains one or more references + to Kubernetes objects that contain TLS certificates of the + Certificate Authorities that can be used as a trust anchor + to validate the certificates presented by the client. \n + A single reference to a Kubernetes ConfigMap, with the CA + certificate in a key named `ca.crt` is currently supported. + \n References to a resource in different namespace are invalid + UNLESS there is a ReferenceGrant in the target namespace + that allows the certificate to be attached." + items: + description: "ObjectReference contains enough information + to let you inspect or modify the referred object. --- + New uses of this type are discouraged because of difficulty + describing its usage when embedded in APIs. 1. Ignored + fields. It includes many fields which are not generally + honored. For instance, ResourceVersion and FieldPath + are both very rarely valid in actual usage. 2. Invalid + usage help. It is impossible to add specific help for + individual usage. In most embedded usages, there are + particular restrictions like, \"must refer only to types + A and B\" or \"UID not honored\" or \"name must be restricted\". + Those cannot be well described when embedded. 3. Inconsistent + validation. Because the usages are different, the validation + rules are different by usage, which makes it hard for + users to predict what will happen. 4. The fields are both + imprecise and overly precise. Kind is not a precise mapping + to a URL. This can produce ambiguity during interpretation + and require a REST mapping. In most cases, the dependency + is on the group,resource tuple and the version of the + actual struct is irrelevant. 5. We cannot easily change + it. Because this type is embedded in many locations, + updates to this type will affect numerous schemas. Don't + make new APIs embed an underspecified API type they do + not control. \n Instead of using this type, create a locally + provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: + https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 + ." + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead + of an entire object, this string should contain a + valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container + within a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container + that triggered the event) or if no container name + is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to + have some well-defined way of referencing a part of + an object. TODO: this design is not final and this + field is subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this + reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + x-kubernetes-map-type: atomic + maxItems: 8 + type: array + type: object ecdhCurves: description: 'ECDHCurves specifies the set of supported ECDH curves. In non-FIPS Envoy Proxy builds the default curves are: - X25519 diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 121e935bde4..836b58afc2f 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -227,6 +227,22 @@ _Appears in:_ +#### ClientValidationContext + + + +ClientValidationContext holds configuration that can be used to validate the client initiating the TLS connection to the Gateway. By default, no client specific configuration is validated. + +_Appears in:_ +- [TLSSettings](#tlssettings) + +| Field | Description | +| --- | --- | +| `caCertificateRefs` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectreference-v1-core) array_ | CACertificateRefs contains one or more references to Kubernetes objects that contain TLS certificates of the Certificate Authorities that can be used as a trust anchor to validate the certificates presented by the client. + A single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt` is currently supported. + References to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. | + + #### ConsistentHash @@ -2073,6 +2089,7 @@ _Appears in:_ | `ecdhCurves` _string array_ | ECDHCurves specifies the set of supported ECDH curves. In non-FIPS Envoy Proxy builds the default curves are: - X25519 - P-256 In builds using BoringSSL FIPS the default curve is: - P-256 | | `signatureAlgorithms` _string array_ | SignatureAlgorithms specifies which signature algorithms the listener should support. | | `alpnProtocols` _[ALPNProtocol](#alpnprotocol) array_ | ALPNProtocols supplies the list of ALPN protocols that should be exposed by the listener. By default h2 and http/1.1 are enabled. Supported values are: - http/1.0 - http/1.1 - h2 | +| `clientValidation` _[ClientValidationContext](#clientvalidationcontext)_ | ClientValidation specifies the configuration to validate the client initiating the TLS connection to the Gateway listener. | #### TLSVersion