github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/security/tls.go (about) 1 // Copyright 2014 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package security 12 13 import ( 14 "crypto/tls" 15 "crypto/x509" 16 17 "github.com/cockroachdb/errors" 18 ) 19 20 // EmbeddedCertsDir is the certs directory inside embedded assets. 21 // Embedded*{Cert,Key} are the filenames for embedded certs. 22 const ( 23 EmbeddedCertsDir = "test_certs" 24 EmbeddedCACert = "ca.crt" 25 EmbeddedCAKey = "ca.key" 26 EmbeddedClientCACert = "ca-client.crt" 27 EmbeddedClientCAKey = "ca-client.key" 28 EmbeddedUICACert = "ca-ui.crt" 29 EmbeddedUICAKey = "ca-ui.key" 30 EmbeddedNodeCert = "node.crt" 31 EmbeddedNodeKey = "node.key" 32 EmbeddedRootCert = "client.root.crt" 33 EmbeddedRootKey = "client.root.key" 34 EmbeddedTestUserCert = "client.testuser.crt" 35 EmbeddedTestUserKey = "client.testuser.key" 36 ) 37 38 // LoadServerTLSConfig creates a server TLSConfig by loading the CA and server certs. 39 // The following paths must be passed: 40 // - sslCA: path to the CA certificate 41 // - sslClientCA: path to the CA certificate to verify client certificates, 42 // can be the same as sslCA 43 // - sslCert: path to the server certificate 44 // - sslCertKey: path to the server key 45 // If the path is prefixed with "embedded=", load the embedded certs. 46 func LoadServerTLSConfig(sslCA, sslClientCA, sslCert, sslCertKey string) (*tls.Config, error) { 47 certPEM, err := assetLoaderImpl.ReadFile(sslCert) 48 if err != nil { 49 return nil, err 50 } 51 keyPEM, err := assetLoaderImpl.ReadFile(sslCertKey) 52 if err != nil { 53 return nil, err 54 } 55 caPEM, err := assetLoaderImpl.ReadFile(sslCA) 56 if err != nil { 57 return nil, err 58 } 59 clientCAPEM, err := assetLoaderImpl.ReadFile(sslClientCA) 60 if err != nil { 61 return nil, err 62 } 63 return newServerTLSConfig(certPEM, keyPEM, caPEM, clientCAPEM) 64 } 65 66 // newServerTLSConfig creates a server TLSConfig from the supplied byte strings containing 67 // - the certificate of this node (should be signed by the CA), 68 // - the private key of this node. 69 // - the certificate of the cluster CA, used to verify other server certificates 70 // - the certificate of the client CA, used to verify client certificates 71 // 72 // caClientPEM can be equal to caPEM (shared CA) or nil (use system CA pool). 73 func newServerTLSConfig(certPEM, keyPEM, caPEM, caClientPEM []byte) (*tls.Config, error) { 74 cfg, err := newBaseTLSConfigWithCertificate(certPEM, keyPEM, caPEM) 75 if err != nil { 76 return nil, err 77 } 78 cfg.ClientAuth = tls.VerifyClientCertIfGiven 79 80 if caClientPEM != nil { 81 certPool := x509.NewCertPool() 82 83 if !certPool.AppendCertsFromPEM(caClientPEM) { 84 return nil, errors.Errorf("failed to parse client CA PEM data to pool") 85 } 86 cfg.ClientCAs = certPool 87 } 88 89 // Use the default cipher suite from golang (RC4 is going away in 1.5). 90 // Prefer the server-specified suite. 91 cfg.PreferServerCipherSuites = true 92 // Should we disable session resumption? This may break forward secrecy. 93 // cfg.SessionTicketsDisabled = true 94 return cfg, nil 95 } 96 97 // newUIServerTLSConfig creates a server TLSConfig for the Admin UI. It does not 98 // use client authentication or a CA. 99 // It needs: 100 // - the server certificate (should be signed by the CA used by HTTP clients to the admin UI) 101 // - the private key for the certificate 102 func newUIServerTLSConfig(certPEM, keyPEM []byte) (*tls.Config, error) { 103 cfg, err := newBaseTLSConfigWithCertificate(certPEM, keyPEM, nil) 104 if err != nil { 105 return nil, err 106 } 107 108 // Use the default cipher suite from golang (RC4 is going away in 1.5). 109 // Prefer the server-specified suite. 110 cfg.PreferServerCipherSuites = true 111 // Should we disable session resumption? This may break forward secrecy. 112 // cfg.SessionTicketsDisabled = true 113 return cfg, nil 114 } 115 116 // LoadClientTLSConfig creates a client TLSConfig by loading the CA and client certs. 117 // The following paths must be passed: 118 // - sslCA: path to the CA certificate 119 // - sslCert: path to the client certificate 120 // - sslCertKey: path to the client key 121 // If the path is prefixed with "embedded=", load the embedded certs. 122 func LoadClientTLSConfig(sslCA, sslCert, sslCertKey string) (*tls.Config, error) { 123 certPEM, err := assetLoaderImpl.ReadFile(sslCert) 124 if err != nil { 125 return nil, err 126 } 127 keyPEM, err := assetLoaderImpl.ReadFile(sslCertKey) 128 if err != nil { 129 return nil, err 130 } 131 caPEM, err := assetLoaderImpl.ReadFile(sslCA) 132 if err != nil { 133 return nil, err 134 } 135 136 return newClientTLSConfig(certPEM, keyPEM, caPEM) 137 } 138 139 // newClientTLSConfig creates a client TLSConfig from the supplied byte strings containing: 140 // - the certificate of this client (should be signed by the CA), 141 // - the private key of this client. 142 // - the certificate of the cluster CA (use system cert pool if nil) 143 func newClientTLSConfig(certPEM, keyPEM, caPEM []byte) (*tls.Config, error) { 144 return newBaseTLSConfigWithCertificate(certPEM, keyPEM, caPEM) 145 } 146 147 // newUIClientTLSConfig creates a client TLSConfig to talk to the Admin UI. 148 // It does not include client certificates and takes an optional CA certificate. 149 func newUIClientTLSConfig(caPEM []byte) (*tls.Config, error) { 150 return newBaseTLSConfig(caPEM) 151 } 152 153 // newBaseTLSConfigWithCertificate returns a tls.Config initialized with the 154 // passed-in certificate and optional CA certificate. 155 func newBaseTLSConfigWithCertificate(certPEM, keyPEM, caPEM []byte) (*tls.Config, error) { 156 cert, err := tls.X509KeyPair(certPEM, keyPEM) 157 if err != nil { 158 return nil, err 159 } 160 161 cfg, err := newBaseTLSConfig(caPEM) 162 if err != nil { 163 return nil, err 164 } 165 166 cfg.Certificates = []tls.Certificate{cert} 167 return cfg, nil 168 } 169 170 // newBaseTLSConfig returns a tls.Config. If caPEM != nil, it is set in RootCAs. 171 func newBaseTLSConfig(caPEM []byte) (*tls.Config, error) { 172 var certPool *x509.CertPool 173 if caPEM != nil { 174 certPool = x509.NewCertPool() 175 176 if !certPool.AppendCertsFromPEM(caPEM) { 177 return nil, errors.Errorf("failed to parse PEM data to pool") 178 } 179 } 180 181 return &tls.Config{ 182 RootCAs: certPool, 183 184 // This is Go's default list of cipher suites (as of go 1.8.3), 185 // with the following differences: 186 // - 3DES-based cipher suites have been removed. This cipher is 187 // vulnerable to the Sweet32 attack and is sometimes reported by 188 // security scanners. (This is arguably a false positive since 189 // it will never be selected: Any TLS1.2 implementation MUST 190 // include at least one cipher higher in the priority list, but 191 // there's also no reason to keep it around) 192 // - AES is always prioritized over ChaCha20. Go makes this decision 193 // by default based on the presence or absence of hardware AES 194 // acceleration. 195 // TODO(bdarnell): do the same detection here. See 196 // https://github.com/golang/go/issues/21167 197 // 198 // Note that some TLS cipher suite guidance (such as Mozilla's[1]) 199 // recommend replacing the CBC_SHA suites below with CBC_SHA384 or 200 // CBC_SHA256 variants. We do not do this because Go does not 201 // currerntly implement the CBC_SHA384 suites, and its CBC_SHA256 202 // implementation is vulnerable to the Lucky13 attack and is disabled 203 // by default.[2] 204 // 205 // [1]: https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility 206 // [2]: https://github.com/golang/go/commit/48d8edb5b21db190f717e035b4d9ab61a077f9d7 207 CipherSuites: []uint16{ 208 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 209 tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 210 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 211 tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 212 tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 213 tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 214 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 215 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 216 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 217 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 218 tls.TLS_RSA_WITH_AES_128_GCM_SHA256, 219 tls.TLS_RSA_WITH_AES_256_GCM_SHA384, 220 tls.TLS_RSA_WITH_AES_128_CBC_SHA, 221 tls.TLS_RSA_WITH_AES_256_CBC_SHA, 222 }, 223 224 MinVersion: tls.VersionTLS12, 225 }, nil 226 }