Skip to content

Commit

Permalink
test(e2e): add stream tcp proxy with SNI test (#1533)
Browse files Browse the repository at this point in the history
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
  • Loading branch information
Juneezee authored Jan 31, 2023
1 parent 33d42c3 commit 5e0f89f
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
7 changes: 7 additions & 0 deletions test/e2e/scaffold/scaffold.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,13 @@ func (s *Scaffold) DNSResolver() *net.Resolver {
}
}

func (s *Scaffold) DialTLSOverTcp(serverName string) (*tls.Conn, error) {
return tls.Dial("tcp", s.apisixTLSOverTCPTunnel.Endpoint(), &tls.Config{
InsecureSkipVerify: true,
ServerName: serverName,
})
}

func (s *Scaffold) UpdateNamespace(ns string) {
s.kubectlOptions.Namespace = ns
}
Expand Down
114 changes: 114 additions & 0 deletions test/e2e/suite-ingress/suite-ingress-resource/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@
package ingress

import (
"bytes"
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"time"

ginkgo "github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -214,4 +222,110 @@ spec:
assert.Equal(ginkgo.GinkgoT(), sr[0].ServerPort, int32(9100))
assert.Equal(ginkgo.GinkgoT(), sr[0].SNI, "")
})

ginkgo.It("stream tcp proxy with SNI", func() {
// create secrets
hostA := "a.test.com"
secretA := "server-secret-a"
serverCertA, serverKeyA := generateCert(ginkgo.GinkgoT(), []string{hostA})
err := s.NewSecret(secretA, serverCertA.String(), serverKeyA.String())
assert.Nil(ginkgo.GinkgoT(), err, "create server cert secret 'a' error")

hostB := "b.test.com"
secretB := "server-secret-b"
serverCertB, serverKeyB := generateCert(ginkgo.GinkgoT(), []string{hostB})
err = s.NewSecret(secretB, serverCertB.String(), serverKeyB.String())
assert.Nil(ginkgo.GinkgoT(), err, "create server cert secret 'b' error")

// create ApisixTls resource
err = s.NewApisixTls("tls-server-a", hostA, secretA)
assert.Nil(ginkgo.GinkgoT(), err, "create ApisixTls 'a' error")

err = s.NewApisixTls("tls-server-b", hostB, secretB)
assert.Nil(ginkgo.GinkgoT(), err, "create ApisixTls 'b' error")

// check ssl in APISIX
assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixTlsCreated(2))

backendSvc, backendSvcPort := s.DefaultHTTPBackend()
apisixRoute := fmt.Sprintf(`
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: httpbin-tcp-route
spec:
stream:
- name: ruleA
protocol: TCP
match:
ingressPort: 9110
host: %s
backend:
serviceName: %s
servicePort: %d
- name: ruleB
protocol: TCP
match:
ingressPort: 9110
host: %s
backend:
serviceName: %s
servicePort: %d
`, hostA, backendSvc, backendSvcPort[0], hostB, backendSvc, backendSvcPort[0])

assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(apisixRoute))

err = s.EnsureNumApisixStreamRoutesCreated(2)
assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")

// SNI: hostA should return certificate with hostA in Subject Alternative Name only
connA, err := s.DialTLSOverTcp(hostA)
assert.Nil(ginkgo.GinkgoT(), err)
defer connA.Close()

assert.Equal(ginkgo.GinkgoT(), connA.ConnectionState().PeerCertificates[0].DNSNames, []string{hostA})

// SNI: hostB should return certificate with hostB in Subject Alternative Name only
connB, err := s.DialTLSOverTcp(hostB)
assert.Nil(ginkgo.GinkgoT(), err)
defer connB.Close()

assert.Equal(ginkgo.GinkgoT(), connB.ConnectionState().PeerCertificates[0].DNSNames, []string{hostB})
})
})

func generateCert(t ginkgo.GinkgoTInterface, dnsNames []string) (certPemBytes, privPemBytes bytes.Buffer) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
pub := priv.Public()

serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
assert.NoError(t, err)

template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Acme Co"},
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour),

KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,

DNSNames: dnsNames,
}

derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, pub, priv)
assert.NoError(t, err)
err = pem.Encode(&certPemBytes, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
assert.NoError(t, err)

privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
assert.NoError(t, err)
err = pem.Encode(&privPemBytes, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes})
assert.NoError(t, err)

return
}

0 comments on commit 5e0f89f

Please sign in to comment.