Merge pull request #4269 from hashicorp/f-tls-remove-weak-standards
Configurable TLS cipher suites and versions; disallow weak ciphers
This commit is contained in:
commit
687c26093c
|
@ -9,6 +9,8 @@ IMPROVEMENTS:
|
||||||
image pulls [[GH-4192](https://github.com/hashicorp/nomad/issues/4192)]
|
image pulls [[GH-4192](https://github.com/hashicorp/nomad/issues/4192)]
|
||||||
* env: Default interpolation of optional meta fields of parameterized jobs to
|
* env: Default interpolation of optional meta fields of parameterized jobs to
|
||||||
an empty string rather than the field key. [[GH-3720](https://github.com/hashicorp/nomad/issues/3720)]
|
an empty string rather than the field key. [[GH-3720](https://github.com/hashicorp/nomad/issues/3720)]
|
||||||
|
* core: Add the option for operators to configure TLS versions and allowed
|
||||||
|
cipher suites. Default is a subset of safe ciphers and TLS 1.2 [[GH-4269](https://github.com/hashicorp/nomad/pull/4269)]
|
||||||
* core: Add a new [progress_deadline](https://www.nomadproject.io/docs/job-specification/update.html#progress_deadline) parameter to
|
* core: Add a new [progress_deadline](https://www.nomadproject.io/docs/job-specification/update.html#progress_deadline) parameter to
|
||||||
support rescheduling failed allocations during a deployment. This allows operators to specify a configurable deadline before which
|
support rescheduling failed allocations during a deployment. This allows operators to specify a configurable deadline before which
|
||||||
a deployment should see healthy allocations [[GH-4259](https://github.com/hashicorp/nomad/issues/4259)]
|
a deployment should see healthy allocations [[GH-4259](https://github.com/hashicorp/nomad/issues/4259)]
|
||||||
|
|
|
@ -399,11 +399,16 @@ func (c *Client) init() error {
|
||||||
func (c *Client) reloadTLSConnections(newConfig *nconfig.TLSConfig) error {
|
func (c *Client) reloadTLSConnections(newConfig *nconfig.TLSConfig) error {
|
||||||
var tlsWrap tlsutil.RegionWrapper
|
var tlsWrap tlsutil.RegionWrapper
|
||||||
if newConfig != nil && newConfig.EnableRPC {
|
if newConfig != nil && newConfig.EnableRPC {
|
||||||
tw, err := tlsutil.NewTLSConfiguration(newConfig).OutgoingTLSWrapper()
|
tw, err := tlsutil.NewTLSConfiguration(newConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tlsWrap = tw
|
|
||||||
|
twWrap, err := tw.OutgoingTLSWrapper()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tlsWrap = twWrap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the new tls wrapper.
|
// Store the new tls wrapper.
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
"github.com/hashicorp/hcl/hcl/ast"
|
||||||
"github.com/hashicorp/nomad/helper"
|
"github.com/hashicorp/nomad/helper"
|
||||||
|
"github.com/hashicorp/nomad/helper/tlsutil"
|
||||||
"github.com/hashicorp/nomad/nomad/structs/config"
|
"github.com/hashicorp/nomad/nomad/structs/config"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
@ -760,6 +761,8 @@ func parseTLSConfig(result **config.TLSConfig, list *ast.ObjectList) error {
|
||||||
"cert_file",
|
"cert_file",
|
||||||
"key_file",
|
"key_file",
|
||||||
"verify_https_client",
|
"verify_https_client",
|
||||||
|
"tls_cipher_suites",
|
||||||
|
"tls_min_version",
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := helper.CheckHCLKeys(listVal, valid); err != nil {
|
if err := helper.CheckHCLKeys(listVal, valid); err != nil {
|
||||||
|
@ -776,6 +779,14 @@ func parseTLSConfig(result **config.TLSConfig, list *ast.ObjectList) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := tlsutil.ParseCiphers(tlsConfig.TLSCipherSuites); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := tlsutil.ParseMinVersion(tlsConfig.TLSMinVersion); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
*result = &tlsConfig
|
*result = &tlsConfig
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,46 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/nomad/nomad/structs/config"
|
"github.com/hashicorp/nomad/nomad/structs/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// supportedTLSVersions are the current TLS versions that Nomad supports
|
||||||
|
var supportedTLSVersions = map[string]uint16{
|
||||||
|
"tls10": tls.VersionTLS10,
|
||||||
|
"tls11": tls.VersionTLS11,
|
||||||
|
"tls12": tls.VersionTLS12,
|
||||||
|
}
|
||||||
|
|
||||||
|
// supportedTLSCiphers are the complete list of TLS ciphers supported by Nomad
|
||||||
|
var supportedTLSCiphers = map[string]uint16{
|
||||||
|
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultTLSCiphers are the TLS Ciphers that are supported by default
|
||||||
|
var defaultTLSCiphers = []string{"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
}
|
||||||
|
|
||||||
// RegionSpecificWrapper is used to invoke a static Region and turns a
|
// RegionSpecificWrapper is used to invoke a static Region and turns a
|
||||||
// RegionWrapper into a Wrapper type.
|
// RegionWrapper into a Wrapper type.
|
||||||
func RegionSpecificWrapper(region string, tlsWrap RegionWrapper) Wrapper {
|
func RegionSpecificWrapper(region string, tlsWrap RegionWrapper) Wrapper {
|
||||||
|
@ -65,9 +100,26 @@ type Config struct {
|
||||||
|
|
||||||
// KeyLoader dynamically reloads TLS configuration.
|
// KeyLoader dynamically reloads TLS configuration.
|
||||||
KeyLoader *config.KeyLoader
|
KeyLoader *config.KeyLoader
|
||||||
|
|
||||||
|
// CipherSuites have a default safe configuration, or operators can override
|
||||||
|
// these values for acceptable safe alternatives.
|
||||||
|
CipherSuites []uint16
|
||||||
|
|
||||||
|
// MinVersion contains the minimum SSL/TLS version that is accepted.
|
||||||
|
MinVersion uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTLSConfiguration(newConf *config.TLSConfig) *Config {
|
func NewTLSConfiguration(newConf *config.TLSConfig) (*Config, error) {
|
||||||
|
ciphers, err := ParseCiphers(newConf.TLSCipherSuites)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
minVersion, err := ParseMinVersion(newConf.TLSMinVersion)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &Config{
|
return &Config{
|
||||||
VerifyIncoming: true,
|
VerifyIncoming: true,
|
||||||
VerifyOutgoing: true,
|
VerifyOutgoing: true,
|
||||||
|
@ -76,7 +128,9 @@ func NewTLSConfiguration(newConf *config.TLSConfig) *Config {
|
||||||
CertFile: newConf.CertFile,
|
CertFile: newConf.CertFile,
|
||||||
KeyFile: newConf.KeyFile,
|
KeyFile: newConf.KeyFile,
|
||||||
KeyLoader: newConf.GetKeyLoader(),
|
KeyLoader: newConf.GetKeyLoader(),
|
||||||
}
|
CipherSuites: ciphers,
|
||||||
|
MinVersion: minVersion,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendCA opens and parses the CA file and adds the certificates to
|
// AppendCA opens and parses the CA file and adds the certificates to
|
||||||
|
@ -132,6 +186,8 @@ func (c *Config) OutgoingTLSConfig() (*tls.Config, error) {
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
RootCAs: x509.NewCertPool(),
|
RootCAs: x509.NewCertPool(),
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
|
CipherSuites: c.CipherSuites,
|
||||||
|
MinVersion: c.MinVersion,
|
||||||
}
|
}
|
||||||
if c.VerifyServerHostname {
|
if c.VerifyServerHostname {
|
||||||
tlsConfig.InsecureSkipVerify = false
|
tlsConfig.InsecureSkipVerify = false
|
||||||
|
@ -250,6 +306,8 @@ func (c *Config) IncomingTLSConfig() (*tls.Config, error) {
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
ClientCAs: x509.NewCertPool(),
|
ClientCAs: x509.NewCertPool(),
|
||||||
ClientAuth: tls.NoClientCert,
|
ClientAuth: tls.NoClientCert,
|
||||||
|
CipherSuites: c.CipherSuites,
|
||||||
|
MinVersion: c.MinVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the CA cert if any
|
// Parse the CA cert if any
|
||||||
|
@ -279,3 +337,42 @@ func (c *Config) IncomingTLSConfig() (*tls.Config, error) {
|
||||||
|
|
||||||
return tlsConfig, nil
|
return tlsConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseCiphers parses ciphersuites from the comma-separated string into
|
||||||
|
// recognized slice
|
||||||
|
func ParseCiphers(cipherStr string) ([]uint16, error) {
|
||||||
|
suites := []uint16{}
|
||||||
|
|
||||||
|
cipherStr = strings.TrimSpace(cipherStr)
|
||||||
|
|
||||||
|
var ciphers []string
|
||||||
|
if cipherStr == "" {
|
||||||
|
ciphers = defaultTLSCiphers
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ciphers = strings.Split(cipherStr, ",")
|
||||||
|
}
|
||||||
|
for _, cipher := range ciphers {
|
||||||
|
c, ok := supportedTLSCiphers[cipher]
|
||||||
|
if !ok {
|
||||||
|
return suites, fmt.Errorf("unsupported TLS cipher %q", cipher)
|
||||||
|
}
|
||||||
|
suites = append(suites, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return suites, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseMinVersion parses the specified minimum TLS version for the Nomad agent
|
||||||
|
func ParseMinVersion(version string) (uint16, error) {
|
||||||
|
if version == "" {
|
||||||
|
return supportedTLSVersions["tls12"], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vers, ok := supportedTLSVersions[version]
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("unsupported TLS version %q", version)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vers, nil
|
||||||
|
}
|
||||||
|
|
|
@ -3,14 +3,17 @@ package tlsutil
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/nomad/nomad/structs/config"
|
"github.com/hashicorp/nomad/nomad/structs/config"
|
||||||
"github.com/hashicorp/yamux"
|
"github.com/hashicorp/yamux"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -412,3 +415,119 @@ func TestConfig_IncomingTLS_NoVerify(t *testing.T) {
|
||||||
t.Fatalf("unexpected client cert")
|
t.Fatalf("unexpected client cert")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfig_ParseCiphers_Valid(t *testing.T) {
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
validCiphers := strings.Join([]string{
|
||||||
|
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
|
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||||
|
}, ",")
|
||||||
|
|
||||||
|
expectedCiphers := []uint16{
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||||
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedCiphers, err := ParseCiphers(validCiphers)
|
||||||
|
require.Nil(err)
|
||||||
|
require.Equal(parsedCiphers, expectedCiphers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_ParseCiphers_Default(t *testing.T) {
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
expectedCiphers := []uint16{
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedCiphers, err := ParseCiphers("")
|
||||||
|
require.Nil(err)
|
||||||
|
require.Equal(parsedCiphers, expectedCiphers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_ParseCiphers_Invalid(t *testing.T) {
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
invalidCiphers := []string{"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
|
"TLS_RSA_WITH_RC4_128_SHA",
|
||||||
|
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cipher := range invalidCiphers {
|
||||||
|
parsedCiphers, err := ParseCiphers(cipher)
|
||||||
|
require.NotNil(err)
|
||||||
|
require.Equal(fmt.Sprintf("unsupported TLS cipher %q", cipher), err.Error())
|
||||||
|
require.Equal(0, len(parsedCiphers))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_ParseMinVersion_Valid(t *testing.T) {
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
validVersions := []string{"tls10",
|
||||||
|
"tls11",
|
||||||
|
"tls12",
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := map[string]uint16{
|
||||||
|
"tls10": tls.VersionTLS10,
|
||||||
|
"tls11": tls.VersionTLS11,
|
||||||
|
"tls12": tls.VersionTLS12,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, version := range validVersions {
|
||||||
|
parsedVersion, err := ParseMinVersion(version)
|
||||||
|
require.Nil(err)
|
||||||
|
require.Equal(expected[version], parsedVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_ParseMinVersion_Invalid(t *testing.T) {
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
invalidVersions := []string{"tls13",
|
||||||
|
"tls15",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, version := range invalidVersions {
|
||||||
|
parsedVersion, err := ParseMinVersion(version)
|
||||||
|
require.NotNil(err)
|
||||||
|
require.Equal(fmt.Sprintf("unsupported TLS version %q", version), err.Error())
|
||||||
|
require.Equal(uint16(0), parsedVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -450,7 +450,12 @@ func (s *Server) reloadTLSConnections(newTLSConfig *config.TLSConfig) error {
|
||||||
return fmt.Errorf("can't reload uninitialized RPC listener")
|
return fmt.Errorf("can't reload uninitialized RPC listener")
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConf := tlsutil.NewTLSConfiguration(newTLSConfig)
|
tlsConf, err := tlsutil.NewTLSConfiguration(newTLSConfig)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Printf("[ERR] nomad: unable to create TLS configuration %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
incomingTLS, tlsWrap, err := getTLSConf(newTLSConfig.EnableRPC, tlsConf)
|
incomingTLS, tlsWrap, err := getTLSConf(newTLSConfig.EnableRPC, tlsConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Printf("[ERR] nomad: unable to reset TLS context %s", err)
|
s.logger.Printf("[ERR] nomad: unable to reset TLS context %s", err)
|
||||||
|
|
|
@ -55,6 +55,14 @@ type TLSConfig struct {
|
||||||
// Checksum is a MD5 hash of the certificate CA File, Certificate file, and
|
// Checksum is a MD5 hash of the certificate CA File, Certificate file, and
|
||||||
// key file.
|
// key file.
|
||||||
Checksum string
|
Checksum string
|
||||||
|
|
||||||
|
// TLSCipherSuites are operator-defined ciphers to be used in Nomad TLS
|
||||||
|
// connections
|
||||||
|
TLSCipherSuites string `mapstructure:"tls_cipher_suites"`
|
||||||
|
|
||||||
|
// TLSMinVersion is used to set the minimum TLS version used for TLS
|
||||||
|
// connections. Should be either "tls10", "tls11", or "tls12".
|
||||||
|
TLSMinVersion string `mapstructure:"tls_min_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeyLoader struct {
|
type KeyLoader struct {
|
||||||
|
@ -147,6 +155,9 @@ func (t *TLSConfig) Copy() *TLSConfig {
|
||||||
new.RPCUpgradeMode = t.RPCUpgradeMode
|
new.RPCUpgradeMode = t.RPCUpgradeMode
|
||||||
new.VerifyHTTPSClient = t.VerifyHTTPSClient
|
new.VerifyHTTPSClient = t.VerifyHTTPSClient
|
||||||
|
|
||||||
|
new.TLSCipherSuites = t.TLSCipherSuites
|
||||||
|
new.TLSMinVersion = t.TLSMinVersion
|
||||||
|
|
||||||
new.SetChecksum()
|
new.SetChecksum()
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
|
@ -174,6 +174,7 @@ func TestTLS_Copy(t *testing.T) {
|
||||||
CAFile: cafile,
|
CAFile: cafile,
|
||||||
CertFile: foocert,
|
CertFile: foocert,
|
||||||
KeyFile: fookey,
|
KeyFile: fookey,
|
||||||
|
TLSCipherSuites: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||||
}
|
}
|
||||||
a.SetChecksum()
|
a.SetChecksum()
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,15 @@ the [Agent's Gossip and RPC Encryption](/docs/agent/encryption.html).
|
||||||
cluster is being upgraded to TLS, and removed after the migration is
|
cluster is being upgraded to TLS, and removed after the migration is
|
||||||
complete. This allows the agent to accept both TLS and plaintext traffic.
|
complete. This allows the agent to accept both TLS and plaintext traffic.
|
||||||
|
|
||||||
|
- `tls_cipher_suites` - Specifies the TLS cipher suites that will be used by
|
||||||
|
the agent. Known insecure ciphers are disabled (3DES and RC4). By default,
|
||||||
|
an agent is configured to use TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, and
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384.
|
||||||
|
|
||||||
|
- `tls_min_version` - Specifies the minimum supported version of TLS. Accepted
|
||||||
|
values are "tls10", "tls11", "tls12". Defaults to TLS 1.2.
|
||||||
|
|
||||||
- `verify_https_client` `(bool: false)` - Specifies agents should require
|
- `verify_https_client` `(bool: false)` - Specifies agents should require
|
||||||
client certificates for all incoming HTTPS requests. The client certificates
|
client certificates for all incoming HTTPS requests. The client certificates
|
||||||
must be signed by the same CA as Nomad.
|
must be signed by the same CA as Nomad.
|
||||||
|
|
Loading…
Reference in New Issue