mirror of https://github.com/docker/docs.git
Slight refactoring of ConfigureServerTLS and added a ConfigureClientTLS
as well. Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
parent
8d96cf0c1f
commit
b399783eee
|
@ -3,6 +3,7 @@ package utils
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -38,25 +39,56 @@ func ConfigureServerTLS(serverCert string, serverKey string, clientAuth bool, ca
|
||||||
|
|
||||||
if clientAuth {
|
if clientAuth {
|
||||||
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
|
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
|
||||||
if caCertDir != "" {
|
}
|
||||||
// Check to see if the given directory exists
|
|
||||||
fi, err := os.Stat(caCertDir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !fi.IsDir() {
|
|
||||||
return nil, fmt.Errorf("No such directory: %s", caCertDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
certStore, err := trustmanager.NewX509FileStore(caCertDir)
|
if caCertDir != "" {
|
||||||
if err != nil {
|
// Check to see if the given directory exists
|
||||||
return nil, err
|
fi, err := os.Stat(caCertDir)
|
||||||
}
|
if err != nil {
|
||||||
if certStore.Empty() {
|
return nil, err
|
||||||
return nil, fmt.Errorf("No certificates in %s", caCertDir)
|
|
||||||
}
|
|
||||||
tlsConfig.ClientCAs = certStore.GetCertificatePool()
|
|
||||||
}
|
}
|
||||||
|
if !fi.IsDir() {
|
||||||
|
return nil, fmt.Errorf("No such directory: %s", caCertDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
certStore, err := trustmanager.NewX509FileStore(caCertDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if certStore.Empty() {
|
||||||
|
return nil, fmt.Errorf("No certificates in %s", caCertDir)
|
||||||
|
}
|
||||||
|
tlsConfig.ClientCAs = certStore.GetCertificatePool()
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlsConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigureClientTLS generates a tls configuration for clients using the
|
||||||
|
// provided.
|
||||||
|
func ConfigureClientTLS(rootCA string, skipVerify bool, clientCert string, clientKey string) (*tls.Config, error) {
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
InsecureSkipVerify: skipVerify,
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
}
|
||||||
|
|
||||||
|
if rootCA != "" {
|
||||||
|
rootCert, err := trustmanager.LoadCertFromFile(rootCA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Could not load root ca file. %s", err.Error())
|
||||||
|
}
|
||||||
|
rootPool := x509.NewCertPool()
|
||||||
|
rootPool.AddCert(rootCert)
|
||||||
|
tlsConfig.RootCAs = rootPool
|
||||||
|
}
|
||||||
|
|
||||||
|
if clientCert != "" && clientKey != "" {
|
||||||
|
keypair, err := tls.LoadX509KeyPair(clientCert, clientKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tlsConfig.Certificates = []tls.Certificate{keypair}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tlsConfig, nil
|
return tlsConfig, nil
|
||||||
|
|
|
@ -35,8 +35,8 @@ func makeTempCertDir(t *testing.T) string {
|
||||||
return tempDir
|
return tempDir
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestTLSConfigFailsIfUnableToLoadCerts fails if unable to load either of the
|
// If the cert files and directory are provided but are invalid, an error is
|
||||||
// server files or the client cert info
|
// returned.
|
||||||
func TestConfigServerTLSFailsIfUnableToLoadCerts(t *testing.T) {
|
func TestConfigServerTLSFailsIfUnableToLoadCerts(t *testing.T) {
|
||||||
tempDir := makeTempCertDir(t)
|
tempDir := makeTempCertDir(t)
|
||||||
|
|
||||||
|
@ -50,9 +50,8 @@ func TestConfigServerTLSFailsIfUnableToLoadCerts(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestConfigServerTLSServerCertsOnly returns a valid tls config with the
|
// If server cert and key are provided, and client auth is disabled, then
|
||||||
// provided server certificate, and since clientAuth was false, no client auth
|
// a valid tls.Config is returned with ClientAuth set to NoClientCert
|
||||||
// or CAs configured.
|
|
||||||
func TestConfigServerTLSServerCertsOnly(t *testing.T) {
|
func TestConfigServerTLSServerCertsOnly(t *testing.T) {
|
||||||
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
|
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -65,10 +64,10 @@ func TestConfigServerTLSServerCertsOnly(t *testing.T) {
|
||||||
assert.Nil(t, tlsConfig.ClientCAs)
|
assert.Nil(t, tlsConfig.ClientCAs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestConfigServerTLSNoCACertsIfNoClientAuth returns a valid tls config with
|
// If server cert and key are provided, and client cert directory is provided,
|
||||||
// the provided server certificate, and since clientAuth was false, no client
|
// a valid tls.Config is returned with the clientCAs set to the certs in that
|
||||||
// auth or CAs configured even though a client CA cert was provided.
|
// directory.
|
||||||
func TestConfigServerTLSNoCACertsIfNoClientAuth(t *testing.T) {
|
func TestConfigServerTLSWithCACerts(t *testing.T) {
|
||||||
tempDir := makeTempCertDir(t)
|
tempDir := makeTempCertDir(t)
|
||||||
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
|
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -78,12 +77,13 @@ func TestConfigServerTLSNoCACertsIfNoClientAuth(t *testing.T) {
|
||||||
assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
|
assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
|
||||||
assert.True(t, tlsConfig.PreferServerCipherSuites)
|
assert.True(t, tlsConfig.PreferServerCipherSuites)
|
||||||
assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
|
assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
|
||||||
assert.Nil(t, tlsConfig.ClientCAs)
|
assert.Len(t, tlsConfig.ClientCAs.Subjects(), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestTLSConfigClientAuthEnabledNoCACerts returns a valid tls config with the
|
// If server cert and key are provided, and client auth is disabled, then
|
||||||
// provided server certificate client auth enabled, but no CAs configured.
|
// a valid tls.Config is returned with ClientAuth set to
|
||||||
func TestTLSConfigClientAuthEnabledNoCACerts(t *testing.T) {
|
// RequireAndVerifyClientCert
|
||||||
|
func TestConfigServerTLSClientAuthEnabled(t *testing.T) {
|
||||||
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
|
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -95,17 +95,54 @@ func TestTLSConfigClientAuthEnabledNoCACerts(t *testing.T) {
|
||||||
assert.Nil(t, tlsConfig.ClientCAs)
|
assert.Nil(t, tlsConfig.ClientCAs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestTLSConfigClientAuthEnabledWithCACert returns a valid tls config with the
|
// The skipVerify boolean gets set on the tls.Config's InsecureSkipBoolean
|
||||||
// provided server certificate, client auth enabled, and a client CA.
|
func TestConfigClientTLSNoVerify(t *testing.T) {
|
||||||
func TestTLSConfigClientAuthEnabledWithCACert(t *testing.T) {
|
for _, skip := range []bool{true, false} {
|
||||||
tempDir := makeTempCertDir(t)
|
tlsConfig, err := ConfigureClientTLS("", skip, "", "")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, tlsConfig.Certificates)
|
||||||
|
assert.Equal(t, skip, tlsConfig.InsecureSkipVerify)
|
||||||
|
assert.Nil(t, tlsConfig.RootCAs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The RootCA is set if it is provided and valid
|
||||||
|
func TestConfigClientTLSValidRootCA(t *testing.T) {
|
||||||
|
tlsConfig, err := ConfigureClientTLS(RootCA, false, "", "")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, tlsConfig.Certificates)
|
||||||
|
assert.Equal(t, false, tlsConfig.InsecureSkipVerify)
|
||||||
|
assert.Len(t, tlsConfig.RootCAs.Subjects(), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An error is returned if a root CA is provided but not valid
|
||||||
|
func TestConfigClientTLSInValidRootCA(t *testing.T) {
|
||||||
|
tlsConfig, err := ConfigureClientTLS("not-a-file.crt", false, "", "")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, tlsConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An error is returned if either the client cert or the key are provided
|
||||||
|
// but invalid.
|
||||||
|
func TestConfigClientTLSClientCertOrKeyInvalid(t *testing.T) {
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
files := []string{ServerCert, ServerKey}
|
||||||
|
files[i] = "not-a-file.crt"
|
||||||
|
tlsConfig, err := ConfigureClientTLS("", false, files[0], files[1])
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, tlsConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The certificate is set if the client cert and client key are provided and
|
||||||
|
// valid.
|
||||||
|
func TestConfigClientTLSValidClientCertAndKey(t *testing.T) {
|
||||||
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
|
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, true, tempDir)
|
tlsConfig, err := ConfigureClientTLS("", false, ServerCert, ServerKey)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
|
assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
|
||||||
assert.True(t, tlsConfig.PreferServerCipherSuites)
|
assert.Equal(t, false, tlsConfig.InsecureSkipVerify)
|
||||||
assert.Equal(t, tls.RequireAndVerifyClientCert, tlsConfig.ClientAuth)
|
assert.Nil(t, tlsConfig.RootCAs)
|
||||||
assert.Equal(t, 1, len(tlsConfig.ClientCAs.Subjects()))
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue