Fix goroutine logging in cert test (#3224)

This commit is contained in:
Lars Lehtonen 2017-09-01 13:55:16 -07:00 committed by Jeff Mitchell
parent 48263622cb
commit f3d6866735

View file

@ -7,6 +7,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"io"
"io/ioutil"
"math/big"
"net"
@ -44,10 +45,10 @@ const (
// But the client, presents the CA cert of the server to trust the server.
// The client can present a cert and key which is completely independent of server's CA.
// The connection state returned will contain the certificate presented by the client.
func connectionState(t *testing.T, serverCAPath, serverCertPath, serverKeyPath, clientCertPath, clientKeyPath string) tls.ConnectionState {
func connectionState(serverCAPath, serverCertPath, serverKeyPath, clientCertPath, clientKeyPath string) (tls.ConnectionState, error) {
serverKeyPair, err := tls.LoadX509KeyPair(serverCertPath, serverKeyPath)
if err != nil {
t.Fatal(err)
return tls.ConnectionState{}, err
}
// Prepare the listener configuration with server's key pair
listenConf := &tls.Config{
@ -57,7 +58,7 @@ func connectionState(t *testing.T, serverCAPath, serverCertPath, serverKeyPath,
clientKeyPair, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
if err != nil {
t.Fatal(err)
return tls.ConnectionState{}, err
}
// Load the CA cert required by the client to authenticate the server.
rootConfig := &rootcerts.Config{
@ -65,7 +66,7 @@ func connectionState(t *testing.T, serverCAPath, serverCertPath, serverKeyPath,
}
serverCAs, err := rootcerts.LoadCACerts(rootConfig)
if err != nil {
t.Fatal(err)
return tls.ConnectionState{}, err
}
// Prepare the dial configuration that the client uses to establish the connection.
dialConf := &tls.Config{
@ -76,37 +77,68 @@ func connectionState(t *testing.T, serverCAPath, serverCertPath, serverKeyPath,
// Start the server.
list, err := tls.Listen("tcp", "127.0.0.1:0", listenConf)
if err != nil {
t.Fatal(err)
return tls.ConnectionState{}, err
}
defer list.Close()
// Accept connections.
serverErrors := make(chan error, 1)
connState := make(chan tls.ConnectionState)
go func() {
defer close(connState)
serverConn, err := list.Accept()
if err != nil {
serverErrors <- err
close(serverErrors)
return
}
defer serverConn.Close()
// Read the ping
buf := make([]byte, 4)
_, err = serverConn.Read(buf)
if (err != nil) && (err != io.EOF) {
serverErrors <- err
close(serverErrors)
return
}
close(serverErrors)
connState <- serverConn.(*tls.Conn).ConnectionState()
}()
// Establish a connection from the client side and write a few bytes.
clientErrors := make(chan error, 1)
go func() {
addr := list.Addr().String()
conn, err := tls.Dial("tcp", addr, dialConf)
if err != nil {
t.Fatalf("err: %v", err)
clientErrors <- err
close(clientErrors)
return
}
defer conn.Close()
// Write ping
conn.Write([]byte("ping"))
_, err = conn.Write([]byte("ping"))
if err != nil {
clientErrors <- err
}
close(clientErrors)
}()
// Accept the connection on the server side.
serverConn, err := list.Accept()
if err != nil {
t.Fatal(err)
for err = range clientErrors {
if err != nil {
return tls.ConnectionState{}, fmt.Errorf("error in client goroutine:%v", err)
}
}
defer serverConn.Close()
// Read the ping
buf := make([]byte, 4)
serverConn.Read(buf)
for err = range serverErrors {
if err != nil {
return tls.ConnectionState{}, fmt.Errorf("error in server goroutine:%v", err)
}
}
// Grab the current state
connState := serverConn.(*tls.Conn).ConnectionState()
return connState
return <-connState, nil
}
func TestBackend_NonCAExpiry(t *testing.T) {
@ -298,7 +330,10 @@ func TestBackend_NonCAExpiry(t *testing.T) {
}
// Create connection state using the certificates generated
connState := connectionState(t, caCertFile.Name(), caCertFile.Name(), caKeyFile.Name(), issuedCertFile.Name(), issuedKeyFile.Name())
connState, err := connectionState(caCertFile.Name(), caCertFile.Name(), caKeyFile.Name(), issuedCertFile.Name(), issuedKeyFile.Name())
if err != nil {
t.Fatalf("error testing connection state:%v", err)
}
loginReq := &logical.Request{
Operation: logical.UpdateOperation,
@ -361,7 +396,10 @@ func TestBackend_RegisteredNonCA_CRL(t *testing.T) {
// Connection state is presenting the client Non-CA cert and its key.
// This is exactly what is registered at the backend.
connState := connectionState(t, serverCAPath, serverCertPath, serverKeyPath, testCertPath1, testKeyPath1)
connState, err := connectionState(serverCAPath, serverCertPath, serverKeyPath, testCertPath1, testKeyPath1)
if err != nil {
t.Fatalf("error testing connection state:%v", err)
}
loginReq := &logical.Request{
Operation: logical.UpdateOperation,
Storage: storage,
@ -441,7 +479,10 @@ func TestBackend_CRLs(t *testing.T) {
// Connection state is presenting the client CA cert and its key.
// This is exactly what is registered at the backend.
connState := connectionState(t, serverCAPath, serverCertPath, serverKeyPath, testRootCACertPath1, testRootCAKeyPath1)
connState, err := connectionState(serverCAPath, serverCertPath, serverKeyPath, testRootCACertPath1, testRootCAKeyPath1)
if err != nil {
t.Fatalf("error testing connection state:%v", err)
}
loginReq := &logical.Request{
Operation: logical.UpdateOperation,
Storage: storage,
@ -457,7 +498,10 @@ func TestBackend_CRLs(t *testing.T) {
// Now, without changing the registered client CA cert, present from
// the client side, a cert issued using the registered CA.
connState = connectionState(t, serverCAPath, serverCertPath, serverKeyPath, testCertPath1, testKeyPath1)
connState, err = connectionState(serverCAPath, serverCertPath, serverKeyPath, testCertPath1, testKeyPath1)
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
loginReq.Connection.ConnState = &connState
// Attempt login with the updated connection
@ -507,7 +551,10 @@ func TestBackend_CRLs(t *testing.T) {
}
// Test login using a different client CA cert pair.
connState = connectionState(t, serverCAPath, serverCertPath, serverKeyPath, testRootCACertPath2, testRootCAKeyPath2)
connState, err = connectionState(serverCAPath, serverCertPath, serverKeyPath, testRootCACertPath2, testRootCAKeyPath2)
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
loginReq.Connection.ConnState = &connState
// Attempt login with the updated connection
@ -583,8 +630,11 @@ func TestBackend_CertWrites(t *testing.T) {
// Test a client trusted by a CA
func TestBackend_basic_CA(t *testing.T) {
connState := testConnState(t, "test-fixtures/keys/cert.pem",
connState, err := testConnState("test-fixtures/keys/cert.pem",
"test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("err: %v", err)
@ -609,8 +659,11 @@ func TestBackend_basic_CA(t *testing.T) {
// Test CRL behavior
func TestBackend_Basic_CRLs(t *testing.T) {
connState := testConnState(t, "test-fixtures/keys/cert.pem",
connState, err := testConnState("test-fixtures/keys/cert.pem",
"test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("err: %v", err)
@ -635,8 +688,11 @@ func TestBackend_Basic_CRLs(t *testing.T) {
// Test a self-signed client (root CA) that is trusted
func TestBackend_basic_singleCert(t *testing.T) {
connState := testConnState(t, "test-fixtures/root/rootcacert.pem",
connState, err := testConnState("test-fixtures/root/rootcacert.pem",
"test-fixtures/root/rootcakey.pem", "test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("err: %v", err)
@ -656,8 +712,11 @@ func TestBackend_basic_singleCert(t *testing.T) {
// Test against a collection of matching and non-matching rules
func TestBackend_mixed_constraints(t *testing.T) {
connState := testConnState(t, "test-fixtures/keys/cert.pem",
connState, err := testConnState("test-fixtures/keys/cert.pem",
"test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("err: %v", err)
@ -678,8 +737,11 @@ func TestBackend_mixed_constraints(t *testing.T) {
// Test an untrusted client
func TestBackend_untrusted(t *testing.T) {
connState := testConnState(t, "test-fixtures/keys/cert.pem",
connState, err := testConnState("test-fixtures/keys/cert.pem",
"test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
logicaltest.Test(t, logicaltest.TestCase{
Backend: testFactory(t),
Steps: []logicaltest.TestStep{
@ -906,17 +968,17 @@ func testAccStepCertNoLease(
}
}
func testConnState(t *testing.T, certPath, keyPath, rootCertPath string) tls.ConnectionState {
func testConnState(certPath, keyPath, rootCertPath string) (tls.ConnectionState, error) {
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
t.Fatalf("err: %v", err)
return tls.ConnectionState{}, err
}
rootConfig := &rootcerts.Config{
CAFile: rootCertPath,
}
rootCAs, err := rootcerts.LoadCACerts(rootConfig)
if err != nil {
t.Fatalf("err: %v", err)
return tls.ConnectionState{}, err
}
listenConf := &tls.Config{
Certificates: []tls.Certificate{cert},
@ -926,37 +988,72 @@ func testConnState(t *testing.T, certPath, keyPath, rootCertPath string) tls.Con
}
dialConf := new(tls.Config)
*dialConf = *listenConf
// start a server
list, err := tls.Listen("tcp", "127.0.0.1:0", listenConf)
if err != nil {
t.Fatalf("err: %v", err)
return tls.ConnectionState{}, err
}
defer list.Close()
// Accept connections.
serverErrors := make(chan error, 1)
connState := make(chan tls.ConnectionState)
go func() {
defer close(connState)
serverConn, err := list.Accept()
serverErrors <- err
if err != nil {
close(serverErrors)
return
}
defer serverConn.Close()
// Read the ping
buf := make([]byte, 4)
_, err = serverConn.Read(buf)
if (err != nil) && (err != io.EOF) {
serverErrors <- err
close(serverErrors)
return
} else {
// EOF is a reasonable error condition, so swallow it.
serverErrors <- nil
}
close(serverErrors)
connState <- serverConn.(*tls.Conn).ConnectionState()
}()
// Establish a connection from the client side and write a few bytes.
clientErrors := make(chan error, 1)
go func() {
addr := list.Addr().String()
conn, err := tls.Dial("tcp", addr, dialConf)
clientErrors <- err
if err != nil {
t.Fatalf("err: %v", err)
close(clientErrors)
return
}
defer conn.Close()
// Write ping
conn.Write([]byte("ping"))
_, err = conn.Write([]byte("ping"))
clientErrors <- err
close(clientErrors)
}()
serverConn, err := list.Accept()
if err != nil {
t.Fatalf("err: %v", err)
for err = range clientErrors {
if err != nil {
return tls.ConnectionState{}, fmt.Errorf("error in client goroutine:%v", err)
}
}
defer serverConn.Close()
// Read the pign
buf := make([]byte, 4)
serverConn.Read(buf)
for err = range serverErrors {
if err != nil {
return tls.ConnectionState{}, fmt.Errorf("error in server goroutine:%v", err)
}
}
// Grab the current state
connState := serverConn.(*tls.Conn).ConnectionState()
return connState
return <-connState, nil
}
func Test_Renew(t *testing.T) {
@ -974,8 +1071,11 @@ func Test_Renew(t *testing.T) {
}
b := lb.(*backend)
connState := testConnState(t, "test-fixtures/keys/cert.pem",
connState, err := testConnState("test-fixtures/keys/cert.pem",
"test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
if err != nil {
t.Fatal(err)