Return error when Gateway has a cross-namespace secret ref

Signed-off-by: Martín Montes <martin11lrx@gmail.com>
This commit is contained in:
Martín Montes 2022-12-01 12:42:14 +01:00
parent 77c410f5cb
commit f884dac555
2 changed files with 79 additions and 3 deletions

View File

@ -239,7 +239,7 @@ func validateIngressTLSBlock(path *field.Path, tlsBlock networkingv1.IngressTLS)
return errs
}
func validateGatewayListenerBlock(path *field.Path, l gwapi.Listener) field.ErrorList {
func validateGatewayListenerBlock(path *field.Path, l gwapi.Listener, ingLike metav1.Object) field.ErrorList {
var errs field.ErrorList
if l.Hostname == nil || *l.Hostname == "" {
@ -266,6 +266,11 @@ func validateGatewayListenerBlock(path *field.Path, l gwapi.Listener) field.Erro
errs = append(errs, field.NotSupported(path.Child("tls").Child("certificateRef").Index(i).Child("kind"),
*secretRef.Kind, []string{"Secret", ""}))
}
if secretRef.Namespace != nil && string(*secretRef.Namespace) != ingLike.GetNamespace() {
errs = append(errs, field.Invalid(path.Child("tls").Child("certificateRef").Index(i).Child("namespace"),
*secretRef.Namespace, "cross-namespace secret references are not allowed in listeners"))
}
}
}
@ -310,7 +315,7 @@ func buildCertificates(
}
case *gwapi.Gateway:
for i, l := range ingLike.Spec.Listeners {
err := validateGatewayListenerBlock(field.NewPath("spec", "listeners").Index(i), l).ToAggregate()
err := validateGatewayListenerBlock(field.NewPath("spec", "listeners").Index(i), l, ingLike).ToAggregate()
if err != nil {
rec.Eventf(ingLike, corev1.EventTypeWarning, reasonBadConfig, "Skipped a listener block: "+err.Error())
continue

View File

@ -3039,11 +3039,18 @@ func ptrMode(mode gwapi.TLSModeType) *gwapi.TLSModeType {
func Test_validateGatewayListenerBlock(t *testing.T) {
tests := []struct {
name string
ingLike metav1.Object
listener gwapi.Listener
wantErr string
}{
{
name: "empty TLS block",
ingLike: &gwapi.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "gateway",
Namespace: "default",
},
},
listener: gwapi.Listener{
Hostname: ptrHostname("example.com"),
Port: gwapi.PortNumber(443),
@ -3053,6 +3060,12 @@ func Test_validateGatewayListenerBlock(t *testing.T) {
},
{
name: "empty hostname",
ingLike: &gwapi.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "gateway",
Namespace: "default",
},
},
listener: gwapi.Listener{
Hostname: ptrHostname(""),
Port: gwapi.PortNumber(443),
@ -3072,6 +3085,12 @@ func Test_validateGatewayListenerBlock(t *testing.T) {
},
{
name: "empty group",
ingLike: &gwapi.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
},
listener: gwapi.Listener{
Hostname: ptrHostname("example.com"),
Port: gwapi.PortNumber(443),
@ -3128,10 +3147,62 @@ func Test_validateGatewayListenerBlock(t *testing.T) {
},
wantErr: "spec.listeners[0].tls.certificateRef[0].kind: Unsupported value: \"SomeOtherKind\": supported values: \"Secret\", \"\"",
},
{
name: "cross-namespace secret ref",
ingLike: &gwapi.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
},
listener: gwapi.Listener{
Hostname: ptrHostname("example.com"),
Port: gwapi.PortNumber(443),
Protocol: gwapi.HTTPSProtocolType,
TLS: &gwapi.GatewayTLSConfig{
Mode: ptrMode(gwapi.TLSModeTerminate),
CertificateRefs: []gwapi.SecretObjectReference{
{
Group: func() *gwapi.Group { g := gwapi.Group(""); return &g }(),
Kind: func() *gwapi.Kind { k := gwapi.Kind("Secret"); return &k }(),
Name: "example-com",
Namespace: func() *gwapi.Namespace { n := gwapi.Namespace("another-namespace"); return &n }(),
},
},
},
},
wantErr: "spec.listeners[0].tls.certificateRef[0].namespace: Invalid value: \"another-namespace\": cross-namespace secret references are not allowed in listeners",
},
{
name: "same namespace secret ref",
ingLike: &gwapi.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "another-namespace",
},
},
listener: gwapi.Listener{
Hostname: ptrHostname("example.com"),
Port: gwapi.PortNumber(443),
Protocol: gwapi.HTTPSProtocolType,
TLS: &gwapi.GatewayTLSConfig{
Mode: ptrMode(gwapi.TLSModeTerminate),
CertificateRefs: []gwapi.SecretObjectReference{
{
Group: func() *gwapi.Group { g := gwapi.Group(""); return &g }(),
Kind: func() *gwapi.Kind { k := gwapi.Kind("Secret"); return &k }(),
Name: "example-com",
Namespace: func() *gwapi.Namespace { n := gwapi.Namespace("another-namespace"); return &n }(),
},
},
},
},
wantErr: "",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
gotErr := validateGatewayListenerBlock(field.NewPath("spec", "listeners").Index(0), test.listener).ToAggregate()
gotErr := validateGatewayListenerBlock(field.NewPath("spec", "listeners").Index(0), test.listener, test.ingLike).ToAggregate()
if test.wantErr == "" {
assert.NoError(t, gotErr)
} else {