Skip to content

Commit

Permalink
Issue kubernetes-sigs#1579 TLSRoute Passthrough Conformance Test (nor…
Browse files Browse the repository at this point in the history
…mative)
  • Loading branch information
candita committed Dec 8, 2022
1 parent b3c8e2a commit 70c6414
Show file tree
Hide file tree
Showing 13 changed files with 498 additions and 17 deletions.
62 changes: 62 additions & 0 deletions conformance/base/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,68 @@ spec:
cpu: 10m
---
apiVersion: v1
kind: Service
metadata:
name: infra-backend-v4
namespace: gateway-conformance-infra
spec:
selector:
app: infra-backend-v4
ports:
- protocol: TCP
port: 443
targetPort: 8443
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: infra-backend-v4
namespace: gateway-conformance-infra
labels:
app: infra-backend-v4
spec:
replicas: 2
selector:
matchLabels:
app: infra-backend-v4
template:
metadata:
labels:
app: infra-backend-v4
spec:
containers:
- name: infra-backend-v4
image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e
volumeMounts:
- name: secret-volume
mountPath: /etc/secret-volume
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: TLS_SERVER_CERT
value: /etc/secret-volume/crt
- name: TLS_SERVER_PRIVKEY
value: /etc/secret-volume/key
resources:
requests:
cpu: 10m
volumes:
- name: secret-volume
secret:
secretName: tls-passthrough-checks-certificate
items:
- key: tls.crt
path: crt
- key: tls.key
path: key
---
apiVersion: v1
kind: Namespace
metadata:
name: gateway-conformance-app-backend
Expand Down
9 changes: 7 additions & 2 deletions conformance/conformance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ func TestConformance(t *testing.T) {
v1alpha2.AddToScheme(client.Scheme())
v1beta1.AddToScheme(client.Scheme())

t.Logf("Running conformance tests with %s GatewayClass", *flags.GatewayClassName)

supportedFeatures := parseSupportedFeatures(*flags.SupportedFeatures)
exemptFeatures := parseSupportedFeatures(*flags.ExemptFeatures)
for feature := range exemptFeatures {
supportedFeatures[feature] = false
}
t.Logf("Running conformance tests with %s GatewayClass\n cleanup: %t\n debug: %t\n supported features: [%v]\n exempt features: [%v]",
*flags.GatewayClassName, *flags.CleanupBaseResources, *flags.ShowDebug, *flags.SupportedFeatures, *flags.ExemptFeatures)

cSuite := suite.New(suite.Options{
Client: client,
Expand All @@ -60,6 +60,11 @@ func TestConformance(t *testing.T) {
SupportedFeatures: supportedFeatures,
})
cSuite.Setup(t)
var debugCT []suite.ConformanceTest
debugCT = append(debugCT, tests.TLSRouteSimpleSameNamespace)
//debugCT = append(debugCT, tests.HTTPRouteHostnameIntersection)
//debugCT = append(debugCT, tests.HTTPRouteListenerHostnameMatching)
tests.ConformanceTests = debugCT
cSuite.Run(t, tests.ConformanceTests)
}

Expand Down
89 changes: 89 additions & 0 deletions conformance/tests/tlsroute-simple-same-namespace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
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/apis/v1beta1"
"sigs.k8s.io/gateway-api/conformance/utils/http"
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
"sigs.k8s.io/gateway-api/conformance/utils/suite"
"sigs.k8s.io/gateway-api/conformance/utils/tls"
)

func init() {
ConformanceTests = append(ConformanceTests, TLSRouteSimpleSameNamespace)
}

var TLSRouteSimpleSameNamespace = suite.ConformanceTest{
ShortName: "TLSRouteSimpleSameNamespace",
Description: "A single TLSRoute in the gateway-conformance-infra namespace attaches to a Gateway in the same namespace",
Manifests: []string{"tests/tlsroute-simple-same-namespace.yaml"},
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
ns := v1beta1.Namespace("gateway-conformance-infra")
routeNN := types.NamespacedName{Name: "gateway-conformance-infra-test", Namespace: string(ns)}
gwNN := types.NamespacedName{Name: "gateway-tlsroute", Namespace: string(ns)}
certNN := types.NamespacedName{Name: "tls-passthrough-checks-certificate", Namespace: string(ns)}

gwAddr, server := kubernetes.GatewayAndTLSRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
if len(server) != 1 {
fmt.Errorf("one and only one server required for TLS")
}
serverStr := string(server[0])

cPem, kPem, err := GetTLSSecret(suite.Client, certNN)
if err != nil {
fmt.Errorf("unexpected error finding TLS secret: %w", err)
}

t.Run("Simple HTTP request for TLSRoute should reach infra-backend", func(t *testing.T) {
tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, cPem, kPem, serverStr,
http.ExpectedResponse{
Request: http.Request{Host: serverStr, Path: "/"},
Backend: "infra-backend-v4",
Namespace: "gateway-conformance-infra",
})
})
},
}

// 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
}
35 changes: 35 additions & 0 deletions conformance/tests/tlsroute-simple-same-namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: gateway-conformance-infra-test
namespace: gateway-conformance-infra
spec:
parentRefs:
- name: gateway-tlsroute
namespace: gateway-conformance-infra
hostnames:
- abc.example.com
rules:
- backendRefs:
- name: infra-backend-v4
port: 443
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: gateway-tlsroute
namespace: gateway-conformance-infra
spec:
gatewayClassName: "{GATEWAY_CLASS_NAME}"
listeners:
- name: https
port: 443
protocol: TLS
hostname: "*.example.com"
allowedRoutes:
namespaces:
from: Same
kinds:
- kind: TLSRoute
tls:
mode: Passthrough
10 changes: 5 additions & 5 deletions conformance/utils/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ func MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, r roundtripp
WaitForConsistentResponse(t, r, req, expected, requiredConsecutiveSuccesses, timeoutConfig.MaxTimeToConsistency)
}

// awaitConvergence runs the given function until it returns 'true' `threshold` times in a row.
// AwaitConvergence runs the given function until it returns 'true' `threshold` times in a row.
// Each failed attempt has a 1s delay; successful attempts have no delay.
func awaitConvergence(t *testing.T, threshold int, maxTimeToConsistency time.Duration, fn func(elapsed time.Duration) bool) {
func AwaitConvergence(t *testing.T, threshold int, maxTimeToConsistency time.Duration, fn func(elapsed time.Duration) bool) {
successes := 0
attempts := 0
start := time.Now()
Expand Down Expand Up @@ -158,7 +158,7 @@ func awaitConvergence(t *testing.T, threshold int, maxTimeToConsistency time.Dur
select {
// Capture the overall timeout
case <-to:
t.Fatalf("timeout while waiting after %d attempts, %d/%d sucessess", attempts, successes, threshold)
t.Fatalf("timeout while waiting after %d attempts, %d/%d successes", attempts, successes, threshold)
// And the per-try delay
case <-time.After(delay):
}
Expand All @@ -169,7 +169,7 @@ func awaitConvergence(t *testing.T, threshold int, maxTimeToConsistency time.Dur
// the expected response consistently. The provided threshold determines how many times in
// a row this must occur to be considered "consistent".
func WaitForConsistentResponse(t *testing.T, r roundtripper.RoundTripper, req roundtripper.Request, expected ExpectedResponse, threshold int, maxTimeToConsistency time.Duration) {
awaitConvergence(t, threshold, maxTimeToConsistency, func(elapsed time.Duration) bool {
AwaitConvergence(t, threshold, maxTimeToConsistency, func(elapsed time.Duration) bool {
cReq, cRes, err := r.CaptureRoundTrip(req)
if err != nil {
t.Logf("Request failed, not ready yet: %v (after %v)", err.Error(), elapsed)
Expand Down Expand Up @@ -282,7 +282,7 @@ func CompareRequest(cReq *roundtripper.CapturedRequest, cRes *roundtripper.Captu
return nil
}

// Get User-defined test case name or generate from expected response to a given request.
// GetTestCaseName gets the user-defined test case name or generates one from expected response to a given request.
func (er *ExpectedResponse) GetTestCaseName(i int) string {

// If TestCase name is provided then use that or else generate one.
Expand Down
2 changes: 1 addition & 1 deletion conformance/utils/kubernetes/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func MustCreateSelfSignedCertSecret(t *testing.T, namespace, secretName string,
return newSecret
}

// generateRSACert generates a basic self signed certificate valir for a year
// generateRSACert generates a basic self signed certificate valid for a year
func generateRSACert(host string, keyOut, certOut io.Writer) error {
priv, err := rsa.GenerateKey(rand.Reader, rsaBits)
if err != nil {
Expand Down
Loading

0 comments on commit 70c6414

Please sign in to comment.