David K. Bainbridge | 528b318 | 2017-01-23 08:51:59 -0800 | [diff] [blame] | 1 | // Copyright 2016 Canonical Ltd. |
| 2 | // Licensed under the LGPLv3, see LICENCE file for details. |
| 3 | |
| 4 | package utils |
| 5 | |
| 6 | import ( |
| 7 | "crypto/tls" |
| 8 | "net/http" |
| 9 | "time" |
| 10 | ) |
| 11 | |
| 12 | // NewHttpTLSTransport returns a new http.Transport constructed with the TLS config |
| 13 | // and the necessary parameters for Juju. |
| 14 | func NewHttpTLSTransport(tlsConfig *tls.Config) *http.Transport { |
| 15 | // See https://code.google.com/p/go/issues/detail?id=4677 |
| 16 | // We need to force the connection to close each time so that we don't |
| 17 | // hit the above Go bug. |
| 18 | transport := &http.Transport{ |
| 19 | Proxy: http.ProxyFromEnvironment, |
| 20 | TLSClientConfig: tlsConfig, |
| 21 | DisableKeepAlives: true, |
| 22 | TLSHandshakeTimeout: 10 * time.Second, |
| 23 | } |
| 24 | installHTTPDialShim(transport) |
| 25 | registerFileProtocol(transport) |
| 26 | return transport |
| 27 | } |
| 28 | |
| 29 | // knownGoodCipherSuites contains the list of secure cipher suites to use |
| 30 | // with tls.Config. This list matches those that Go 1.6 implements from |
| 31 | // https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations. |
| 32 | // |
| 33 | // https://tools.ietf.org/html/rfc7525#section-4.2 excludes RSA exchange completely |
| 34 | // so we could be more strict if all our clients will support |
| 35 | // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256/384. Unfortunately Go's crypto library |
| 36 | // is limited and doesn't support DHE-RSA-AES256-GCM-SHA384 and |
| 37 | // DHE-RSA-AES256-SHA256, which are part of the recommended set. |
| 38 | // |
| 39 | // Unfortunately we can't drop the RSA algorithms because our servers aren't |
| 40 | // generating ECDHE keys. |
| 41 | var knownGoodCipherSuites = []uint16{ |
| 42 | // These are technically useless for Juju, since we use an RSA certificate, |
| 43 | // but they also don't hurt anything, and supporting an ECDSA certificate |
| 44 | // could be useful in the future. |
| 45 | tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, |
| 46 | tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, |
| 47 | |
| 48 | tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, |
| 49 | tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, |
| 50 | |
| 51 | // Windows doesn't support GCM currently, so we need these for RSA support. |
| 52 | tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, |
| 53 | tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, |
| 54 | |
| 55 | // We need this so that we have at least one suite in common |
| 56 | // with the default gnutls installed for precise and trusty. |
| 57 | tls.TLS_RSA_WITH_AES_256_CBC_SHA, |
| 58 | } |
| 59 | |
| 60 | // SecureTLSConfig returns a tls.Config that conforms to Juju's security |
| 61 | // standards, so as to avoid known security vulnerabilities in certain |
| 62 | // configurations. |
| 63 | // |
| 64 | // Currently it excludes RC4 implementations from the available ciphersuites, |
| 65 | // requires ciphersuites that provide forward secrecy, and sets the minimum TLS |
| 66 | // version to 1.2. |
| 67 | func SecureTLSConfig() *tls.Config { |
| 68 | return &tls.Config{ |
| 69 | CipherSuites: knownGoodCipherSuites, |
| 70 | MinVersion: tls.VersionTLS12, |
| 71 | } |
| 72 | } |