Skip to content

Commit

Permalink
test: allow specifying HTTP protocol (#822)
Browse files Browse the repository at this point in the history
Signed-off-by: spacewander <spacewanderlzx@gmail.com>
  • Loading branch information
spacewander authored Feb 20, 2024
1 parent ae20420 commit f277d4f
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 4 deletions.
64 changes: 64 additions & 0 deletions test/e2e/conformance/tests/go-wasm-sni-misdirect.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,70 @@ var WasmPluginsSniMisdirect = suite.ConformanceTest{
},
},
},
{
Meta: http.AssertionMeta{
TestCaseName: "case 3: https/2.0 request with sni and same with host",
TargetBackend: "infra-backend-v1",
TargetNamespace: "higress-conformance-infra",
},
Request: http.AssertionRequest{
ActualRequest: http.Request{
Protocol: "HTTP/2.0",
Host: "foo.com",
Path: "/foo",
Headers: map[string]string{
"Content-Type": "text/plain",
},
TLSConfig: &http.TLSConfig{
SNI: "foo.com",
Certificates: http.Certificates{
CACerts: [][]byte{caCertOut.Bytes()},
ClientKeyPairs: []http.ClientKeyPair{{
ClientCert: cliCertOut.Bytes(),
ClientKey: cliKeyOut.Bytes()},
},
},
},
},
},
Response: http.AssertionResponse{
ExpectedResponse: http.Response{
StatusCode: 200,
},
},
},
{
Meta: http.AssertionMeta{
TestCaseName: "case 4: https/2.0 request with sni and not same with host",
TargetBackend: "infra-backend-v1",
TargetNamespace: "higress-conformance-infra",
},
Request: http.AssertionRequest{
ActualRequest: http.Request{
Protocol: "HTTP/2.0",
Host: "bar.com",
Path: "/foo",
Headers: map[string]string{
"Content-Type": "text/plain",
},
TLSConfig: &http.TLSConfig{
SNI: "foo.com",
Certificates: http.Certificates{
CACerts: [][]byte{caCertOut.Bytes()},
ClientKeyPairs: []http.ClientKeyPair{{
ClientCert: cliCertOut.Bytes(),
ClientKey: cliKeyOut.Bytes()},
},
},
},
},
},
Response: http.AssertionResponse{
ExpectedResponse: http.Response{
StatusCode: 421,
},
},
},
}

t.Run("WasmPlugin sni-misdirect", func(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/conformance/tests/go-wasm-sni-misdirect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ spec:
ingressClassName: higress
tls:
- hosts:
- "foo.com"
- "*.com"
secretName: foo-secret
rules:
- host: "foo.com"
- host: "*.com"
http:
paths:
- pathType: Exact
Expand Down
8 changes: 6 additions & 2 deletions test/e2e/conformance/utils/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const (
// values can be provided, as a comma-separated value.
type Request struct {
Host string
Protocol string
Method string
Path string
Headers map[string]string
Expand Down Expand Up @@ -162,12 +163,10 @@ func MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, r roundtripp

var (
scheme = "http"
protocol = "HTTP"
tlsConfig *roundtripper.TLSConfig
)
if expected.Request.ActualRequest.TLSConfig != nil {
scheme = "https"
protocol = "HTTPS"
clientKeyPairs := make([]roundtripper.ClientKeyPair, 0, len(expected.Request.ActualRequest.TLSConfig.Certificates.ClientKeyPairs))
for _, keyPair := range expected.Request.ActualRequest.TLSConfig.Certificates.ClientKeyPairs {
clientKeyPairs = append(clientKeyPairs, roundtripper.ClientKeyPair{
Expand Down Expand Up @@ -213,6 +212,11 @@ func MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, r roundtripp

path, query, _ := strings.Cut(expected.Request.ActualRequest.Path, "?")

protocol := "HTTP/1.1"
if expected.Request.ActualRequest.Protocol != "" {
protocol = expected.Request.ActualRequest.Protocol
}

req := roundtripper.Request{
Method: expected.Request.ActualRequest.Method,
Host: expected.Request.ActualRequest.Host,
Expand Down
51 changes: 51 additions & 0 deletions test/e2e/conformance/utils/roundtripper/roundtripper.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"net/url"
"regexp"

"golang.org/x/net/http2"

"github.com/alibaba/higress/test/e2e/conformance/utils/config"
)

Expand Down Expand Up @@ -109,6 +111,53 @@ type DefaultRoundTripper struct {
TimeoutConfig config.TimeoutConfig
}

func (d *DefaultRoundTripper) initTransport(client *http.Client, protocol string, tlsConfig *TLSConfig) error {
var tlsClientConfig *tls.Config
if tlsConfig != nil {
pool := x509.NewCertPool()
for _, caCert := range tlsConfig.Certificates.CACert {
pool.AppendCertsFromPEM(caCert)
}
var clientCerts []tls.Certificate
for _, keyPair := range tlsConfig.Certificates.ClientKeyPairs {
newClientCert, err := tls.X509KeyPair(keyPair.ClientCert, keyPair.ClientKey)
if err != nil {
return fmt.Errorf("failed to load client key pair: %w", err)
}
clientCerts = append(clientCerts, newClientCert)
}

tlsClientConfig = &tls.Config{
MinVersion: tlsConfig.MinVersion,
MaxVersion: tlsConfig.MaxVersion,
ServerName: tlsConfig.SNI,
CipherSuites: tlsConfig.CipherSuites,
RootCAs: pool,
Certificates: clientCerts,
InsecureSkipVerify: true,
}
}

switch protocol {
case "HTTP/2.0":
tr := &http2.Transport{}
if tlsClientConfig != nil {
tr.TLSClientConfig = tlsClientConfig
}
client.Transport = tr
default: // HTTP1
if tlsClientConfig != nil {
client.Transport = &http.Transport{
TLSHandshakeTimeout: d.TimeoutConfig.TLSHandshakeTimeout,
DisableKeepAlives: true,
TLSClientConfig: tlsClientConfig,
}
}
}

return nil
}

// CaptureRoundTrip makes a request with the provided parameters and returns the
// captured request and response from echoserver. An error will be returned if
// there is an error running the function but not if an HTTP error status code
Expand Down Expand Up @@ -152,6 +201,8 @@ func (d *DefaultRoundTripper) CaptureRoundTrip(request Request) (*CapturedReques
}
}

d.initTransport(client, request.Protocol, request.TLSConfig)

method := "GET"
if request.Method != "" {
method = request.Method
Expand Down
77 changes: 77 additions & 0 deletions test/e2e/conformance/utils/roundtripper/roundtripper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) 2022 Alibaba Group Holding Ltd.
//
// 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 roundtripper

import (
"crypto/tls"
"crypto/x509"
"net/http"
"testing"

"github.com/stretchr/testify/assert"
"golang.org/x/net/http2"
)

func TestTransport(t *testing.T) {
req := Request{
Protocol: "HTTP/2.0",
}
tests := []struct {
name string
req Request
prevTransport http.RoundTripper
tlsConfig *TLSConfig
transport http.RoundTripper
}{
{
name: "default",
req: Request{},
},
{
name: "http2",
req: req,
transport: &http2.Transport{},
},
{
name: "http1",
req: Request{
Protocol: "HTTP/1.1",
},
},
{
name: "https",
req: req,
tlsConfig: &TLSConfig{
SNI: "www.example.com",
},
transport: &http2.Transport{
TLSClientConfig: &tls.Config{
RootCAs: x509.NewCertPool(),
ServerName: "www.example.com",
InsecureSkipVerify: true,
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := DefaultRoundTripper{}
c := http.Client{}
d.initTransport(&c, tt.req.Protocol, tt.tlsConfig)
assert.Equal(t, tt.transport, c.Transport)
})
}
}

0 comments on commit f277d4f

Please sign in to comment.