Skip to content

Commit

Permalink
tests: Add additional certmanager tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mikenairn committed Feb 19, 2024
1 parent 8d1f0fe commit dffcb1f
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 0 deletions.
259 changes: 259 additions & 0 deletions controllers/tlspolicy_certmanager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
//go:build unit

package controllers

import (
"testing"

"github.com/stretchr/testify/assert"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/utils/ptr"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)

// Helper function tests largely based on cert manager https://github.com/cert-manager/cert-manager/blob/master/pkg/controller/certificate-shim/sync_test.go
func Test_validateGatewayListenerBlock(t *testing.T) {
tests := []struct {
name string
ingLike metav1.Object
listener gatewayapiv1.Listener
wantErr string
}{
{
name: "empty TLS block",
ingLike: &gatewayapiv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "gateway",
Namespace: "default",
},
},
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
},
wantErr: "spec.listeners[0].tls: Required value: the TLS block cannot be empty",
},
{
name: "empty hostname",
ingLike: &gatewayapiv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "gateway",
Namespace: "default",
},
},
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
Mode: ptr.To(gatewayapiv1.TLSModeTerminate),
CertificateRefs: []gatewayapiv1.SecretObjectReference{
{
Group: func() *gatewayapiv1.Group { g := gatewayapiv1.Group("core"); return &g }(),
Kind: func() *gatewayapiv1.Kind { k := gatewayapiv1.Kind("Secret"); return &k }(),
Name: "example-com",
},
},
},
},
wantErr: "spec.listeners[0].hostname: Required value: the hostname cannot be empty",
},
{
name: "empty TLS CertificateRefs",
ingLike: &gatewayapiv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "gateway",
Namespace: "default",
},
},
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
CertificateRefs: []gatewayapiv1.SecretObjectReference{
{
Group: func() *gatewayapiv1.Group { g := gatewayapiv1.Group(""); return &g }(),
Kind: func() *gatewayapiv1.Kind { k := gatewayapiv1.Kind("Secret"); return &k }(),
Name: "example-com",
},
},
},
},
wantErr: "spec.listeners[0].tls.mode: Required value: the mode field is required",
},
{
name: "empty TLS Mode",
ingLike: &gatewayapiv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "gateway",
Namespace: "default",
},
},
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
Mode: ptr.To(gatewayapiv1.TLSModeTerminate),
CertificateRefs: []gatewayapiv1.SecretObjectReference{},
},
},
wantErr: "spec.listeners[0].tls.certificateRef: Required value: listener has no certificateRefs",
},
{
name: "unsupported TLS Mode",
ingLike: &gatewayapiv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "gateway",
Namespace: "default",
},
},
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
Mode: ptr.To(gatewayapiv1.TLSModePassthrough),
CertificateRefs: []gatewayapiv1.SecretObjectReference{
{
Group: func() *gatewayapiv1.Group { g := gatewayapiv1.Group(""); return &g }(),
Kind: func() *gatewayapiv1.Kind { k := gatewayapiv1.Kind("Secret"); return &k }(),
Name: "example-com",
},
},
},
},
wantErr: "spec.listeners[0].tls.mode: Unsupported value: \"Passthrough\": supported values: \"Terminate\"",
},
{
name: "empty group",
ingLike: &gatewayapiv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
},
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
Mode: ptr.To(gatewayapiv1.TLSModeTerminate),
CertificateRefs: []gatewayapiv1.SecretObjectReference{
{
Group: func() *gatewayapiv1.Group { g := gatewayapiv1.Group(""); return &g }(),
Kind: func() *gatewayapiv1.Kind { k := gatewayapiv1.Kind("Secret"); return &k }(),
Name: "example-com",
},
},
},
},
// no group is now supported
wantErr: "",
},
{
name: "unsupported group",
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
Mode: ptr.To(gatewayapiv1.TLSModeTerminate),
CertificateRefs: []gatewayapiv1.SecretObjectReference{
{
Group: func() *gatewayapiv1.Group { g := gatewayapiv1.Group("invalid"); return &g }(),
Kind: func() *gatewayapiv1.Kind { k := gatewayapiv1.Kind("Secret"); return &k }(),
Name: "example-com-tls",
},
},
},
},
wantErr: "spec.listeners[0].tls.certificateRef[0].group: Unsupported value: \"invalid\": supported values: \"core\", \"\"",
},
{
name: "unsupported kind",
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
Mode: ptr.To(gatewayapiv1.TLSModeTerminate),
CertificateRefs: []gatewayapiv1.SecretObjectReference{
{
Group: func() *gatewayapiv1.Group { g := gatewayapiv1.Group("core"); return &g }(),
Kind: func() *gatewayapiv1.Kind { k := gatewayapiv1.Kind("SomeOtherKind"); return &k }(),
Name: "example-com",
},
},
},
},
wantErr: "spec.listeners[0].tls.certificateRef[0].kind: Unsupported value: \"SomeOtherKind\": supported values: \"Secret\", \"\"",
},
{
name: "cross-namespace secret ref",
ingLike: &gatewayapiv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
},
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
Mode: ptr.To(gatewayapiv1.TLSModeTerminate),
CertificateRefs: []gatewayapiv1.SecretObjectReference{
{
Group: func() *gatewayapiv1.Group { g := gatewayapiv1.Group(""); return &g }(),
Kind: func() *gatewayapiv1.Kind { k := gatewayapiv1.Kind("Secret"); return &k }(),
Name: "example-com",
Namespace: func() *gatewayapiv1.Namespace { n := gatewayapiv1.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: &gatewayapiv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "another-namespace",
},
},
listener: gatewayapiv1.Listener{
Hostname: ptr.To(gatewayapiv1.Hostname("example.com")),
Port: gatewayapiv1.PortNumber(443),
Protocol: gatewayapiv1.HTTPSProtocolType,
TLS: &gatewayapiv1.GatewayTLSConfig{
Mode: ptr.To(gatewayapiv1.TLSModeTerminate),
CertificateRefs: []gatewayapiv1.SecretObjectReference{
{
Group: func() *gatewayapiv1.Group { g := gatewayapiv1.Group(""); return &g }(),
Kind: func() *gatewayapiv1.Kind { k := gatewayapiv1.Kind("Secret"); return &k }(),
Name: "example-com",
Namespace: func() *gatewayapiv1.Namespace { n := gatewayapiv1.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, test.ingLike).ToAggregate()
if test.wantErr == "" {
assert.NoError(t, gotErr)
} else {
assert.EqualError(t, gotErr, test.wantErr)
}
})
}
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/martinlindhe/base36 v1.1.1
github.com/onsi/ginkgo/v2 v2.13.2
github.com/onsi/gomega v1.30.0
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.26.0
golang.org/x/net v0.19.0
golang.org/x/sync v0.5.0
Expand Down Expand Up @@ -120,6 +121,7 @@ require (
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
Expand Down

0 comments on commit dffcb1f

Please sign in to comment.