Skip to content

Commit

Permalink
test readability: refactored TLS tests
Browse files Browse the repository at this point in the history
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
  • Loading branch information
fredbi committed Dec 10, 2023
1 parent 7c6b268 commit 4f2e629
Show file tree
Hide file tree
Showing 2 changed files with 375 additions and 277 deletions.
277 changes: 0 additions & 277 deletions client/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,14 @@ package client

import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"encoding/pem"
"encoding/xml"
"errors"
"io"
"net/http"
"net/http/cookiejar"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
goruntime "runtime"
"testing"
"time"

Expand Down Expand Up @@ -57,277 +51,6 @@ type task struct {
ID int64 `json:"id" xml:"id"`
}

func TestRuntime_TLSAuthConfig(t *testing.T) {
var opts TLSClientOptions
opts.CA = "../fixtures/certs/myCA.crt"
opts.Key = "../fixtures/certs/myclient.key"
opts.Certificate = "../fixtures/certs/myclient.crt"
opts.ServerName = "somewhere"

cfg, err := TLSClientAuth(opts)
require.NoError(t, err)
require.NotNil(t, cfg)
assert.Len(t, cfg.Certificates, 1)
assert.NotNil(t, cfg.RootCAs)
assert.Equal(t, "somewhere", cfg.ServerName)
}

func TestRuntime_TLSAuthConfigWithRSAKey(t *testing.T) {
keyPem, err := os.ReadFile("../fixtures/certs/myclient.key")
require.NoError(t, err)

keyDer, _ := pem.Decode(keyPem)
require.NotNil(t, keyDer)

key, err := x509.ParsePKCS1PrivateKey(keyDer.Bytes)
require.NoError(t, err)

certPem, err := os.ReadFile("../fixtures/certs/myclient.crt")
require.NoError(t, err)

certDer, _ := pem.Decode(certPem)
require.NotNil(t, certDer)

cert, err := x509.ParseCertificate(certDer.Bytes)
require.NoError(t, err)

var opts TLSClientOptions
opts.LoadedKey = key
opts.LoadedCertificate = cert

cfg, err := TLSClientAuth(opts)
require.NoError(t, err)
require.NotNil(t, cfg)
assert.Len(t, cfg.Certificates, 1)
}

func TestRuntime_TLSAuthConfigWithECKey(t *testing.T) {
keyPem, err := os.ReadFile("../fixtures/certs/myclient-ecc.key")
require.NoError(t, err)

_, remainder := pem.Decode(keyPem)
keyDer, _ := pem.Decode(remainder)
require.NotNil(t, keyDer)

key, err := x509.ParseECPrivateKey(keyDer.Bytes)
require.NoError(t, err)

certPem, err := os.ReadFile("../fixtures/certs/myclient-ecc.crt")
require.NoError(t, err)

certDer, _ := pem.Decode(certPem)
require.NotNil(t, certDer)

cert, err := x509.ParseCertificate(certDer.Bytes)
require.NoError(t, err)

var opts TLSClientOptions
opts.LoadedKey = key
opts.LoadedCertificate = cert

cfg, err := TLSClientAuth(opts)
require.NoError(t, err)
require.NotNil(t, cfg)
assert.Len(t, cfg.Certificates, 1)
}

func TestRuntime_TLSAuthConfigWithLoadedCA(t *testing.T) {
certPem, err := os.ReadFile("../fixtures/certs/myCA.crt")
require.NoError(t, err)

block, _ := pem.Decode(certPem)
require.NotNil(t, block)

cert, err := x509.ParseCertificate(block.Bytes)
require.NoError(t, err)

var opts TLSClientOptions
opts.LoadedCA = cert

cfg, err := TLSClientAuth(opts)
require.NoError(t, err)
require.NotNil(t, cfg)
assert.NotNil(t, cfg.RootCAs)
}

func TestRuntime_TLSAuthConfigWithLoadedCAPool(t *testing.T) {
certPem, err := os.ReadFile("../fixtures/certs/myCA.crt")
require.NoError(t, err)

block, _ := pem.Decode(certPem)
require.NotNil(t, block)

cert, err := x509.ParseCertificate(block.Bytes)
require.NoError(t, err)

pool := x509.NewCertPool()
pool.AddCert(cert)

var opts TLSClientOptions
opts.LoadedCAPool = pool

cfg, err := TLSClientAuth(opts)
require.NoError(t, err)
require.NotNil(t, cfg)
require.NotNil(t, cfg.RootCAs)

// Using require.Len prints the (very large and incomprehensible)
// Subjects list on failure, so instead use require.Equal.
assert.Len(t, cfg.RootCAs.Subjects(), 1) //nolint:staticcheck
}

func TestRuntime_TLSAuthConfigWithLoadedCAPoolAndLoadedCA(t *testing.T) {
certPem, err := os.ReadFile(filepath.Join("..", "fixtures", "certs", "myCA.crt"))
require.NoError(t, err)

block, _ := pem.Decode(certPem)
require.NotNil(t, block)

cert, err := x509.ParseCertificate(block.Bytes)
require.NoError(t, err)

var pool *x509.CertPool
if goruntime.GOOS == "windows" {
// Windows doesn't have the system cert pool.
pool = x509.NewCertPool()
} else {
pool, err = x509.SystemCertPool()
require.NoError(t, err)
}
startingCertCount := len(pool.Subjects()) //nolint:staticcheck

var opts TLSClientOptions
opts.LoadedCAPool = pool
opts.LoadedCA = cert

cfg, err := TLSClientAuth(opts)
require.NoError(t, err)
require.NotNil(t, cfg)
require.NotNil(t, cfg.RootCAs)

// Using require.Len prints the (very large and incomprehensible)
// Subjects list on failure, so instead use require.Equal.
assert.Len(t, cfg.RootCAs.Subjects(), startingCertCount+1) //nolint:staticcheck
}

func TestRuntime_TLSAuthConfigWithVerifyPeerCertificate(t *testing.T) {
var opts TLSClientOptions
opts.InsecureSkipVerify = true
var verify = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
return nil
}
opts.VerifyPeerCertificate = verify

cfg, err := TLSClientAuth(opts)
require.NoError(t, err)
require.NotNil(t, cfg)
assert.True(t, cfg.InsecureSkipVerify)
assert.NotNil(t, cfg.VerifyPeerCertificate)
}

func TestRuntime_ManualCertificateValidation(t *testing.T) {
// test manual verification of server certificates
// against root certificate on client side.
result := []task{
{false, "task 1 content", 1},
{false, "task 2 content", 2},
}
var verifyCalled bool
server := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
rw.Header().Add(runtime.HeaderContentType, runtime.JSONMime)
rw.WriteHeader(http.StatusOK)
jsongen := json.NewEncoder(rw)
require.NoError(t, jsongen.Encode(result))
}))

// root cert
rootCertFile := filepath.Join("..", "fixtures", "certs", "myCA.crt")
rootCertPem, err := os.ReadFile(rootCertFile)
require.NoError(t, err)
rootCertRaw, _ := pem.Decode(rootCertPem)
require.NotNil(t, rootCertRaw)
rootCert, err := x509.ParseCertificate(rootCertRaw.Bytes)
require.NoError(t, err)

// create server tls config
serverCACertPool := x509.NewCertPool()
serverCACertPool.AddCert(rootCert)
server.TLS = &tls.Config{
RootCAs: serverCACertPool,
MinVersion: tls.VersionTLS12,
}

// load server certs
serverCertFile := filepath.Join("..", "fixtures", "certs", "mycert1.crt")
serverKeyFile := filepath.Join("..", "fixtures", "certs", "mycert1.key")
server.TLS.Certificates = make([]tls.Certificate, 1)
server.TLS.Certificates[0], err = tls.LoadX509KeyPair(
serverCertFile,
serverKeyFile,
)
require.NoError(t, err)

server.StartTLS()
defer server.Close()

// test if server is a valid endpoint
// by comparing received certs against root cert,
// explicitly omitting DNSName check.
client, err := TLSClient(TLSClientOptions{
InsecureSkipVerify: true,
VerifyPeerCertificate: func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
verifyCalled = true

caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(rootCertPem)

opts := x509.VerifyOptions{
Roots: caCertPool,
CurrentTime: time.Date(2017, time.July, 1, 1, 1, 1, 1, time.UTC),
}

cert, e := x509.ParseCertificate(rawCerts[0])
if e != nil {
return e
}

_, e = cert.Verify(opts)
return e
},
})

require.NoError(t, err)
hu, err := url.Parse(server.URL)
require.NoError(t, err)
rt := NewWithClient(hu.Host, "/", []string{schemeHTTPS}, client)

rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
return nil
})

var received []task
_, err = rt.Submit(&runtime.ClientOperation{
ID: "getTasks",
Method: http.MethodGet,
PathPattern: "/",
Params: rwrtr,
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
if response.Code() == http.StatusOK {
if e := consumer.Consume(response.Body(), &received); e != nil {
return nil, e
}
return result, nil
}
return nil, errors.New("generic error")
}),
})

require.NoError(t, err)
assert.True(t, verifyCalled)
assert.IsType(t, []task{}, received)
assert.EqualValues(t, result, received)
}

func TestRuntime_Concurrent(t *testing.T) {
// test that it can make a simple request
// and get the response for it.
Expand Down
Loading

0 comments on commit 4f2e629

Please sign in to comment.