github.com/chenchun/docker@v1.3.2-0.20150629222414-20467faf132b/pkg/tlsconfig/config.go (about) 1 // Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. 2 // 3 // As a reminder from https://golang.org/pkg/crypto/tls/#Config: 4 // 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. 5 // A Config may be reused; the tls package will also not modify it. 6 package tlsconfig 7 8 import ( 9 "crypto/tls" 10 "crypto/x509" 11 "fmt" 12 "io/ioutil" 13 "os" 14 15 "github.com/Sirupsen/logrus" 16 ) 17 18 // Options represents the information needed to create client and server TLS configurations. 19 type Options struct { 20 InsecureSkipVerify bool 21 ClientAuth tls.ClientAuthType 22 CAFile string 23 CertFile string 24 KeyFile string 25 } 26 27 // Extra (server-side) accepted CBC cipher suites - will phase out in the future 28 var acceptedCBCCiphers = []uint16{ 29 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 30 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 31 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 33 tls.TLS_RSA_WITH_AES_256_CBC_SHA, 34 tls.TLS_RSA_WITH_AES_128_CBC_SHA, 35 } 36 37 // Client TLS cipher suites (dropping CBC ciphers for client preferred suite set) 38 var clientCipherSuites = []uint16{ 39 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 40 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 41 } 42 43 // For use by code which already has a crypto/tls options struct but wants to 44 // use a commonly accepted set of TLS cipher suites, with known weak algorithms removed 45 var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...) 46 47 // ServerDefault is a secure-enough TLS configuration for the server TLS configuration. 48 var ServerDefault = tls.Config{ 49 // Avoid fallback to SSL protocols < TLS1.0 50 MinVersion: tls.VersionTLS10, 51 PreferServerCipherSuites: true, 52 CipherSuites: DefaultServerAcceptedCiphers, 53 } 54 55 // ClientDefault is a secure-enough TLS configuration for the client TLS configuration. 56 var ClientDefault = tls.Config{ 57 // Prefer TLS1.2 as the client minimum 58 MinVersion: tls.VersionTLS12, 59 CipherSuites: clientCipherSuites, 60 } 61 62 // certPool returns an X.509 certificate pool from `caFile`, the certificate file. 63 func certPool(caFile string) (*x509.CertPool, error) { 64 // If we should verify the server, we need to load a trusted ca 65 certPool := x509.NewCertPool() 66 pem, err := ioutil.ReadFile(caFile) 67 if err != nil { 68 return nil, fmt.Errorf("Could not read CA certificate %s: %v", caFile, err) 69 } 70 if !certPool.AppendCertsFromPEM(pem) { 71 return nil, fmt.Errorf("failed to append certificates from PEM file: %s", caFile) 72 } 73 s := certPool.Subjects() 74 subjects := make([]string, len(s)) 75 for i, subject := range s { 76 subjects[i] = string(subject) 77 } 78 logrus.Debugf("Trusting certs with subjects: %v", subjects) 79 return certPool, nil 80 } 81 82 // Client returns a TLS configuration meant to be used by a client. 83 func Client(options Options) (*tls.Config, error) { 84 tlsConfig := ClientDefault 85 tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify 86 if !options.InsecureSkipVerify { 87 CAs, err := certPool(options.CAFile) 88 if err != nil { 89 return nil, err 90 } 91 tlsConfig.RootCAs = CAs 92 } 93 94 if options.CertFile != "" && options.KeyFile != "" { 95 tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile) 96 if err != nil { 97 return nil, fmt.Errorf("Could not load X509 key pair: %v. Make sure the key is not encrypted", err) 98 } 99 tlsConfig.Certificates = []tls.Certificate{tlsCert} 100 } 101 102 return &tlsConfig, nil 103 } 104 105 // Server returns a TLS configuration meant to be used by a server. 106 func Server(options Options) (*tls.Config, error) { 107 tlsConfig := ServerDefault 108 tlsConfig.ClientAuth = options.ClientAuth 109 tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile) 110 if err != nil { 111 if os.IsNotExist(err) { 112 return nil, fmt.Errorf("Could not load X509 key pair (%s, %s): %v", options.CertFile, options.KeyFile, err) 113 } 114 return nil, fmt.Errorf("Error reading X509 key pair (%s, %s): %v. Make sure the key is not encrypted.", options.CertFile, options.KeyFile, err) 115 } 116 tlsConfig.Certificates = []tls.Certificate{tlsCert} 117 if options.ClientAuth >= tls.VerifyClientCertIfGiven { 118 CAs, err := certPool(options.CAFile) 119 if err != nil { 120 return nil, err 121 } 122 tlsConfig.ClientCAs = CAs 123 } 124 return &tlsConfig, nil 125 }