1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #27918 from dmcgowan/use-system-certs

Merge system certificate pool with custom certificates
This commit is contained in:
Tibor Vass 2016-11-02 13:51:58 -07:00 committed by GitHub
commit 1e51f99684
6 changed files with 48 additions and 138 deletions

View file

@ -64,7 +64,7 @@ clone git github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
clone git golang.org/x/net 2beffdc2e92c8a3027590f898fe88f69af48a3f8 https://github.com/tonistiigi/net.git
clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git
clone git github.com/docker/go-units 8a7beacffa3009a9ac66bad506b18ffdd110cf97
clone git github.com/docker/go-connections 1494b6df4050e60923d68cd8cc6a19e7af9f1c01
clone git github.com/docker/go-connections f512407a188ecb16f31a33dbc9c4e4814afc1b03
clone git github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e
clone git github.com/imdario/mergo 0.2.1

View file

@ -1,132 +0,0 @@
// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
//
// As a reminder from https://golang.org/pkg/crypto/tls/#Config:
// A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified.
// A Config may be reused; the tls package will also not modify it.
package tlsconfig
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"os"
"github.com/Sirupsen/logrus"
)
// Options represents the information needed to create client and server TLS configurations.
type Options struct {
CAFile string
// If either CertFile or KeyFile is empty, Client() will not load them
// preventing the client from authenticating to the server.
// However, Server() requires them and will error out if they are empty.
CertFile string
KeyFile string
// client-only option
InsecureSkipVerify bool
// server-only option
ClientAuth tls.ClientAuthType
}
// Extra (server-side) accepted CBC cipher suites - will phase out in the future
var acceptedCBCCiphers = []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
}
// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
var clientCipherSuites = []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
}
// DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls
// options struct but wants to use a commonly accepted set of TLS cipher suites, with
// known weak algorithms removed.
var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
// ServerDefault returns a secure-enough TLS configuration for the server TLS configuration.
func ServerDefault() *tls.Config {
return &tls.Config{
// Avoid fallback to SSL protocols < TLS1.0
MinVersion: tls.VersionTLS10,
PreferServerCipherSuites: true,
CipherSuites: DefaultServerAcceptedCiphers,
}
}
// ClientDefault returns a secure-enough TLS configuration for the client TLS configuration.
func ClientDefault() *tls.Config {
return &tls.Config{
// Prefer TLS1.2 as the client minimum
MinVersion: tls.VersionTLS12,
CipherSuites: clientCipherSuites,
}
}
// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
func certPool(caFile string) (*x509.CertPool, error) {
// If we should verify the server, we need to load a trusted ca
certPool := x509.NewCertPool()
pem, err := ioutil.ReadFile(caFile)
if err != nil {
return nil, fmt.Errorf("Could not read CA certificate %q: %v", caFile, err)
}
if !certPool.AppendCertsFromPEM(pem) {
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
}
logrus.Debugf("Trusting %d certs", len(certPool.Subjects()))
return certPool, nil
}
// Client returns a TLS configuration meant to be used by a client.
func Client(options Options) (*tls.Config, error) {
tlsConfig := ClientDefault()
tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
if !options.InsecureSkipVerify && options.CAFile != "" {
CAs, err := certPool(options.CAFile)
if err != nil {
return nil, err
}
tlsConfig.RootCAs = CAs
}
if options.CertFile != "" || options.KeyFile != "" {
tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
if err != nil {
return nil, fmt.Errorf("Could not load X509 key pair: %v. Make sure the key is not encrypted", err)
}
tlsConfig.Certificates = []tls.Certificate{tlsCert}
}
return tlsConfig, nil
}
// Server returns a TLS configuration meant to be used by a server.
func Server(options Options) (*tls.Config, error) {
tlsConfig := ServerDefault()
tlsConfig.ClientAuth = options.ClientAuth
tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("Could not load X509 key pair (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err)
}
return nil, fmt.Errorf("Error reading X509 key pair (cert: %q, key: %q): %v. Make sure the key is not encrypted.", options.CertFile, options.KeyFile, err)
}
tlsConfig.Certificates = []tls.Certificate{tlsCert}
if options.ClientAuth >= tls.VerifyClientCertIfGiven {
CAs, err := certPool(options.CAFile)
if err != nil {
return nil, err
}
tlsConfig.ClientCAs = CAs
}
return tlsConfig, nil
}

View file

@ -3,7 +3,6 @@ package registry
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"io/ioutil"
@ -64,8 +63,11 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
for _, f := range fs {
if strings.HasSuffix(f.Name(), ".crt") {
if tlsConfig.RootCAs == nil {
// TODO(dmcgowan): Copy system pool
tlsConfig.RootCAs = x509.NewCertPool()
systemPool, err := tlsconfig.SystemCertPool()
if err != nil {
return fmt.Errorf("unable to get system cert pool: %v", err)
}
tlsConfig.RootCAs = systemPool
}
logrus.Debugf("crt: %s", filepath.Join(directory, f.Name()))
data, err := ioutil.ReadFile(filepath.Join(directory, f.Name()))

View file

@ -0,0 +1,21 @@
// +build go1.7
package tlsconfig
import (
"crypto/x509"
"runtime"
"github.com/Sirupsen/logrus"
)
// SystemCertPool returns a copy of the system cert pool,
// returns an error if failed to load or empty pool on windows.
func SystemCertPool() (*x509.CertPool, error) {
certpool, err := x509.SystemCertPool()
if err != nil && runtime.GOOS == "windows" {
logrus.Warnf("Unable to use system certificate pool: %v", err)
return x509.NewCertPool(), nil
}
return certpool, err
}

View file

@ -0,0 +1,16 @@
// +build !go1.7
package tlsconfig
import (
"crypto/x509"
"github.com/Sirupsen/logrus"
)
// SystemCertPool returns an new empty cert pool,
// accessing system cert pool is supported in go 1.7
func SystemCertPool() (*x509.CertPool, error) {
logrus.Warn("Unable to use system certificate pool: requires building with go 1.7 or later")
return x509.NewCertPool(), nil
}

View file

@ -68,10 +68,13 @@ func ClientDefault() *tls.Config {
// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
func certPool(caFile string) (*x509.CertPool, error) {
// If we should verify the server, we need to load a trusted ca
certPool := x509.NewCertPool()
certPool, err := SystemCertPool()
if err != nil {
return nil, fmt.Errorf("failed to read system certificates: %v", err)
}
pem, err := ioutil.ReadFile(caFile)
if err != nil {
return nil, fmt.Errorf("Could not read CA certificate %q: %v", caFile, err)
return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err)
}
if !certPool.AppendCertsFromPEM(pem) {
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)