diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 7e7864ea3a..fa8db5faf4 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -374,6 +374,8 @@ const ( ) // GatewayTLSConfig describes a TLS configuration. +// +// +kubebuilder:validation:XValidation:message="certificateRefs or options must be specified when mode is Terminate",rule="self.mode == 'Terminate' ? size(self.certificateRefs) > 0 || size(self.options) > 0 : true" type GatewayTLSConfig struct { // Mode defines the TLS behavior for the TLS session initiated by the client. // There are two possible modes: diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index fa6b6faa51..dff81950cc 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -730,6 +730,11 @@ spec: maxProperties: 16 type: object type: object + x-kubernetes-validations: + - message: certificateRefs or options must be specified when + mode is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 || size(self.options) > 0 : true' required: - name - port @@ -1814,6 +1819,11 @@ spec: maxProperties: 16 type: object type: object + x-kubernetes-validations: + - message: certificateRefs or options must be specified when + mode is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 || size(self.options) > 0 : true' required: - name - port diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 66ec6c99da..17726b6404 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -672,6 +672,11 @@ spec: maxProperties: 16 type: object type: object + x-kubernetes-validations: + - message: certificateRefs or options must be specified when + mode is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 || size(self.options) > 0 : true' required: - name - port @@ -1698,6 +1703,11 @@ spec: maxProperties: 16 type: object type: object + x-kubernetes-validations: + - message: certificateRefs or options must be specified when + mode is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 || size(self.options) > 0 : true' required: - name - port diff --git a/pkg/test/cel/gateway_test.go b/pkg/test/cel/gateway_test.go index 6ebc55340d..ac6ba4e601 100644 --- a/pkg/test/cel/gateway_test.go +++ b/pkg/test/cel/gateway_test.go @@ -205,7 +205,7 @@ func TestValidateGateway(t *testing.T) { wantErrors: []string{"hostname must not be specified for protocols ['TCP', 'UDP']"}, }, { - desc: "certificateRefs not set with https protocol and TLS terminate mode", + desc: "certificateRefs not set with HTTPS protocol and TLS terminate mode", mutate: func(gw *gatewayv1.Gateway) { tlsMode := gatewayv1.TLSModeType("Terminate") gw.Spec.Listeners = []gatewayv1.Listener{ @@ -219,9 +219,10 @@ func TestValidateGateway(t *testing.T) { }, } }, + wantErrors: []string{"certificateRefs or options must be specified when mode is Terminate"}, }, { - desc: "certificateRefs not set with tls protocol and TLS terminate mode", + desc: "certificateRefs not set with TLS protocol and TLS terminate mode", mutate: func(gw *gatewayv1.Gateway) { tlsMode := gatewayv1.TLSModeType("Terminate") gw.Spec.Listeners = []gatewayv1.Listener{ @@ -235,9 +236,29 @@ func TestValidateGateway(t *testing.T) { }, } }, + wantErrors: []string{"certificateRefs or options must be specified when mode is Terminate"}, }, { - desc: "certificateRefs set with tls protocol and TLS terminate mode", + desc: "certificateRefs set with HTTPS protocol and TLS terminate mode", + mutate: func(gw *gatewayv1.Gateway) { + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners = []gatewayv1.Listener{ + { + Name: gatewayv1.SectionName("https"), + Protocol: gatewayv1.HTTPSProtocolType, + Port: gatewayv1.PortNumber(8443), + TLS: &gatewayv1.GatewayTLSConfig{ + Mode: &tlsMode, + CertificateRefs: []gatewayv1.SecretObjectReference{ + {Name: gatewayv1.ObjectName("foo")}, + }, + }, + }, + } + }, + }, + { + desc: "certificateRefs set with TLS protocol and TLS terminate mode", mutate: func(gw *gatewayv1.Gateway) { tlsMode := gatewayv1.TLSModeType("Terminate") gw.Spec.Listeners = []gatewayv1.Listener{ @@ -255,6 +276,44 @@ func TestValidateGateway(t *testing.T) { } }, }, + { + desc: "options set with HTTPS protocol and TLS terminate mode", + mutate: func(gw *gatewayv1.Gateway) { + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners = []gatewayv1.Listener{ + { + Name: gatewayv1.SectionName("https"), + Protocol: gatewayv1.HTTPSProtocolType, + Port: gatewayv1.PortNumber(8443), + TLS: &gatewayv1.GatewayTLSConfig{ + Mode: &tlsMode, + Options: map[gatewayv1.AnnotationKey]gatewayv1.AnnotationValue{ + "networking.example.com/tls-version": "1.2", + }, + }, + }, + } + }, + }, + { + desc: "options set with tls protocol and TLS terminate mode", + mutate: func(gw *gatewayv1.Gateway) { + tlsMode := gatewayv1.TLSModeType("Terminate") + gw.Spec.Listeners = []gatewayv1.Listener{ + { + Name: gatewayv1.SectionName("tls"), + Protocol: gatewayv1.TLSProtocolType, + Port: gatewayv1.PortNumber(8443), + TLS: &gatewayv1.GatewayTLSConfig{ + Mode: &tlsMode, + Options: map[gatewayv1.AnnotationKey]gatewayv1.AnnotationValue{ + "networking.example.com/tls-version": "1.2", + }, + }, + }, + } + }, + }, { desc: "names are not unique within the Gateway", mutate: func(gw *gatewayv1.Gateway) { diff --git a/site-src/guides/implementers.md b/site-src/guides/implementers.md index 2ede264f50..eed5e62ead 100644 --- a/site-src/guides/implementers.md +++ b/site-src/guides/implementers.md @@ -211,7 +211,7 @@ certificate stored by the external `vendor.example.com` TLS Certificate provider. #### 2. Automatically generated TLS certs that are populated later -Many users would prefer that TLS certs were automatically generated on their +Many users would prefer that TLS certs will be automatically generated on their behalf. One potential implementation of that would involve a controller that watches Gateways and HTTPRoutes, generates TLS certs, and attaches them to the Gateway. Depending on the implementation details, Gateway owners may need to