Change ConfigServerTLS to take a client CA directory instead of certs

Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
Ying Li 2015-10-16 14:13:05 -07:00
parent e50cc2c9cd
commit 7356dfd273
4 changed files with 70 additions and 13 deletions

View File

@ -260,6 +260,12 @@ func (s *X509FileStore) GetVerifyOptions(dnsName string) (x509.VerifyOptions, er
return opts, nil
}
// Empty returns true if there are no certificates in the X509FileStore, false
// otherwise.
func (s *X509FileStore) Empty() bool {
return len(s.fingerprintMap) == 0
}
func fileName(cert *x509.Certificate) (string, CertID, error) {
certID, err := fingerprintCert(cert)
if err != nil {

View File

@ -124,6 +124,21 @@ func TestAddCertFromFileX509FileStore(t *testing.T) {
}
}
// TestNewX509FileStoreEmpty verifies the behavior of the Empty function
func TestNewX509FileStoreEmpty(t *testing.T) {
tempDir, err := ioutil.TempDir("", "cert-test")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)
store, err := NewX509FileStore(tempDir)
assert.NoError(t, err, "failed to create a new X509FileStore: %v", store)
assert.True(t, store.Empty())
err = store.AddCertFromFile("../fixtures/root-ca.crt")
assert.NoError(t, err, "failed to add certificate from file")
assert.False(t, store.Empty())
}
func TestAddCertFromPEMX509FileStore(t *testing.T) {
b, err := ioutil.ReadFile("../fixtures/root-ca.crt")
if err != nil {

View File

@ -3,7 +3,8 @@ package utils
import (
"crypto/rand"
"crypto/tls"
"crypto/x509"
"fmt"
"os"
"github.com/docker/notary/trustmanager"
)
@ -12,7 +13,7 @@ import (
// and optionally client authentication. Note that a tls configuration is
// constructed that either requires and verifies client authentication or
// doesn't deal with client certs at all. Nothing in the middle.
func ConfigureServerTLS(serverCert string, serverKey string, clientAuth bool, caCert string) (*tls.Config, error) {
func ConfigureServerTLS(serverCert string, serverKey string, clientAuth bool, caCertDir string) (*tls.Config, error) {
keypair, err := tls.LoadX509KeyPair(serverCert, serverKey)
if err != nil {
return nil, err
@ -37,14 +38,24 @@ func ConfigureServerTLS(serverCert string, serverKey string, clientAuth bool, ca
if clientAuth {
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
if caCert != "" {
cert, err := trustmanager.LoadCertFromFile(caCert)
if caCertDir != "" {
// Check to see if the given directory exists
fi, err := os.Stat(caCertDir)
if err != nil {
return nil, err
}
caPool := x509.NewCertPool()
caPool.AddCert(cert)
tlsConfig.ClientCAs = caPool
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()
}
}

View File

@ -2,6 +2,10 @@ package utils
import (
"crypto/tls"
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
@ -10,16 +14,35 @@ import (
const (
ServerCert = "../fixtures/notary-server.crt"
ServerKey = "../fixtures/notary-server.key"
CACert = "../fixtures/root-ca.crt"
FakeFile = "../fixtures/not-a-file"
RootCA = "../fixtures/root-ca.crt"
)
// copies the provided certificate into a temporary directory
func makeTempCertDir(t *testing.T) string {
tempDir, err := ioutil.TempDir("/tmp", "cert-test")
assert.NoError(t, err, "couldn't open temp directory")
in, err := os.Open(RootCA)
assert.NoError(t, err, "cannot open %s", RootCA)
defer in.Close()
copiedCert := filepath.Join(tempDir, filepath.Base(RootCA))
out, err := os.Create(copiedCert)
assert.NoError(t, err, "cannot open %s", copiedCert)
defer out.Close()
_, err = io.Copy(out, in)
assert.NoError(t, err, "cannot copy %s to %s", RootCA, copiedCert)
return tempDir
}
// TestTLSConfigFailsIfUnableToLoadCerts fails if unable to load either of the
// server files or the client cert info
func TestConfigServerTLSFailsIfUnableToLoadCerts(t *testing.T) {
tempDir := makeTempCertDir(t)
for i := 0; i < 3; i++ {
files := []string{ServerCert, ServerKey, CACert}
files[i] = FakeFile
files := []string{ServerCert, ServerKey, tempDir}
files[i] = "not-real-file"
result, err := ConfigureServerTLS(files[0], files[1], true, files[2])
assert.Nil(t, result)
@ -46,10 +69,11 @@ func TestConfigServerTLSServerCertsOnly(t *testing.T) {
// the provided server certificate, and since clientAuth was false, no client
// auth or CAs configured even though a client CA cert was provided.
func TestConfigServerTLSNoCACertsIfNoClientAuth(t *testing.T) {
tempDir := makeTempCertDir(t)
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
assert.NoError(t, err)
tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, false, CACert)
tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, false, tempDir)
assert.NoError(t, err)
assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
assert.True(t, tlsConfig.PreferServerCipherSuites)
@ -74,10 +98,11 @@ func TestTLSConfigClientAuthEnabledNoCACerts(t *testing.T) {
// TestTLSConfigClientAuthEnabledWithCACert returns a valid tls config with the
// provided server certificate, client auth enabled, and a client CA.
func TestTLSConfigClientAuthEnabledWithCACert(t *testing.T) {
tempDir := makeTempCertDir(t)
keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
assert.NoError(t, err)
tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, true, CACert)
tlsConfig, err := ConfigureServerTLS(ServerCert, ServerKey, true, tempDir)
assert.NoError(t, err)
assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
assert.True(t, tlsConfig.PreferServerCipherSuites)