Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion conformance/tests/backendtlspolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,13 @@ var BackendTLSPolicy = confsuite.ConformanceTest{

// For the re-encrypt case, we need to use the cert for the frontend tls listener.
certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns}
serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
serverCertPem, _, err := kubernetes.GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(serverCertPem) == 0 {
t.Fatal("missing required server certificate pem for the test")
}
// Verify that the request to a re-encrypted call to /backendTLS should succeed.
tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, serverCertPem, nil, nil, "https-listener.org",
h.ExpectedResponse{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,13 @@ var GatewayFrontendInvalidDefaultClientCertificateValidation = confsuite.Conform

// Get Server certificate, this certificate is the same for both listeners
certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns}
serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
serverCertPem, _, err := kubernetes.GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(serverCertPem) == 0 {
t.Fatal("missing required server certificate pem for the test")
}

t.Run("Validate tls configuration does not impact HTTP listener", func(t *testing.T) {
expectedConditions := []metav1.Condition{
Expand Down
5 changes: 4 additions & 1 deletion conformance/tests/gateway-tls-backend-client-certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@ var GatewayTLSBackendClientCertificate = confsuite.ConformanceTest{
})

t.Run("HTTP request sent to Service using TLS should succeed and the configured client certificate should be presented.", func(t *testing.T) {
expectedClientCert, _, err := GetTLSSecret(suite.Client, types.NamespacedName{Name: "tls-checks-client-certificate", Namespace: ns})
expectedClientCert, _, err := kubernetes.GetTLSSecret(suite.Client, types.NamespacedName{Name: "tls-checks-client-certificate", Namespace: ns})
if err != nil {
t.Fatalf("unexpected error finding TLS client certifcate secret: %v", err)
}
if len(expectedClientCert) == 0 {
t.Fatal("missing required server certificate pem for the test")
}

h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr,
h.ExpectedResponse{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,33 @@ var GatewayFrontendClientCertificateValidationInsecureFallback = confsuite.Confo

// Get Server certificate, this certificate is the same for both listeners
certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns}
serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
serverCertPem, _, err := kubernetes.GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(serverCertPem) == 0 {
t.Fatal("missing required server certificate pem for the test")
}

// Get client certificate for default configuration
clientCertNN := types.NamespacedName{Name: "tls-validity-checks-client-certificate", Namespace: ns}
clientCertPem, clientCertKey, err := GetTLSSecret(suite.Client, clientCertNN)
clientCertPem, clientCertKey, err := kubernetes.GetTLSSecret(suite.Client, clientCertNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(clientCertPem) == 0 || len(clientCertKey) == 0 {
t.Fatal("missing required client certificate and private keypem for the test")
}

// Get client certificate for per port configuration
clientCertPerPortNN := types.NamespacedName{Name: "tls-validity-checks-per-port-client-certificate", Namespace: ns}
clientCertPerPortPem, clientCertPerPortKey, err := GetTLSSecret(suite.Client, clientCertPerPortNN)
clientCertPerPortPem, clientCertPerPortKey, err := kubernetes.GetTLSSecret(suite.Client, clientCertPerPortNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(clientCertPerPortPem) == 0 || len(clientCertPerPortKey) == 0 {
t.Fatal("missing required client certificate and private keypem for the test")
}

t.Run("Validate default TLS configuration", func(t *testing.T) {
defaultAddr := net.JoinHostPort(gwAddr, "443")
Expand Down
15 changes: 12 additions & 3 deletions conformance/tests/gateway-with-clientcertificate-validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,33 @@ var GatewayFrontendClientCertificateValidation = confsuite.ConformanceTest{

// Get Server certificate, this certificate is the same for both listeners
certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns}
serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
serverCertPem, _, err := kubernetes.GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(serverCertPem) == 0 {
t.Fatal("missing required server certificate pem for the test")
}

// Get client certificate for default configuration
clientCertNN := types.NamespacedName{Name: "tls-validity-checks-client-certificate", Namespace: ns}
clientCertPem, clientCertKey, err := GetTLSSecret(suite.Client, clientCertNN)
clientCertPem, clientCertKey, err := kubernetes.GetTLSSecret(suite.Client, clientCertNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(clientCertPem) == 0 || len(clientCertKey) == 0 {
t.Fatal("missing required client certificate and private keypem for the test")
}

// Get client certificate for per port configuration
clientCertPerPortNN := types.NamespacedName{Name: "tls-validity-checks-per-port-client-certificate", Namespace: ns}
clientCertPerPortPem, clientCertPerPortKey, err := GetTLSSecret(suite.Client, clientCertPerPortNN)
clientCertPerPortPem, clientCertPerPortKey, err := kubernetes.GetTLSSecret(suite.Client, clientCertPerPortNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(clientCertPerPortPem) == 0 || len(clientCertPerPortKey) == 0 {
t.Fatal("missing required client certificate and private keypem for the test")
}

t.Run("Validate default configuration", func(t *testing.T) {
defaultAddr := net.JoinHostPort(gwAddr, "443")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,13 @@ var HTTPRouteHTTPSListenerDetectMisdirectedRequests = confsuite.ConformanceTest{
}

certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns}
serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
serverCertPem, _, err := kubernetes.GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(serverCertPem) == 0 {
t.Fatal("missing required server certificate pem for the test")
}

cases := []struct {
host string
Expand Down
5 changes: 4 additions & 1 deletion conformance/tests/httproute-https-listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ var HTTPRouteHTTPSListener = confsuite.ConformanceTest{
kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNoHostNN, gwNN)

certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns}
serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
serverCertPem, _, err := kubernetes.GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(serverCertPem) == 0 {
t.Fatal("missing required server certificate pem for the test")
}

cases := []struct {
host string
Expand Down
5 changes: 4 additions & 1 deletion conformance/tests/httproute-redirect-port-and-scheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@ var HTTPRouteRedirectPortAndScheme = confsuite.ConformanceTest{
kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN)

certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns}
serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
serverCertPem, _, err := kubernetes.GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(serverCertPem) == 0 {
t.Fatal("missing required server certificate pem for the test")
}

// NOTE: In all the test cases, a missing value of expected Port within
// RedirectRequest implies that it is still valid and acceptable for a
Expand Down
5 changes: 4 additions & 1 deletion conformance/tests/tlsroute-hostname-intersection.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ var TLSRouteHostnameIntersection = confsuite.ConformanceTest{
// namespace so we have to wait for it to be ready.
kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns})

serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
serverCertPem, _, err := kubernetes.GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
if len(serverCertPem) == 0 {
t.Fatal("missing required server certificate pem for the test")
}

t.Run("TLSRoutes intersect with exact listener hostname", func(t *testing.T) {
routeNN := types.NamespacedName{Namespace: ns, Name: "tlsroute-more-specific-wc-hostname-x-1"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ var TLSRouteMixedTerminationSameNamespace = confsuite.ConformanceTest{
routePassthroughNN := types.NamespacedName{Name: "gateway-conformance-mixed-passthroughroute", Namespace: ns}
gwNN := types.NamespacedName{Name: "gateway-tlsroute-mixed-termination", Namespace: ns}
caCertNN := types.NamespacedName{Name: "tls-checks-ca-certificate", Namespace: ns}
certNN := types.NamespacedName{Name: "tls-passthrough-checks-certificate", Namespace: ns}

kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns})

Expand Down Expand Up @@ -109,11 +108,6 @@ var TLSRouteMixedTerminationSameNamespace = confsuite.ConformanceTest{
t.Fatalf("ca.crt not found in configmap: %s/%s", caCertNN.Namespace, caCertNN.Name)
}

serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}

t.Run("Simple TLS request matching terminated TLSRoute should reach tcp-backend unencrypted", func(t *testing.T) {
t.Parallel()

Expand All @@ -128,7 +122,7 @@ var TLSRouteMixedTerminationSameNamespace = confsuite.ConformanceTest{

t.Run("Simple TLS request matching TLSRoute Passthrough should reach infra-backend", func(t *testing.T) {
t.Parallel()
tcp.MakeTCPRequestAndExpectEventuallyValidResponse(t, suite.TimeoutConfig, gwAddr, serverCertPem, serverStrPassthrough, true,
tcp.MakeTCPRequestAndExpectEventuallyValidResponse(t, suite.TimeoutConfig, gwAddr, []byte(caString), serverStrPassthrough, true,
tcp.ExpectedResponse{
BackendIsTLS: true, // Passthrough expects a TLS Backend
Backend: "tcp-backend",
Expand Down
34 changes: 8 additions & 26 deletions conformance/tests/tlsroute-simple-same-namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,9 @@ limitations under the License.
package tests

import (
"context"
"fmt"
"testing"
"time"

v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
confsuite "sigs.k8s.io/gateway-api/conformance/utils/suite"
Expand All @@ -48,7 +43,7 @@ var TLSRouteSimpleSameNamespace = confsuite.ConformanceTest{
ns := confsuite.InfrastructureNamespace
routeNN := types.NamespacedName{Name: confsuite.InfrastructureGatewayName, Namespace: ns}
gwNN := types.NamespacedName{Name: "gateway-tlsroute", Namespace: ns}
certNN := types.NamespacedName{Name: "tls-passthrough-checks-certificate", Namespace: ns}
caCertNN := types.NamespacedName{Name: "tls-checks-ca-certificate", Namespace: ns}

kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns})

Expand All @@ -58,12 +53,17 @@ var TLSRouteSimpleSameNamespace = confsuite.ConformanceTest{
}
serverStr := string(hostnames[0])

serverCertPem, _, err := GetTLSSecret(suite.Client, certNN)
caConfigMap, err := kubernetes.GetConfigMapData(suite.Client, suite.TimeoutConfig, caCertNN)
if err != nil {
t.Fatalf("unexpected error finding TLS secret: %v", err)
}
caString, ok := caConfigMap["ca.crt"]
if !ok {
t.Fatalf("ca.crt not found in configmap: %s/%s", caCertNN.Namespace, caCertNN.Name)
}

t.Run("Simple TLS request matching TLSRoute should reach infra-backend", func(t *testing.T) {
tcp.MakeTCPRequestAndExpectEventuallyValidResponse(t, suite.TimeoutConfig, gwAddr, serverCertPem, serverStr, true,
tcp.MakeTCPRequestAndExpectEventuallyValidResponse(t, suite.TimeoutConfig, gwAddr, []byte(caString), serverStr, true,
tcp.ExpectedResponse{
BackendIsTLS: true, // Passthrough expects a TLS Backend
Backend: "tcp-backend",
Expand All @@ -73,21 +73,3 @@ var TLSRouteSimpleSameNamespace = confsuite.ConformanceTest{
})
},
}

// GetTLSSecret fetches the named Secret and converts both cert and key to []byte
func GetTLSSecret(client client.Client, secretName types.NamespacedName) ([]byte, []byte, error) {
var cert, key []byte

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

secret := &v1.Secret{}
err := client.Get(ctx, secretName, secret)
if err != nil {
return cert, key, fmt.Errorf("error fetching TLS Secret: %w", err)
}
cert = secret.Data["tls.crt"]
key = secret.Data["tls.key"]

return cert, key, nil
}
22 changes: 22 additions & 0 deletions conformance/utils/kubernetes/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package kubernetes

import (
"bytes"
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
Expand All @@ -34,8 +35,11 @@ import (

"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
kvalidation "k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
Expand Down Expand Up @@ -260,3 +264,21 @@ func validateHost(host string) error {
}
return nil
}

// GetTLSSecret fetches the named Secret and converts both cert and key to []byte
func GetTLSSecret(client client.Client, secretName types.NamespacedName) ([]byte, []byte, error) {
var cert, key []byte

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

secret := &v1.Secret{}
err := client.Get(ctx, secretName, secret)
if err != nil {
return cert, key, fmt.Errorf("error fetching TLS Secret: %w", err)
}
cert = secret.Data["tls.crt"]
key = secret.Data["tls.key"]

return cert, key, nil
}
10 changes: 6 additions & 4 deletions conformance/utils/suite/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,17 +397,19 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest)
secret = kubernetes.MustCreateCASignedClientCertSecret(t, InfrastructureNamespace, "tls-validity-checks-per-port-client-certificate", ca, caPrivKey)
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)

secret = kubernetes.MustCreateSelfSignedCertSecret(t, InfrastructureNamespace, "tls-passthrough-checks-certificate", []string{"abc.example.com"})
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
secret = kubernetes.MustCreateSelfSignedCertSecret(t, AppBackendNamespace, "tls-passthrough-checks-certificate", []string{"abc.example.com"})
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
caConfigMap, ca, caPrivKey = kubernetes.MustCreateCACertConfigMap(t, InfrastructureNamespace, "tls-checks-ca-certificate")
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup)
secret = kubernetes.MustCreateCASignedCertSecret(t, InfrastructureNamespace, "tls-checks-certificate", []string{"abc.example.com", "spiffe://abc.example.com/test-identity", "other.example.com"}, ca, caPrivKey)
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
secret = kubernetes.MustCreateCASignedClientCertSecret(t, InfrastructureNamespace, "tls-checks-client-certificate", ca, caPrivKey)
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)

// Secret used for tcp-backend serving TLS
secret = kubernetes.MustCreateCASignedCertSecret(t, InfrastructureNamespace, "tls-passthrough-checks-certificate", []string{"abc.example.com"}, ca, caPrivKey)
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
secret = kubernetes.MustCreateCASignedCertSecret(t, AppBackendNamespace, "tls-passthrough-checks-certificate", []string{"abc.example.com"}, ca, caPrivKey)
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)

// The following secret is used for TLSRoute mode Terminate validation
secret = kubernetes.MustCreateCASignedCertSecret(t, InfrastructureNamespace, "tls-terminate-checks-certificate", []string{"tls.example.com"}, ca, caPrivKey)
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
Expand Down