Support per-listener TLS configuration ⚙️ (#12504)

Introduces the capability to configure TLS differently for Consul's
listeners/ports (i.e. HTTPS, gRPC, and the internal multiplexed RPC
port) which is useful in scenarios where you may want the HTTPS or
gRPC interfaces to present a certificate signed by a well-known/public
CA, rather than the certificate used for internal communication which
must have a SAN in the form `server.<dc>.consul`.
This commit is contained in:
Dan Upton 2022-03-18 10:46:58 +00:00 committed by GitHub
parent 27711fe5c7
commit 57f0f42733
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 2886 additions and 1866 deletions

7
.changelog/12504.txt Normal file
View File

@ -0,0 +1,7 @@
```release-note:feature
tls: it is now possible to configure TLS differently for each of Consul's listeners (i.e. HTTPS, gRPC and the internal multiplexed RPC listener) using the `tls` stanza
```
```release-note:deprecation
config: setting `cert_file`, `key_file`, `ca_file`, `ca_path`, `tls_min_version`, `tls_cipher_suites`, `verify_incoming`, `verify_incoming_rpc`, `verify_incoming_https`, `verify_outgoing` and `verify_server_hostname` at the top-level is now deprecated, use the `tls` stanza instead
```

View File

@ -489,7 +489,7 @@ func (a *Agent) Start(ctx context.Context) error {
c.NodeID = a.config.NodeID
a.config = c
if err := a.tlsConfigurator.Update(a.config.ToTLSUtilConfig()); err != nil {
if err := a.tlsConfigurator.Update(a.config.TLS); err != nil {
return fmt.Errorf("Failed to load TLS configurations after applying auto-config settings: %w", err)
}
@ -1218,7 +1218,7 @@ func newConsulConfig(runtimeCfg *config.RuntimeConfig, logger hclog.Logger) (*co
}
cfg.Build = fmt.Sprintf("%s%s:%s", runtimeCfg.Version, runtimeCfg.VersionPrerelease, revision)
cfg.TLSConfig = runtimeCfg.ToTLSUtilConfig()
cfg.TLSConfig = runtimeCfg.TLS
cfg.DefaultQueryTime = runtimeCfg.DefaultQueryTime
cfg.MaxQueryTime = runtimeCfg.MaxQueryTime
@ -3748,7 +3748,7 @@ func (a *Agent) reloadConfigInternal(newCfg *config.RuntimeConfig) error {
// the checks and service registrations.
a.tokens.Load(newCfg.ACLTokens, a.logger)
if err := a.tlsConfigurator.Update(newCfg.ToTLSUtilConfig()); err != nil {
if err := a.tlsConfigurator.Update(newCfg.TLS); err != nil {
return fmt.Errorf("Failed reloading tls configuration: %s", err)
}

View File

@ -822,7 +822,7 @@ func startedAutoConfig(t *testing.T, autoEncrypt bool) testAutoConfig {
if !autoEncrypt {
// auto-encrypt doesn't modify the config but rather sets the value
// in the TLS configurator
require.True(t, cfg.VerifyServerHostname)
require.True(t, cfg.TLS.InternalRPC.VerifyServerHostname)
}
ctx, cancel := context.WithCancel(context.Background())

View File

@ -81,11 +81,12 @@ func translateConfig(c *pbconfig.Config) config.Config {
}
if t := c.TLS; t != nil {
result.VerifyOutgoing = &t.VerifyOutgoing
result.VerifyServerHostname = &t.VerifyServerHostname
result.TLSMinVersion = stringPtrOrNil(t.MinVersion)
result.TLSCipherSuites = stringPtrOrNil(t.CipherSuites)
result.TLSPreferServerCipherSuites = &t.PreferServerCipherSuites
result.TLS.Defaults = config.TLSProtocolConfig{
VerifyOutgoing: &t.VerifyOutgoing,
TLSMinVersion: stringPtrOrNil(t.MinVersion),
TLSCipherSuites: stringPtrOrNil(t.CipherSuites),
}
result.TLS.InternalRPC.VerifyServerHostname = &t.VerifyServerHostname
}
return result

View File

@ -88,28 +88,32 @@ func TestTranslateConfig(t *testing.T) {
},
},
TLS: &pbconfig.TLS{
VerifyOutgoing: true,
VerifyServerHostname: true,
CipherSuites: "stuff",
MinVersion: "tls13",
PreferServerCipherSuites: true,
VerifyOutgoing: true,
VerifyServerHostname: true,
CipherSuites: "stuff",
MinVersion: "tls13",
},
}
expected := config.Config{
Datacenter: stringPointer("abc"),
PrimaryDatacenter: stringPointer("def"),
NodeName: stringPointer("ghi"),
SegmentName: stringPointer("jkl"),
RetryJoinLAN: []string{"10.0.0.1"},
EncryptKey: stringPointer("blarg"),
EncryptVerifyIncoming: boolPointer(true),
EncryptVerifyOutgoing: boolPointer(true),
VerifyOutgoing: boolPointer(true),
VerifyServerHostname: boolPointer(true),
TLSCipherSuites: stringPointer("stuff"),
TLSMinVersion: stringPointer("tls13"),
TLSPreferServerCipherSuites: boolPointer(true),
Datacenter: stringPointer("abc"),
PrimaryDatacenter: stringPointer("def"),
NodeName: stringPointer("ghi"),
SegmentName: stringPointer("jkl"),
RetryJoinLAN: []string{"10.0.0.1"},
EncryptKey: stringPointer("blarg"),
EncryptVerifyIncoming: boolPointer(true),
EncryptVerifyOutgoing: boolPointer(true),
TLS: config.TLS{
Defaults: config.TLSProtocolConfig{
VerifyOutgoing: boolPointer(true),
TLSCipherSuites: stringPointer("stuff"),
TLSMinVersion: stringPointer("tls13"),
},
InternalRPC: config.TLSProtocolConfig{
VerifyServerHostname: boolPointer(true),
},
},
ACL: config.ACL{
Enabled: boolPointer(true),
PolicyTTL: stringPointer("1s"),

View File

@ -747,18 +747,6 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
enableRemoteScriptChecks := boolVal(c.EnableScriptChecks)
enableLocalScriptChecks := boolValWithDefault(c.EnableLocalScriptChecks, enableRemoteScriptChecks)
// VerifyServerHostname implies VerifyOutgoing
verifyServerName := boolVal(c.VerifyServerHostname)
verifyOutgoing := boolVal(c.VerifyOutgoing)
if verifyServerName {
// Setting only verify_server_hostname is documented to imply
// verify_outgoing. If it doesn't then we risk sending communication over TCP
// when we documented it as forcing TLS for RPCs. Enforce this here rather
// than in several different places through the code that need to reason
// about it. (See CVE-2018-19653)
verifyOutgoing = true
}
var configEntries []structs.ConfigEntry
if len(c.ConfigEntries.Bootstrap) > 0 {
@ -963,9 +951,6 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
c.Cache.EntryFetchMaxBurst, cache.DefaultEntryFetchMaxBurst,
),
},
CAFile: stringVal(c.CAFile),
CAPath: stringVal(c.CAPath),
CertFile: stringVal(c.CertFile),
CheckUpdateInterval: b.durationVal("check_update_interval", c.CheckUpdateInterval),
CheckOutputMaxSize: intValWithDefault(c.CheckOutputMaxSize, 4096),
Checks: checks,
@ -1012,7 +997,6 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
GRPCAddrs: grpcAddrs,
HTTPMaxConnsPerClient: intVal(c.Limits.HTTPMaxConnsPerClient),
HTTPSHandshakeTimeout: b.durationVal("limits.https_handshake_timeout", c.Limits.HTTPSHandshakeTimeout),
KeyFile: stringVal(c.KeyFile),
KVMaxValueSize: uint64Val(c.Limits.KVMaxValueSize),
LeaveDrainTime: b.durationVal("performance.leave_drain_time", c.Performance.LeaveDrainTime),
LeaveOnTerm: leaveOnTerm,
@ -1026,72 +1010,69 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
LogRotateBytes: intVal(c.LogRotateBytes),
LogRotateMaxFiles: intVal(c.LogRotateMaxFiles),
},
MaxQueryTime: b.durationVal("max_query_time", c.MaxQueryTime),
NodeID: types.NodeID(stringVal(c.NodeID)),
NodeMeta: c.NodeMeta,
NodeName: b.nodeName(c.NodeName),
ReadReplica: boolVal(c.ReadReplica),
PidFile: stringVal(c.PidFile),
PrimaryDatacenter: primaryDatacenter,
PrimaryGateways: b.expandAllOptionalAddrs("primary_gateways", c.PrimaryGateways),
PrimaryGatewaysInterval: b.durationVal("primary_gateways_interval", c.PrimaryGatewaysInterval),
RPCAdvertiseAddr: rpcAdvertiseAddr,
RPCBindAddr: rpcBindAddr,
RPCHandshakeTimeout: b.durationVal("limits.rpc_handshake_timeout", c.Limits.RPCHandshakeTimeout),
RPCHoldTimeout: b.durationVal("performance.rpc_hold_timeout", c.Performance.RPCHoldTimeout),
RPCMaxBurst: intVal(c.Limits.RPCMaxBurst),
RPCMaxConnsPerClient: intVal(c.Limits.RPCMaxConnsPerClient),
RPCProtocol: intVal(c.RPCProtocol),
RPCRateLimit: rate.Limit(float64Val(c.Limits.RPCRate)),
RPCConfig: consul.RPCConfig{EnableStreaming: boolValWithDefault(c.RPC.EnableStreaming, serverMode)},
RaftProtocol: intVal(c.RaftProtocol),
RaftSnapshotThreshold: intVal(c.RaftSnapshotThreshold),
RaftSnapshotInterval: b.durationVal("raft_snapshot_interval", c.RaftSnapshotInterval),
RaftTrailingLogs: intVal(c.RaftTrailingLogs),
ReconnectTimeoutLAN: b.durationVal("reconnect_timeout", c.ReconnectTimeoutLAN),
ReconnectTimeoutWAN: b.durationVal("reconnect_timeout_wan", c.ReconnectTimeoutWAN),
RejoinAfterLeave: boolVal(c.RejoinAfterLeave),
RetryJoinIntervalLAN: b.durationVal("retry_interval", c.RetryJoinIntervalLAN),
RetryJoinIntervalWAN: b.durationVal("retry_interval_wan", c.RetryJoinIntervalWAN),
RetryJoinLAN: b.expandAllOptionalAddrs("retry_join", c.RetryJoinLAN),
RetryJoinMaxAttemptsLAN: intVal(c.RetryJoinMaxAttemptsLAN),
RetryJoinMaxAttemptsWAN: intVal(c.RetryJoinMaxAttemptsWAN),
RetryJoinWAN: b.expandAllOptionalAddrs("retry_join_wan", c.RetryJoinWAN),
SegmentName: stringVal(c.SegmentName),
Segments: segments,
SegmentLimit: intVal(c.SegmentLimit),
SerfAdvertiseAddrLAN: serfAdvertiseAddrLAN,
SerfAdvertiseAddrWAN: serfAdvertiseAddrWAN,
SerfAllowedCIDRsLAN: serfAllowedCIDRSLAN,
SerfAllowedCIDRsWAN: serfAllowedCIDRSWAN,
SerfBindAddrLAN: serfBindAddrLAN,
SerfBindAddrWAN: serfBindAddrWAN,
SerfPortLAN: serfPortLAN,
SerfPortWAN: serfPortWAN,
ServerMode: serverMode,
ServerName: stringVal(c.ServerName),
ServerPort: serverPort,
Services: services,
SessionTTLMin: b.durationVal("session_ttl_min", c.SessionTTLMin),
SkipLeaveOnInt: skipLeaveOnInt,
StartJoinAddrsLAN: b.expandAllOptionalAddrs("start_join", c.StartJoinAddrsLAN),
StartJoinAddrsWAN: b.expandAllOptionalAddrs("start_join_wan", c.StartJoinAddrsWAN),
TLSCipherSuites: b.tlsCipherSuites("tls_cipher_suites", c.TLSCipherSuites),
TLSMinVersion: stringVal(c.TLSMinVersion),
TLSPreferServerCipherSuites: boolVal(c.TLSPreferServerCipherSuites),
TaggedAddresses: c.TaggedAddresses,
TranslateWANAddrs: boolVal(c.TranslateWANAddrs),
TxnMaxReqLen: uint64Val(c.Limits.TxnMaxReqLen),
UIConfig: b.uiConfigVal(c.UIConfig),
UnixSocketGroup: stringVal(c.UnixSocket.Group),
UnixSocketMode: stringVal(c.UnixSocket.Mode),
UnixSocketUser: stringVal(c.UnixSocket.User),
VerifyIncoming: boolVal(c.VerifyIncoming),
VerifyIncomingHTTPS: boolVal(c.VerifyIncomingHTTPS),
VerifyIncomingRPC: boolVal(c.VerifyIncomingRPC),
VerifyOutgoing: verifyOutgoing,
VerifyServerHostname: verifyServerName,
Watches: c.Watches,
MaxQueryTime: b.durationVal("max_query_time", c.MaxQueryTime),
NodeID: types.NodeID(stringVal(c.NodeID)),
NodeMeta: c.NodeMeta,
NodeName: b.nodeName(c.NodeName),
ReadReplica: boolVal(c.ReadReplica),
PidFile: stringVal(c.PidFile),
PrimaryDatacenter: primaryDatacenter,
PrimaryGateways: b.expandAllOptionalAddrs("primary_gateways", c.PrimaryGateways),
PrimaryGatewaysInterval: b.durationVal("primary_gateways_interval", c.PrimaryGatewaysInterval),
RPCAdvertiseAddr: rpcAdvertiseAddr,
RPCBindAddr: rpcBindAddr,
RPCHandshakeTimeout: b.durationVal("limits.rpc_handshake_timeout", c.Limits.RPCHandshakeTimeout),
RPCHoldTimeout: b.durationVal("performance.rpc_hold_timeout", c.Performance.RPCHoldTimeout),
RPCMaxBurst: intVal(c.Limits.RPCMaxBurst),
RPCMaxConnsPerClient: intVal(c.Limits.RPCMaxConnsPerClient),
RPCProtocol: intVal(c.RPCProtocol),
RPCRateLimit: rate.Limit(float64Val(c.Limits.RPCRate)),
RPCConfig: consul.RPCConfig{EnableStreaming: boolValWithDefault(c.RPC.EnableStreaming, serverMode)},
RaftProtocol: intVal(c.RaftProtocol),
RaftSnapshotThreshold: intVal(c.RaftSnapshotThreshold),
RaftSnapshotInterval: b.durationVal("raft_snapshot_interval", c.RaftSnapshotInterval),
RaftTrailingLogs: intVal(c.RaftTrailingLogs),
ReconnectTimeoutLAN: b.durationVal("reconnect_timeout", c.ReconnectTimeoutLAN),
ReconnectTimeoutWAN: b.durationVal("reconnect_timeout_wan", c.ReconnectTimeoutWAN),
RejoinAfterLeave: boolVal(c.RejoinAfterLeave),
RetryJoinIntervalLAN: b.durationVal("retry_interval", c.RetryJoinIntervalLAN),
RetryJoinIntervalWAN: b.durationVal("retry_interval_wan", c.RetryJoinIntervalWAN),
RetryJoinLAN: b.expandAllOptionalAddrs("retry_join", c.RetryJoinLAN),
RetryJoinMaxAttemptsLAN: intVal(c.RetryJoinMaxAttemptsLAN),
RetryJoinMaxAttemptsWAN: intVal(c.RetryJoinMaxAttemptsWAN),
RetryJoinWAN: b.expandAllOptionalAddrs("retry_join_wan", c.RetryJoinWAN),
SegmentName: stringVal(c.SegmentName),
Segments: segments,
SegmentLimit: intVal(c.SegmentLimit),
SerfAdvertiseAddrLAN: serfAdvertiseAddrLAN,
SerfAdvertiseAddrWAN: serfAdvertiseAddrWAN,
SerfAllowedCIDRsLAN: serfAllowedCIDRSLAN,
SerfAllowedCIDRsWAN: serfAllowedCIDRSWAN,
SerfBindAddrLAN: serfBindAddrLAN,
SerfBindAddrWAN: serfBindAddrWAN,
SerfPortLAN: serfPortLAN,
SerfPortWAN: serfPortWAN,
ServerMode: serverMode,
ServerName: stringVal(c.ServerName),
ServerPort: serverPort,
Services: services,
SessionTTLMin: b.durationVal("session_ttl_min", c.SessionTTLMin),
SkipLeaveOnInt: skipLeaveOnInt,
StartJoinAddrsLAN: b.expandAllOptionalAddrs("start_join", c.StartJoinAddrsLAN),
StartJoinAddrsWAN: b.expandAllOptionalAddrs("start_join_wan", c.StartJoinAddrsWAN),
TaggedAddresses: c.TaggedAddresses,
TranslateWANAddrs: boolVal(c.TranslateWANAddrs),
TxnMaxReqLen: uint64Val(c.Limits.TxnMaxReqLen),
UIConfig: b.uiConfigVal(c.UIConfig),
UnixSocketGroup: stringVal(c.UnixSocket.Group),
UnixSocketMode: stringVal(c.UnixSocket.Mode),
UnixSocketUser: stringVal(c.UnixSocket.User),
Watches: c.Watches,
}
rt.TLS, err = b.buildTLSConfig(rt, c.TLS)
if err != nil {
return RuntimeConfig{}, err
}
rt.UseStreamingBackend = boolValWithDefault(c.UseStreamingBackend, true)
@ -1477,10 +1458,8 @@ func (b *builder) validate(rt RuntimeConfig) error {
b.warn("rpc.enable_streaming = true has no effect when not running in server mode")
}
if rt.AutoEncryptAllowTLS {
if !rt.VerifyIncoming && !rt.VerifyIncomingRPC {
b.warn("if auto_encrypt.allow_tls is turned on, either verify_incoming or verify_incoming_rpc should be enabled. It is necessary to turn it off during a migration to TLS, but it should definitely be turned on afterwards.")
}
if rt.AutoEncryptAllowTLS && !rt.TLS.InternalRPC.VerifyIncoming {
b.warn("if auto_encrypt.allow_tls is turned on, tls.internal_rpc.verify_incoming should be enabled (either explicitly or via tls.defaults.verify_incoming). It is necessary to turn it off during a migration to TLS, but it should definitely be turned on afterwards.")
}
if err := checkLimitsFromMaxConnsPerClient(rt.HTTPMaxConnsPerClient); err != nil {
@ -2319,7 +2298,7 @@ func (b *builder) validateAutoConfig(rt RuntimeConfig) error {
// Right now we require TLS as everything we are going to transmit via auto-config is sensitive. Signed Certificates, Tokens
// and other encryption keys. This must be transmitted over a secure connection so we don't allow doing otherwise.
if !rt.VerifyOutgoing {
if !rt.TLS.InternalRPC.VerifyOutgoing {
return fmt.Errorf("auto_config.enabled cannot be set without configuring TLS for server communications")
}
@ -2366,7 +2345,7 @@ func validateAutoConfigAuthorizer(rt RuntimeConfig) error {
// Right now we require TLS as everything we are going to transmit via auto-config is sensitive. Signed Certificates, Tokens
// and other encryption keys. This must be transmitted over a secure connection so we don't allow doing otherwise.
if rt.CertFile == "" {
if rt.TLS.InternalRPC.CertFile == "" {
return fmt.Errorf("auto_config.authorization.enabled cannot be set without providing a TLS certificate for the server")
}
@ -2475,3 +2454,75 @@ func validateAbsoluteURLPath(p string) error {
return nil
}
func (b *builder) buildTLSConfig(rt RuntimeConfig, t TLS) (tlsutil.Config, error) {
var c tlsutil.Config
// Consul makes no outgoing connections to the public gRPC port (internal gRPC
// traffic goes through the multiplexed internal RPC port) so return an error
// rather than let the user think this setting is going to do anything useful.
if t.GRPC.VerifyOutgoing != nil {
return c, errors.New("verify_outgoing is not valid in the tls.grpc stanza")
}
// Similarly, only the internal RPC configuration honors VerifyServerHostname
// so we call it out here too.
if t.Defaults.VerifyServerHostname != nil || t.GRPC.VerifyServerHostname != nil || t.HTTPS.VerifyServerHostname != nil {
return c, errors.New("verify_server_hostname is only valid in the tls.internal_rpc stanza")
}
// TLS is only enabled on the gRPC listener if there's an HTTPS port configured
// for historic and backwards-compatibility reasons.
if rt.HTTPSPort <= 0 && (t.GRPC != TLSProtocolConfig{}) {
b.warn("tls.grpc was provided but TLS will NOT be enabled on the gRPC listener without an HTTPS listener configured (e.g. via ports.https)")
}
defaultCipherSuites := b.tlsCipherSuites("tls.defaults.tls_cipher_suites", t.Defaults.TLSCipherSuites)
mapCommon := func(name string, src TLSProtocolConfig, dst *tlsutil.ProtocolConfig) {
dst.CAPath = stringValWithDefault(src.CAPath, stringVal(t.Defaults.CAPath))
dst.CAFile = stringValWithDefault(src.CAFile, stringVal(t.Defaults.CAFile))
dst.CertFile = stringValWithDefault(src.CertFile, stringVal(t.Defaults.CertFile))
dst.KeyFile = stringValWithDefault(src.KeyFile, stringVal(t.Defaults.KeyFile))
dst.TLSMinVersion = stringValWithDefault(src.TLSMinVersion, stringVal(t.Defaults.TLSMinVersion))
dst.VerifyIncoming = boolValWithDefault(src.VerifyIncoming, boolVal(t.Defaults.VerifyIncoming))
// We prevent this from being set explicity in the tls.grpc stanza above, but
// let's also prevent it from getting the tls.defaults value to avoid confusion
// if we decide to support it in the future.
if name != "grpc" {
dst.VerifyOutgoing = boolValWithDefault(src.VerifyOutgoing, boolVal(t.Defaults.VerifyOutgoing))
}
if src.TLSCipherSuites == nil {
dst.CipherSuites = defaultCipherSuites
} else {
dst.CipherSuites = b.tlsCipherSuites(
fmt.Sprintf("tls.%s.tls_cipher_suites", name),
src.TLSCipherSuites,
)
}
}
mapCommon("internal_rpc", t.InternalRPC, &c.InternalRPC)
c.InternalRPC.VerifyServerHostname = boolVal(t.InternalRPC.VerifyServerHostname)
// Setting only verify_server_hostname is documented to imply verify_outgoing.
// If it doesn't then we risk sending communication over plain TCP when we
// documented it as forcing TLS for RPCs. Enforce this here rather than in
// several different places through the code that need to reason about it.
//
// See: CVE-2018-19653
c.InternalRPC.VerifyOutgoing = c.InternalRPC.VerifyOutgoing || c.InternalRPC.VerifyServerHostname
mapCommon("https", t.HTTPS, &c.HTTPS)
mapCommon("grpc", t.GRPC, &c.GRPC)
c.ServerName = rt.ServerName
c.NodeName = rt.NodeName
c.Domain = rt.DNSDomain
c.EnableAgentTLSForChecks = rt.EnableAgentTLSForChecks
c.AutoTLS = rt.AutoEncryptTLS || rt.AutoConfig.Enabled
return c, nil
}

View File

@ -147,9 +147,6 @@ type Config struct {
Bootstrap *bool `mapstructure:"bootstrap"`
BootstrapExpect *int `mapstructure:"bootstrap_expect"`
Cache Cache `mapstructure:"cache"`
CAFile *string `mapstructure:"ca_file"`
CAPath *string `mapstructure:"ca_path"`
CertFile *string `mapstructure:"cert_file"`
Check *CheckDefinition `mapstructure:"check"` // needs to be a pointer to avoid partial merges
CheckOutputMaxSize *int `mapstructure:"check_output_max_size"`
CheckUpdateInterval *string `mapstructure:"check_update_interval"`
@ -186,7 +183,6 @@ type Config struct {
GossipLAN GossipLANConfig `mapstructure:"gossip_lan"`
GossipWAN GossipWANConfig `mapstructure:"gossip_wan"`
HTTPConfig HTTPConfig `mapstructure:"http_config"`
KeyFile *string `mapstructure:"key_file"`
LeaveOnTerm *bool `mapstructure:"leave_on_terminate"`
LicensePath *string `mapstructure:"license_path"`
Limits Limits `mapstructure:"limits"`
@ -233,9 +229,7 @@ type Config struct {
StartJoinAddrsLAN []string `mapstructure:"start_join"`
StartJoinAddrsWAN []string `mapstructure:"start_join_wan"`
SyslogFacility *string `mapstructure:"syslog_facility"`
TLSCipherSuites *string `mapstructure:"tls_cipher_suites"`
TLSMinVersion *string `mapstructure:"tls_min_version"`
TLSPreferServerCipherSuites *bool `mapstructure:"tls_prefer_server_cipher_suites"`
TLS TLS `mapstructure:"tls"`
TaggedAddresses map[string]string `mapstructure:"tagged_addresses"`
Telemetry Telemetry `mapstructure:"telemetry"`
TranslateWANAddrs *bool `mapstructure:"translate_wan_addrs"`
@ -248,13 +242,8 @@ type Config struct {
UIDir *string `mapstructure:"ui_dir"`
UIConfig RawUIConfig `mapstructure:"ui_config"`
UnixSocket UnixSocket `mapstructure:"unix_sockets"`
VerifyIncoming *bool `mapstructure:"verify_incoming"`
VerifyIncomingHTTPS *bool `mapstructure:"verify_incoming_https"`
VerifyIncomingRPC *bool `mapstructure:"verify_incoming_rpc"`
VerifyOutgoing *bool `mapstructure:"verify_outgoing"`
VerifyServerHostname *bool `mapstructure:"verify_server_hostname"`
Watches []map[string]interface{} `mapstructure:"watches"`
UnixSocket UnixSocket `mapstructure:"unix_sockets"`
Watches []map[string]interface{} `mapstructure:"watches"`
RPC RPC `mapstructure:"rpc"`
@ -859,3 +848,22 @@ type RawUIMetricsProxyAddHeader struct {
type RPC struct {
EnableStreaming *bool `mapstructure:"enable_streaming"`
}
type TLSProtocolConfig struct {
CAFile *string `mapstructure:"ca_file"`
CAPath *string `mapstructure:"ca_path"`
CertFile *string `mapstructure:"cert_file"`
KeyFile *string `mapstructure:"key_file"`
TLSMinVersion *string `mapstructure:"tls_min_version"`
TLSCipherSuites *string `mapstructure:"tls_cipher_suites"`
VerifyIncoming *bool `mapstructure:"verify_incoming"`
VerifyOutgoing *bool `mapstructure:"verify_outgoing"`
VerifyServerHostname *bool `mapstructure:"verify_server_hostname"`
}
type TLS struct {
Defaults TLSProtocolConfig `mapstructure:"defaults"`
InternalRPC TLSProtocolConfig `mapstructure:"internal_rpc"`
HTTPS TLSProtocolConfig `mapstructure:"https"`
GRPC TLSProtocolConfig `mapstructure:"grpc"`
}

View File

@ -55,7 +55,12 @@ func DefaultSource() Source {
server = false
syslog_facility = "LOCAL0"
tls_min_version = "tls12"
tls = {
defaults = {
tls_min_version = "tls12"
}
}
// TODO (slackpad) - Until #3744 is done, we need to keep these
// in sync with agent/consul/config.go.

View File

@ -1,6 +1,8 @@
package config
import "fmt"
import (
"fmt"
)
type DeprecatedConfig struct {
// DEPRECATED (ACL-Legacy-Compat) - moved into the "acl.tokens" stanza
@ -28,6 +30,42 @@ type DeprecatedConfig struct {
ACLDownPolicy *string `mapstructure:"acl_down_policy"`
// DEPRECATED (ACL-Legacy-Compat) - moved to "acl.token_ttl"
ACLTTL *string `mapstructure:"acl_ttl"`
// DEPRECATED(TLS) - moved to "tls.defaults.ca_file"
CAFile *string `mapstructure:"ca_file"`
// DEPRECATED(TLS) - moved to "tls.defaults.ca_path"
CAPath *string `mapstructure:"ca_path"`
// DEPRECATED(TLS) - moved to "tls.defaults.cert_file"
CertFile *string `mapstructure:"cert_file"`
// DEPRECATED(TLS) - moved to "tls.defaults.key_file"
KeyFile *string `mapstructure:"key_file"`
// DEPRECATED(TLS) - moved to "tls.defaults.tls_cipher_suites"
TLSCipherSuites *string `mapstructure:"tls_cipher_suites"`
// DEPRECATED(TLS) - moved to "tls.defaults.tls_min_version"
TLSMinVersion *string `mapstructure:"tls_min_version"`
// DEPRECATED(TLS) - moved to "tls.defaults.verify_incoming"
VerifyIncoming *bool `mapstructure:"verify_incoming"`
// DEPRECATED(TLS) - moved to "tls.https.verify_incoming"
VerifyIncomingHTTPS *bool `mapstructure:"verify_incoming_https"`
// DEPRECATED(TLS) - moved to "tls.internal_rpc.verify_incoming"
VerifyIncomingRPC *bool `mapstructure:"verify_incoming_rpc"`
// DEPRECATED(TLS) - moved to "tls.defaults.verify_outgoing"
VerifyOutgoing *bool `mapstructure:"verify_outgoing"`
// DEPRECATED(TLS) - moved to "tls.internal_rpc.verify_server_hostname"
VerifyServerHostname *bool `mapstructure:"verify_server_hostname"`
// DEPRECATED(TLS) - this isn't honored by crypto/tls anymore.
TLSPreferServerCipherSuites *bool `mapstructure:"tls_prefer_server_cipher_suites"`
}
func applyDeprecatedConfig(d *decodeTarget) (Config, []string) {
@ -132,9 +170,102 @@ func applyDeprecatedConfig(d *decodeTarget) (Config, []string) {
warns = append(warns, deprecationWarning("acl_enable_key_list_policy", "acl.enable_key_list_policy"))
}
warns = append(warns, applyDeprecatedTLSConfig(dep, &d.Config)...)
return d.Config, warns
}
func applyDeprecatedTLSConfig(dep DeprecatedConfig, cfg *Config) []string {
var warns []string
defaults := &cfg.TLS.Defaults
internalRPC := &cfg.TLS.InternalRPC
https := &cfg.TLS.HTTPS
if v := dep.CAFile; v != nil {
if defaults.CAFile == nil {
defaults.CAFile = v
}
warns = append(warns, deprecationWarning("ca_file", "tls.defaults.ca_file"))
}
if v := dep.CAPath; v != nil {
if defaults.CAPath == nil {
defaults.CAPath = v
}
warns = append(warns, deprecationWarning("ca_path", "tls.defaults.ca_path"))
}
if v := dep.CertFile; v != nil {
if defaults.CertFile == nil {
defaults.CertFile = v
}
warns = append(warns, deprecationWarning("cert_file", "tls.defaults.cert_file"))
}
if v := dep.KeyFile; v != nil {
if defaults.KeyFile == nil {
defaults.KeyFile = v
}
warns = append(warns, deprecationWarning("key_file", "tls.defaults.key_file"))
}
if v := dep.TLSCipherSuites; v != nil {
if defaults.TLSCipherSuites == nil {
defaults.TLSCipherSuites = v
}
warns = append(warns, deprecationWarning("tls_cipher_suites", "tls.defaults.tls_cipher_suites"))
}
if v := dep.TLSMinVersion; v != nil {
if defaults.TLSMinVersion == nil {
defaults.TLSMinVersion = v
}
warns = append(warns, deprecationWarning("tls_min_version", "tls.defaults.tls_min_version"))
}
if v := dep.VerifyIncoming; v != nil {
if defaults.VerifyIncoming == nil {
defaults.VerifyIncoming = v
}
warns = append(warns, deprecationWarning("verify_incoming", "tls.defaults.verify_incoming"))
}
if v := dep.VerifyIncomingHTTPS; v != nil {
if https.VerifyIncoming == nil {
https.VerifyIncoming = v
}
warns = append(warns, deprecationWarning("verify_incoming_https", "tls.https.verify_incoming"))
}
if v := dep.VerifyIncomingRPC; v != nil {
if internalRPC.VerifyIncoming == nil {
internalRPC.VerifyIncoming = v
}
warns = append(warns, deprecationWarning("verify_incoming_rpc", "tls.internal_rpc.verify_incoming"))
}
if v := dep.VerifyOutgoing; v != nil {
if defaults.VerifyOutgoing == nil {
defaults.VerifyOutgoing = v
}
warns = append(warns, deprecationWarning("verify_outgoing", "tls.defaults.verify_outgoing"))
}
if v := dep.VerifyServerHostname; v != nil {
if internalRPC.VerifyServerHostname == nil {
internalRPC.VerifyServerHostname = v
}
warns = append(warns, deprecationWarning("verify_server_hostname", "tls.internal_rpc.verify_server_hostname"))
}
if dep.TLSPreferServerCipherSuites != nil {
warns = append(warns, "The 'tls_prefer_server_cipher_suites' field is deprecated and will be ignored.")
}
return warns
}
func deprecationWarning(old, new string) string {
return fmt.Sprintf("The '%v' field is deprecated. Use the '%v' field instead.", old, new)
}

View File

@ -1,11 +1,14 @@
package config
import (
"crypto/tls"
"sort"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/tlsutil"
)
func TestLoad_DeprecatedConfig(t *testing.T) {
@ -26,6 +29,18 @@ acl_down_policy = "async-cache"
acl_ttl = "3h"
acl_enable_key_list_policy = true
ca_file = "some-ca-file"
ca_path = "some-ca-path"
cert_file = "some-cert-file"
key_file = "some-key-file"
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
tls_min_version = "some-tls-version"
verify_incoming = true
verify_incoming_https = false
verify_incoming_rpc = false
verify_outgoing = true
verify_server_hostname = true
tls_prefer_server_cipher_suites = true
`},
}
patchLoadOptsShims(&opts)
@ -41,9 +56,20 @@ acl_enable_key_list_policy = true
deprecationWarning("acl_replication_token", "acl.tokens.replication"),
deprecationWarning("acl_token", "acl.tokens.default"),
deprecationWarning("acl_ttl", "acl.token_ttl"),
deprecationWarning("ca_file", "tls.defaults.ca_file"),
deprecationWarning("ca_path", "tls.defaults.ca_path"),
deprecationWarning("cert_file", "tls.defaults.cert_file"),
deprecationWarning("key_file", "tls.defaults.key_file"),
deprecationWarning("tls_cipher_suites", "tls.defaults.tls_cipher_suites"),
deprecationWarning("tls_min_version", "tls.defaults.tls_min_version"),
deprecationWarning("verify_incoming", "tls.defaults.verify_incoming"),
deprecationWarning("verify_incoming_https", "tls.https.verify_incoming"),
deprecationWarning("verify_incoming_rpc", "tls.internal_rpc.verify_incoming"),
deprecationWarning("verify_outgoing", "tls.defaults.verify_outgoing"),
deprecationWarning("verify_server_hostname", "tls.internal_rpc.verify_server_hostname"),
"The 'tls_prefer_server_cipher_suites' field is deprecated and will be ignored.",
}
sort.Strings(result.Warnings)
require.Equal(t, expectWarns, result.Warnings)
require.ElementsMatch(t, expectWarns, result.Warnings)
// Ideally this would compare against the entire result.RuntimeConfig, but
// we have so many non-zero defaults in that response that the noise of those
// defaults makes this test difficult to read. So as a workaround, compare
@ -58,6 +84,22 @@ acl_enable_key_list_policy = true
require.Equal(t, "async-cache", rt.ACLResolverSettings.ACLDownPolicy)
require.Equal(t, 3*time.Hour, rt.ACLResolverSettings.ACLTokenTTL)
require.Equal(t, true, rt.ACLEnableKeyListPolicy)
for _, l := range []tlsutil.ProtocolConfig{rt.TLS.InternalRPC, rt.TLS.GRPC, rt.TLS.HTTPS} {
require.Equal(t, "some-ca-file", l.CAFile)
require.Equal(t, "some-ca-path", l.CAPath)
require.Equal(t, "some-cert-file", l.CertFile)
require.Equal(t, "some-key-file", l.KeyFile)
require.Equal(t, "some-tls-version", l.TLSMinVersion)
require.Equal(t, []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, l.CipherSuites)
}
require.False(t, rt.TLS.InternalRPC.VerifyIncoming)
require.False(t, rt.TLS.HTTPS.VerifyIncoming)
require.True(t, rt.TLS.GRPC.VerifyIncoming)
require.True(t, rt.TLS.InternalRPC.VerifyOutgoing)
require.True(t, rt.TLS.HTTPS.VerifyOutgoing)
require.True(t, rt.TLS.InternalRPC.VerifyServerHostname)
}
func TestLoad_DeprecatedConfig_ACLReplication(t *testing.T) {

View File

@ -377,24 +377,6 @@ type RuntimeConfig struct {
// Cache represent cache configuration of agent
Cache cache.Options
// CAFile is a path to a certificate authority file. This is used with
// VerifyIncoming or VerifyOutgoing to verify the TLS connection.
//
// hcl: ca_file = string
CAFile string
// CAPath is a path to a directory of certificate authority files. This is
// used with VerifyIncoming or VerifyOutgoing to verify the TLS connection.
//
// hcl: ca_path = string
CAPath string
// CertFile is used to provide a TLS certificate that is used for serving
// TLS connections. Must be provided to serve TLS connections.
//
// hcl: cert_file = string
CertFile string
// CheckUpdateInterval controls the interval on which the output of a health check
// is updated if there is no change to the state. For example, a check in a steady
// state may run every 5 second generating a unique output (timestamp, etc), forcing
@ -767,12 +749,6 @@ type RuntimeConfig struct {
// flags: -https-port int
HTTPSPort int
// KeyFile is used to provide a TLS key that is used for serving TLS
// connections. Must be provided to serve TLS connections.
//
// hcl: key_file = string
KeyFile string
// KVMaxValueSize controls the max allowed value size. If not set defaults
// to raft's suggested max value size.
//
@ -1338,40 +1314,11 @@ type RuntimeConfig struct {
// flag: -join-wan string -join-wan string
StartJoinAddrsWAN []string
// TLSCipherSuites is used to specify the list of supported ciphersuites.
// TLS configures certificates, CA, cipher suites, and other TLS settings
// on Consul's listeners (i.e. Internal multiplexed RPC, HTTPS and gRPC).
//
// The values should be a list of the following values:
//
// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
// TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
// TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
// TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
//
// todo(fs): IMHO, we should also support the raw 0xNNNN values from
// todo(fs): https://golang.org/pkg/crypto/tls/#pkg-constants
// todo(fs): since they are standardized by IANA.
//
// hcl: tls_cipher_suites = []string
TLSCipherSuites []uint16
// TLSMinVersion is used to set the minimum TLS version used for TLS
// connections. Should be either "tls10", "tls11", "tls12" or "tls13".
// Defaults to tls12.
//
// hcl: tls_min_version = string
TLSMinVersion string
// TLSPreferServerCipherSuites specifies whether to prefer the server's
// cipher suite over the client cipher suites.
//
// hcl: tls_prefer_server_cipher_suites = (true|false)
TLSPreferServerCipherSuites bool
// hcl: tls { ... }
TLS tlsutil.Config
// TaggedAddresses are used to publish a set of addresses for
// for a node, which can be used by the remote agent. We currently
@ -1427,49 +1374,6 @@ type RuntimeConfig struct {
// hcl: unix_sockets { user = string }
UnixSocketUser string
// VerifyIncoming is used to verify the authenticity of incoming
// connections. This means that TCP requests are forbidden, only allowing
// for TLS. TLS connections must match a provided certificate authority.
// This can be used to force client auth.
//
// hcl: verify_incoming = (true|false)
VerifyIncoming bool
// VerifyIncomingHTTPS is used to verify the authenticity of incoming HTTPS
// connections. This means that TCP requests are forbidden, only allowing
// for TLS. TLS connections must match a provided certificate authority.
// This can be used to force client auth.
//
// hcl: verify_incoming_https = (true|false)
VerifyIncomingHTTPS bool
// VerifyIncomingRPC is used to verify the authenticity of incoming RPC
// connections. This means that TCP requests are forbidden, only allowing
// for TLS. TLS connections must match a provided certificate authority.
// This can be used to force client auth.
//
// hcl: verify_incoming_rpc = (true|false)
VerifyIncomingRPC bool
// VerifyOutgoing is used to verify the authenticity of outgoing
// connections. This means that TLS requests are used. TLS connections must
// match a provided certificate authority. This is used to verify
// authenticity of server nodes.
//
// hcl: verify_outgoing = (true|false)
VerifyOutgoing bool
// VerifyServerHostname is used to enable hostname verification of servers.
// This ensures that the certificate presented is valid for
// server.<datacenter>.<domain>. This prevents a compromised client from
// being restarted as a server, and then intercepting request traffic as
// well as being added as a raft peer. This should be enabled by default
// with VerifyOutgoing, but for legacy reasons we cannot break existing
// clients.
//
// hcl: verify_server_hostname = (true|false)
VerifyServerHostname bool
// Watches are used to monitor various endpoints and to invoke a
// handler to act appropriately. These are managed entirely in the
// agent layer using the standard APIs.
@ -1676,9 +1580,11 @@ func (c *RuntimeConfig) ConnectCAConfiguration() (*structs.CAConfiguration, erro
}
func (c *RuntimeConfig) APIConfig(includeClientCerts bool) (*api.Config, error) {
tls := c.TLS.HTTPS
cfg := &api.Config{
Datacenter: c.Datacenter,
TLSConfig: api.TLSConfig{InsecureSkipVerify: !c.VerifyOutgoing},
TLSConfig: api.TLSConfig{InsecureSkipVerify: !tls.VerifyOutgoing},
}
unixAddr, httpAddr, httpsAddr := c.ClientAddress()
@ -1686,11 +1592,11 @@ func (c *RuntimeConfig) APIConfig(includeClientCerts bool) (*api.Config, error)
if httpsAddr != "" {
cfg.Address = httpsAddr
cfg.Scheme = "https"
cfg.TLSConfig.CAFile = c.CAFile
cfg.TLSConfig.CAPath = c.CAPath
cfg.TLSConfig.CAFile = tls.CAFile
cfg.TLSConfig.CAPath = tls.CAPath
if includeClientCerts {
cfg.TLSConfig.CertFile = c.CertFile
cfg.TLSConfig.KeyFile = c.KeyFile
cfg.TLSConfig.CertFile = tls.CertFile
cfg.TLSConfig.KeyFile = tls.KeyFile
}
} else if httpAddr != "" {
cfg.Address = httpAddr
@ -1715,28 +1621,6 @@ func (c *RuntimeConfig) Sanitized() map[string]interface{} {
return sanitize("rt", reflect.ValueOf(c)).Interface().(map[string]interface{})
}
func (c *RuntimeConfig) ToTLSUtilConfig() tlsutil.Config {
return tlsutil.Config{
VerifyIncoming: c.VerifyIncoming,
VerifyIncomingRPC: c.VerifyIncomingRPC,
VerifyIncomingHTTPS: c.VerifyIncomingHTTPS,
VerifyOutgoing: c.VerifyOutgoing,
VerifyServerHostname: c.VerifyServerHostname,
CAFile: c.CAFile,
CAPath: c.CAPath,
CertFile: c.CertFile,
KeyFile: c.KeyFile,
NodeName: c.NodeName,
Domain: c.DNSDomain,
ServerName: c.ServerName,
TLSMinVersion: c.TLSMinVersion,
CipherSuites: c.TLSCipherSuites,
PreferServerCipherSuites: c.TLSPreferServerCipherSuites,
EnableAgentTLSForChecks: c.EnableAgentTLSForChecks,
AutoTLS: c.AutoEncryptTLS || c.AutoConfig.Enabled,
}
}
// isSecret determines whether a field name represents a field which
// may contain a secret.
func isSecret(name string) bool {

View File

@ -32,6 +32,7 @@ import (
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/logging"
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/tlsutil"
"github.com/hashicorp/consul/types"
)
@ -386,6 +387,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
},
expected: func(rt *RuntimeConfig) {
rt.DNSDomain = "a"
rt.TLS.Domain = "a"
rt.DataDir = dataDir
},
})
@ -590,6 +592,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
},
expected: func(rt *RuntimeConfig) {
rt.NodeName = "a"
rt.TLS.NodeName = "a"
rt.DataDir = dataDir
},
})
@ -2505,6 +2508,98 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
},
expectedErr: `invalid meta for service a: Node metadata cannot contain more than 64 key`,
})
run(t, testCase{
desc: "verify_outgoing in the grpc stanza",
args: []string{
`-data-dir=` + dataDir,
},
hcl: []string{`
tls {
grpc {
verify_outgoing = true
}
}
`},
json: []string{`
{
"tls": {
"grpc": {
"verify_outgoing": true
}
}
}
`},
expectedErr: "verify_outgoing is not valid in the tls.grpc stanza",
})
run(t, testCase{
desc: "verify_server_hostname in the defaults stanza",
args: []string{
`-data-dir=` + dataDir,
},
hcl: []string{`
tls {
defaults {
verify_server_hostname = true
}
}
`},
json: []string{`
{
"tls": {
"defaults": {
"verify_server_hostname": true
}
}
}
`},
expectedErr: "verify_server_hostname is only valid in the tls.internal_rpc stanza",
})
run(t, testCase{
desc: "verify_server_hostname in the grpc stanza",
args: []string{
`-data-dir=` + dataDir,
},
hcl: []string{`
tls {
grpc {
verify_server_hostname = true
}
}
`},
json: []string{`
{
"tls": {
"grpc": {
"verify_server_hostname": true
}
}
}
`},
expectedErr: "verify_server_hostname is only valid in the tls.internal_rpc stanza",
})
run(t, testCase{
desc: "verify_server_hostname in the https stanza",
args: []string{
`-data-dir=` + dataDir,
},
hcl: []string{`
tls {
https {
verify_server_hostname = true
}
}
`},
json: []string{`
{
"tls": {
"https": {
"verify_server_hostname": true
}
}
}
`},
expectedErr: "verify_server_hostname is only valid in the tls.internal_rpc stanza",
})
run(t, testCase{
desc: "translated keys",
args: []string{
@ -2920,8 +3015,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
`},
expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir
rt.VerifyServerHostname = true
rt.VerifyOutgoing = true
rt.TLS.InternalRPC.VerifyServerHostname = true
rt.TLS.InternalRPC.VerifyOutgoing = true
},
expectedWarnings: []string{
deprecationWarning("verify_server_hostname", "tls.internal_rpc.verify_server_hostname"),
},
})
run(t, testCase{
@ -2930,18 +3028,18 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
`-data-dir=` + dataDir,
},
json: []string{`{
"verify_incoming": true,
"tls": { "internal_rpc": { "verify_incoming": true } },
"auto_encrypt": { "allow_tls": true },
"server": true
}`},
hcl: []string{`
verify_incoming = true
tls { internal_rpc { verify_incoming = true } }
auto_encrypt { allow_tls = true }
server = true
`},
expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir
rt.VerifyIncoming = true
rt.TLS.InternalRPC.VerifyIncoming = true
rt.AutoEncryptAllowTLS = true
rt.ConnectEnabled = true
@ -2953,26 +3051,29 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
},
})
run(t, testCase{
desc: "auto_encrypt.allow_tls works with verify_incoming",
desc: "auto_encrypt.allow_tls works with tls.defaults.verify_incoming",
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
"verify_incoming": true,
"tls": { "defaults": { "verify_incoming": true } },
"auto_encrypt": { "allow_tls": true },
"server": true
}`},
hcl: []string{`
verify_incoming = true
tls { defaults { verify_incoming = true } }
auto_encrypt { allow_tls = true }
server = true
`},
expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir
rt.VerifyIncoming = true
rt.AutoEncryptAllowTLS = true
rt.ConnectEnabled = true
rt.TLS.InternalRPC.VerifyIncoming = true
rt.TLS.GRPC.VerifyIncoming = true
rt.TLS.HTTPS.VerifyIncoming = true
// server things
rt.ServerMode = true
rt.LeaveOnTerm = false
@ -2981,25 +3082,25 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
},
})
run(t, testCase{
desc: "auto_encrypt.allow_tls works with verify_incoming_rpc",
desc: "auto_encrypt.allow_tls works with tls.internal_rpc.verify_incoming",
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`{
"verify_incoming_rpc": true,
"tls": { "internal_rpc": { "verify_incoming": true } },
"auto_encrypt": { "allow_tls": true },
"server": true
}`},
hcl: []string{`
verify_incoming_rpc = true
tls { internal_rpc { verify_incoming = true } }
auto_encrypt { allow_tls = true }
server = true
`},
expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir
rt.VerifyIncomingRPC = true
rt.AutoEncryptAllowTLS = true
rt.ConnectEnabled = true
rt.TLS.InternalRPC.VerifyIncoming = true
// server things
rt.ServerMode = true
@ -3009,7 +3110,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
},
})
run(t, testCase{
desc: "auto_encrypt.allow_tls warns without verify_incoming or verify_incoming_rpc",
desc: "auto_encrypt.allow_tls warns without tls.defaults.verify_incoming or tls.internal_rpc.verify_incoming",
args: []string{
`-data-dir=` + dataDir,
},
@ -3021,7 +3122,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
auto_encrypt { allow_tls = true }
server = true
`},
expectedWarnings: []string{"if auto_encrypt.allow_tls is turned on, either verify_incoming or verify_incoming_rpc should be enabled. It is necessary to turn it off during a migration to TLS, but it should definitely be turned on afterwards."},
expectedWarnings: []string{"if auto_encrypt.allow_tls is turned on, tls.internal_rpc.verify_incoming should be enabled (either explicitly or via tls.defaults.verify_incoming). It is necessary to turn it off during a migration to TLS, but it should definitely be turned on afterwards."},
expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir
rt.AutoEncryptAllowTLS = true
@ -4436,7 +4537,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
auto_encrypt {
tls = true
}
verify_outgoing = true
tls {
internal_rpc {
verify_outgoing = true
}
}
`},
json: []string{`{
"auto_config": {
@ -4447,7 +4552,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"auto_encrypt": {
"tls": true
},
"verify_outgoing": true
"tls": {
"internal_rpc": {
"verify_outgoing": true
}
}
}`},
expectedErr: "both auto_encrypt.tls and auto_config.enabled cannot be set to true.",
})
@ -4463,7 +4572,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
intro_token = "blah"
server_addresses = ["198.18.0.1"]
}
verify_outgoing = true
tls {
internal_rpc {
verify_outgoing = true
}
}
`},
json: []string{`
{
@ -4473,7 +4586,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"intro_token": "blah",
"server_addresses": ["198.18.0.1"]
},
"verify_outgoing": true
"tls": {
"internal_rpc": {
"verify_outgoing": true
}
}
}`},
expectedErr: "auto_config.enabled cannot be set to true for server agents",
})
@ -4536,7 +4653,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
enabled = true
server_addresses = ["198.18.0.1"]
}
verify_outgoing = true
tls {
internal_rpc {
verify_outgoing = true
}
}
`},
json: []string{`
{
@ -4544,7 +4665,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"enabled": true,
"server_addresses": ["198.18.0.1"]
},
"verify_outgoing": true
"tls": {
"internal_rpc": {
"verify_outgoing": true
}
}
}`},
expectedErr: "One of auto_config.intro_token, auto_config.intro_token_file or the CONSUL_INTRO_TOKEN environment variable must be set to enable auto_config",
})
@ -4559,7 +4684,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
enabled = true
intro_token = "blah"
}
verify_outgoing = true
tls {
internal_rpc {
verify_outgoing = true
}
}
`},
json: []string{`
{
@ -4567,7 +4696,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"enabled": true,
"intro_token": "blah"
},
"verify_outgoing": true
"tls": {
"internal_rpc": {
"verify_outgoing": true
}
}
}`},
expectedErr: "auto_config.enabled is set without providing a list of addresses",
})
@ -4586,7 +4719,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
dns_sans = ["foo"]
ip_sans = ["invalid", "127.0.0.1"]
}
verify_outgoing = true
tls {
internal_rpc {
verify_outgoing = true
}
}
`},
json: []string{`
{
@ -4598,7 +4735,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"dns_sans": ["foo"],
"ip_sans": ["invalid", "127.0.0.1"]
},
"verify_outgoing": true
"tls": {
"internal_rpc": {
"verify_outgoing": true
}
}
}`},
expectedWarnings: []string{
"Cannot parse ip \"invalid\" from auto_config.ip_sans",
@ -4613,7 +4754,8 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
rt.AutoConfig.DNSSANs = []string{"foo"}
rt.AutoConfig.IPSANs = []net.IP{net.IPv4(127, 0, 0, 1)}
rt.DataDir = dataDir
rt.VerifyOutgoing = true
rt.TLS.InternalRPC.VerifyOutgoing = true
rt.TLS.AutoTLS = true
},
})
@ -4652,7 +4794,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
enabled = true
}
}
cert_file = "foo"
tls {
internal_rpc {
cert_file = "foo"
}
}
`},
json: []string{`
{
@ -4661,7 +4807,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"enabled": true
}
},
"cert_file": "foo"
"tls": {
"internal_rpc": {
"cert_file": "foo"
}
}
}`},
expectedErr: `auto_config.authorization.static has invalid configuration: exactly one of 'JWTValidationPubKeys', 'JWKSURL', or 'OIDCDiscoveryURL' must be set for type "jwt"`,
})
@ -4682,7 +4832,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}
}
}
cert_file = "foo"
tls {
internal_rpc {
cert_file = "foo"
}
}
`},
json: []string{`
{
@ -4695,7 +4849,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}
}
},
"cert_file": "foo"
"tls": {
"internal_rpc": {
"cert_file": "foo"
}
}
}`},
expectedErr: `auto_config.authorization.static has invalid configuration: exactly one of 'JWTValidationPubKeys', 'JWKSURL', or 'OIDCDiscoveryURL' must be set for type "jwt"`,
})
@ -4720,7 +4878,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}
}
}
cert_file = "foo"
tls {
internal_rpc {
cert_file = "foo"
}
}
`},
json: []string{`
{
@ -4737,7 +4899,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}
}
},
"cert_file": "foo"
"tls": {
"internal_rpc": {
"cert_file": "foo"
}
}
}`},
expectedErr: `Enabling auto-config authorization (auto_config.authorization.enabled) in non primary datacenters with ACLs enabled (acl.enabled) requires also enabling ACL token replication (acl.enable_token_replication)`,
})
@ -4760,7 +4926,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}
}
}
cert_file = "foo"
tls {
internal_rpc {
cert_file = "foo"
}
}
`},
json: []string{`
{
@ -4775,7 +4945,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}
}
},
"cert_file": "foo"
"tls": {
"internal_rpc": {
"cert_file": "foo"
}
}
}`},
expectedErr: `auto_config.authorization.static.claim_assertion "values.node == ${node}" is invalid: Selector "values" is not valid`,
})
@ -4800,7 +4974,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}
}
}
cert_file = "foo"
tls {
internal_rpc {
cert_file = "foo"
}
}
`},
json: []string{`
{
@ -4818,7 +4996,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}
}
},
"cert_file": "foo"
"tls": {
"internal_rpc": {
"cert_file": "foo"
}
}
}`},
expected: func(rt *RuntimeConfig) {
rt.AutoConfig.Authorizer.Enabled = true
@ -4831,7 +5013,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
rt.LeaveOnTerm = false
rt.ServerMode = true
rt.SkipLeaveOnInt = true
rt.CertFile = "foo"
rt.TLS.InternalRPC.CertFile = "foo"
rt.RPCConfig.EnableStreaming = true
},
})
@ -5197,6 +5379,165 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}`},
expectedErr: "advertise_reconnect_timeout can only be used on a client",
})
run(t, testCase{
desc: "TLS defaults and overrides",
args: []string{
`-data-dir=` + dataDir,
},
hcl: []string{`
ports {
https = 4321
}
tls {
defaults {
ca_file = "default_ca_file"
ca_path = "default_ca_path"
cert_file = "default_cert_file"
tls_min_version = "tls12"
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
verify_incoming = true
}
internal_rpc {
ca_file = "internal_rpc_ca_file"
}
https {
cert_file = "https_cert_file"
tls_min_version = "tls13"
}
grpc {
verify_incoming = false
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
}
}
`},
json: []string{`
{
"ports": {
"https": 4321
},
"tls": {
"defaults": {
"ca_file": "default_ca_file",
"ca_path": "default_ca_path",
"cert_file": "default_cert_file",
"tls_min_version": "tls12",
"tls_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"verify_incoming": true
},
"internal_rpc": {
"ca_file": "internal_rpc_ca_file"
},
"https": {
"cert_file": "https_cert_file",
"tls_min_version": "tls13"
},
"grpc": {
"verify_incoming": false,
"tls_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
}
}
}
`},
expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir
rt.HTTPSPort = 4321
rt.HTTPSAddrs = []net.Addr{tcpAddr("127.0.0.1:4321")}
rt.TLS.Domain = "consul."
rt.TLS.NodeName = "thehostname"
rt.TLS.InternalRPC.CAFile = "internal_rpc_ca_file"
rt.TLS.InternalRPC.CAPath = "default_ca_path"
rt.TLS.InternalRPC.CertFile = "default_cert_file"
rt.TLS.InternalRPC.TLSMinVersion = "tls12"
rt.TLS.InternalRPC.CipherSuites = []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}
rt.TLS.InternalRPC.VerifyIncoming = true
rt.TLS.HTTPS.CAFile = "default_ca_file"
rt.TLS.HTTPS.CAPath = "default_ca_path"
rt.TLS.HTTPS.CertFile = "https_cert_file"
rt.TLS.HTTPS.TLSMinVersion = "tls13"
rt.TLS.HTTPS.CipherSuites = []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}
rt.TLS.HTTPS.VerifyIncoming = true
rt.TLS.GRPC.CAFile = "default_ca_file"
rt.TLS.GRPC.CAPath = "default_ca_path"
rt.TLS.GRPC.CertFile = "default_cert_file"
rt.TLS.GRPC.TLSMinVersion = "tls12"
rt.TLS.GRPC.CipherSuites = []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}
rt.TLS.GRPC.VerifyIncoming = false
},
})
run(t, testCase{
desc: "tls.internal_rpc.verify_server_hostname implies tls.internal_rpc.verify_outgoing",
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`
{
"tls": {
"internal_rpc": {
"verify_server_hostname": true
}
}
}
`},
hcl: []string{`
tls {
internal_rpc {
verify_server_hostname = true
}
}
`},
expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir
rt.TLS.Domain = "consul."
rt.TLS.NodeName = "thehostname"
rt.TLS.InternalRPC.VerifyServerHostname = true
rt.TLS.InternalRPC.VerifyOutgoing = true
},
})
run(t, testCase{
desc: "tls.grpc without ports.https",
args: []string{
`-data-dir=` + dataDir,
},
json: []string{`
{
"tls": {
"grpc": {
"cert_file": "cert-1234"
}
}
}
`},
hcl: []string{`
tls {
grpc {
cert_file = "cert-1234"
}
}
`},
expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir
rt.TLS.Domain = "consul."
rt.TLS.NodeName = "thehostname"
rt.TLS.GRPC.CertFile = "cert-1234"
},
expectedWarnings: []string{
"tls.grpc was provided but TLS will NOT be enabled on the gRPC listener without an HTTPS listener configured (e.g. via ports.https)",
},
})
}
func (tc testCase) run(format string, dataDir string) func(t *testing.T) {
@ -5382,9 +5723,6 @@ func TestLoad_FullConfig(t *testing.T) {
EntryFetchMaxBurst: 42,
EntryFetchRate: 0.334,
},
CAFile: "erA7T0PM",
CAPath: "mQEN1Mfp",
CertFile: "7s4QAzDk",
CheckOutputMaxSize: checks.DefaultBufSize,
Checks: []*structs.CheckDefinition{
{
@ -5592,7 +5930,6 @@ func TestLoad_FullConfig(t *testing.T) {
HTTPSHandshakeTimeout: 2391 * time.Millisecond,
HTTPSPort: 15127,
HTTPUseCache: false,
KeyFile: "IEkkwgIA",
KVMaxValueSize: 1234567800,
LeaveDrainTime: 8265 * time.Second,
LeaveOnTerm: true,
@ -5966,9 +6303,43 @@ func TestLoad_FullConfig(t *testing.T) {
Name: "ftO6DySn", // notice this is the same as the metrics prefix
},
},
TLSCipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
TLSMinVersion: "pAOWafkR",
TLSPreferServerCipherSuites: true,
TLS: tlsutil.Config{
InternalRPC: tlsutil.ProtocolConfig{
VerifyIncoming: true,
CAFile: "mKl19Utl",
CAPath: "lOp1nhPa",
CertFile: "dfJ4oPln",
KeyFile: "aL1Knkpo",
TLSMinVersion: "lPo1MklP",
CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
VerifyOutgoing: true,
VerifyServerHostname: true,
},
GRPC: tlsutil.ProtocolConfig{
VerifyIncoming: true,
CAFile: "lOp1nhJk",
CAPath: "fLponKpl",
CertFile: "a674klPn",
KeyFile: "1y4prKjl",
TLSMinVersion: "lPo4fNkl",
CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
VerifyOutgoing: false,
},
HTTPS: tlsutil.ProtocolConfig{
VerifyIncoming: true,
CAFile: "7Yu1PolM",
CAPath: "nu4PlHzn",
CertFile: "1yrhPlMk",
KeyFile: "1bHapOkL",
TLSMinVersion: "mK14iOpz",
CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
VerifyOutgoing: true,
},
NodeName: "otlLxGaI",
ServerName: "Oerr9n1G",
Domain: "7W1xXSqd",
EnableAgentTLSForChecks: true,
},
TaggedAddresses: map[string]string{
"7MYgHrYH": "dALJAhLD",
"h6DdBy6K": "ebrr9zZ8",
@ -5997,14 +6368,9 @@ func TestLoad_FullConfig(t *testing.T) {
},
DashboardURLTemplates: map[string]string{"u2eziu2n_lower_case": "http://lkjasd.otr"},
},
UnixSocketUser: "E0nB1DwA",
UnixSocketGroup: "8pFodrV8",
UnixSocketMode: "E8sAwOv4",
VerifyIncoming: true,
VerifyIncomingHTTPS: true,
VerifyIncomingRPC: true,
VerifyOutgoing: true,
VerifyServerHostname: true,
UnixSocketUser: "E0nB1DwA",
UnixSocketGroup: "8pFodrV8",
UnixSocketMode: "E8sAwOv4",
Watches: []map[string]interface{}{
{
"type": "key",
@ -6038,6 +6404,18 @@ func TestLoad_FullConfig(t *testing.T) {
deprecationWarning("acl_ttl", "acl.token_ttl"),
deprecationWarning("acl_enable_key_list_policy", "acl.enable_key_list_policy"),
`bootstrap_expect > 0: expecting 53 servers`,
deprecationWarning("ca_file", "tls.defaults.ca_file"),
deprecationWarning("ca_path", "tls.defaults.ca_path"),
deprecationWarning("cert_file", "tls.defaults.cert_file"),
deprecationWarning("key_file", "tls.defaults.key_file"),
deprecationWarning("tls_cipher_suites", "tls.defaults.tls_cipher_suites"),
deprecationWarning("tls_min_version", "tls.defaults.tls_min_version"),
deprecationWarning("verify_incoming", "tls.defaults.verify_incoming"),
deprecationWarning("verify_incoming_https", "tls.https.verify_incoming"),
deprecationWarning("verify_incoming_rpc", "tls.internal_rpc.verify_incoming"),
deprecationWarning("verify_outgoing", "tls.defaults.verify_outgoing"),
deprecationWarning("verify_server_hostname", "tls.internal_rpc.verify_server_hostname"),
"The 'tls_prefer_server_cipher_suites' field is deprecated and will be ignored.",
}
expectedWarns = append(expectedWarns, enterpriseConfigKeyWarnings...)
@ -6350,34 +6728,38 @@ func TestRuntime_APIConfigHTTPS(t *testing.T) {
HTTPSAddrs: []net.Addr{
&net.TCPAddr{IP: net.ParseIP("198.18.0.2"), Port: 5678},
},
Datacenter: "dc-test",
CAFile: "/etc/consul/ca.crt",
CAPath: "/etc/consul/ca.dir",
CertFile: "/etc/consul/server.crt",
KeyFile: "/etc/consul/ssl/server.key",
VerifyOutgoing: false,
Datacenter: "dc-test",
TLS: tlsutil.Config{
HTTPS: tlsutil.ProtocolConfig{
CAFile: "/etc/consul/ca.crt",
CAPath: "/etc/consul/ca.dir",
CertFile: "/etc/consul/server.crt",
KeyFile: "/etc/consul/ssl/server.key",
VerifyOutgoing: false,
},
},
}
cfg, err := rt.APIConfig(false)
require.NoError(t, err)
require.Equal(t, "198.18.0.2:5678", cfg.Address)
require.Equal(t, "https", cfg.Scheme)
require.Equal(t, rt.CAFile, cfg.TLSConfig.CAFile)
require.Equal(t, rt.CAPath, cfg.TLSConfig.CAPath)
require.Equal(t, rt.TLS.HTTPS.CAFile, cfg.TLSConfig.CAFile)
require.Equal(t, rt.TLS.HTTPS.CAPath, cfg.TLSConfig.CAPath)
require.Equal(t, "", cfg.TLSConfig.CertFile)
require.Equal(t, "", cfg.TLSConfig.KeyFile)
require.Equal(t, rt.Datacenter, cfg.Datacenter)
require.Equal(t, true, cfg.TLSConfig.InsecureSkipVerify)
rt.VerifyOutgoing = true
rt.TLS.HTTPS.VerifyOutgoing = true
cfg, err = rt.APIConfig(true)
require.NoError(t, err)
require.Equal(t, "198.18.0.2:5678", cfg.Address)
require.Equal(t, "https", cfg.Scheme)
require.Equal(t, rt.CAFile, cfg.TLSConfig.CAFile)
require.Equal(t, rt.CAPath, cfg.TLSConfig.CAPath)
require.Equal(t, rt.CertFile, cfg.TLSConfig.CertFile)
require.Equal(t, rt.KeyFile, cfg.TLSConfig.KeyFile)
require.Equal(t, rt.TLS.HTTPS.CAFile, cfg.TLSConfig.CAFile)
require.Equal(t, rt.TLS.HTTPS.CAPath, cfg.TLSConfig.CAPath)
require.Equal(t, rt.TLS.HTTPS.CertFile, cfg.TLSConfig.CertFile)
require.Equal(t, rt.TLS.HTTPS.KeyFile, cfg.TLSConfig.KeyFile)
require.Equal(t, rt.Datacenter, cfg.Datacenter)
require.Equal(t, false, cfg.TLSConfig.InsecureSkipVerify)
}
@ -6515,86 +6897,6 @@ func TestRuntime_ClientAddressAnyV6(t *testing.T) {
require.Equal(t, "[::1]:5688", https)
}
func TestRuntime_ToTLSUtilConfig(t *testing.T) {
c := &RuntimeConfig{
VerifyIncoming: true,
VerifyIncomingRPC: true,
VerifyIncomingHTTPS: true,
VerifyOutgoing: true,
VerifyServerHostname: true,
CAFile: "a",
CAPath: "b",
CertFile: "c",
KeyFile: "d",
NodeName: "e",
ServerName: "f",
DNSDomain: "g",
TLSMinVersion: "tls12",
TLSCipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
TLSPreferServerCipherSuites: true,
EnableAgentTLSForChecks: true,
AutoEncryptTLS: true,
}
r := c.ToTLSUtilConfig()
require.True(t, r.VerifyIncoming)
require.True(t, r.VerifyIncomingRPC)
require.True(t, r.VerifyIncomingHTTPS)
require.True(t, r.VerifyOutgoing)
require.True(t, r.EnableAgentTLSForChecks)
require.True(t, r.AutoTLS)
require.True(t, r.VerifyServerHostname)
require.True(t, r.PreferServerCipherSuites)
require.Equal(t, "a", r.CAFile)
require.Equal(t, "b", r.CAPath)
require.Equal(t, "c", r.CertFile)
require.Equal(t, "d", r.KeyFile)
require.Equal(t, "e", r.NodeName)
require.Equal(t, "f", r.ServerName)
require.Equal(t, "g", r.Domain)
require.Equal(t, "tls12", r.TLSMinVersion)
require.Equal(t, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, r.CipherSuites)
}
func TestRuntime_ToTLSUtilConfig_AutoConfig(t *testing.T) {
c := &RuntimeConfig{
VerifyIncoming: true,
VerifyIncomingRPC: true,
VerifyIncomingHTTPS: true,
VerifyOutgoing: true,
VerifyServerHostname: true,
CAFile: "a",
CAPath: "b",
CertFile: "c",
KeyFile: "d",
NodeName: "e",
ServerName: "f",
DNSDomain: "g",
TLSMinVersion: "tls12",
TLSCipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
TLSPreferServerCipherSuites: true,
EnableAgentTLSForChecks: true,
AutoConfig: AutoConfig{Enabled: true},
}
r := c.ToTLSUtilConfig()
require.True(t, r.VerifyIncoming)
require.True(t, r.VerifyIncomingRPC)
require.True(t, r.VerifyIncomingHTTPS)
require.True(t, r.VerifyOutgoing)
require.True(t, r.EnableAgentTLSForChecks)
require.True(t, r.AutoTLS)
require.True(t, r.VerifyServerHostname)
require.True(t, r.PreferServerCipherSuites)
require.Equal(t, "a", r.CAFile)
require.Equal(t, "b", r.CAPath)
require.Equal(t, "c", r.CertFile)
require.Equal(t, "d", r.KeyFile)
require.Equal(t, "e", r.NodeName)
require.Equal(t, "f", r.ServerName)
require.Equal(t, "g", r.Domain)
require.Equal(t, "tls12", r.TLSMinVersion)
require.Equal(t, []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, r.CipherSuites)
}
func Test_UIPathBuilder(t *testing.T) {
cases := []struct {
name string

View File

@ -74,14 +74,11 @@
"BindAddr": "127.0.0.1",
"Bootstrap": false,
"BootstrapExpect": 0,
"CAFile": "",
"CAPath": "",
"Cache": {
"EntryFetchMaxBurst": 42,
"EntryFetchRate": 0.334,
"Logger": null
},
"CertFile": "",
"CheckDeregisterIntervalMin": "0s",
"CheckOutputMaxSize": 4096,
"CheckReapInterval": "0s",
@ -218,7 +215,6 @@
"HTTPSPort": 0,
"HTTPUseCache": false,
"KVMaxValueSize": 1234567800000000,
"KeyFile": "hidden",
"LeaveDrainTime": "0s",
"LeaveOnTerm": false,
"Logging": {
@ -354,9 +350,46 @@
"StartJoinAddrsWAN": [],
"SyncCoordinateIntervalMin": "0s",
"SyncCoordinateRateTarget": 0,
"TLSCipherSuites": [],
"TLSMinVersion": "",
"TLSPreferServerCipherSuites": false,
"TLS": {
"AutoTLS": false,
"Domain": "",
"EnableAgentTLSForChecks": false,
"GRPC": {
"CAFile": "",
"CAPath": "",
"CertFile": "",
"CipherSuites": [],
"KeyFile": "hidden",
"TLSMinVersion": "",
"VerifyIncoming": false,
"VerifyOutgoing": false,
"VerifyServerHostname": false
},
"HTTPS": {
"CAFile": "",
"CAPath": "",
"CertFile": "",
"CipherSuites": [],
"KeyFile": "hidden",
"TLSMinVersion": "",
"VerifyIncoming": false,
"VerifyOutgoing": false,
"VerifyServerHostname": false
},
"InternalRPC": {
"CAFile": "",
"CAPath": "",
"CertFile": "",
"CipherSuites": [],
"KeyFile": "hidden",
"TLSMinVersion": "",
"VerifyIncoming": false,
"VerifyOutgoing": false,
"VerifyServerHostname": false
},
"NodeName": "",
"ServerName": ""
},
"TaggedAddresses": {},
"Telemetry": {
"AllowedPrefixes": [],
@ -417,11 +450,6 @@
"UnixSocketMode": "",
"UnixSocketUser": "",
"UseStreamingBackend": false,
"VerifyIncoming": false,
"VerifyIncomingHTTPS": false,
"VerifyIncomingRPC": false,
"VerifyOutgoing": false,
"VerifyServerHostname": false,
"Version": "",
"VersionPrerelease": "",
"Watches": []

View File

@ -647,6 +647,48 @@ telemetry {
statsite_address = "HpFwKB8R"
disable_compat_1.9 = true
}
tls {
defaults {
ca_file = "a5tY0opl"
ca_path = "bN63LpXu"
cert_file = "hB4PoxkL"
key_file = "Po0hB1tY"
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
tls_min_version = "yU0uIp1A"
verify_incoming = true
verify_outgoing = true
}
internal_rpc {
ca_file = "mKl19Utl"
ca_path = "lOp1nhPa"
cert_file = "dfJ4oPln"
key_file = "aL1Knkpo"
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
tls_min_version = "lPo1MklP"
verify_incoming = true
verify_outgoing = true
verify_server_hostname = true
}
https {
ca_file = "7Yu1PolM"
ca_path = "nu4PlHzn"
cert_file = "1yrhPlMk"
key_file = "1bHapOkL"
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
tls_min_version = "mK14iOpz"
verify_incoming = true
verify_outgoing = true
}
grpc {
ca_file = "lOp1nhJk"
ca_path = "fLponKpl"
cert_file = "a674klPn"
key_file = "1y4prKjl"
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
tls_min_version = "lPo4fNkl"
verify_incoming = true
}
}
tls_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
tls_min_version = "pAOWafkR"
tls_prefer_server_cipher_suites = true

View File

@ -644,6 +644,47 @@
"statsite_address": "HpFwKB8R",
"disable_compat_1.9": true
},
"tls": {
"defaults": {
"ca_file": "a5tY0opl",
"ca_path": "bN63LpXu",
"cert_file": "hB4PoxkL",
"key_file": "Po0hB1tY",
"tls_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"tls_min_version": "yU0uIp1A",
"verify_incoming": true,
"verify_outgoing": true
},
"internal_rpc": {
"ca_file": "mKl19Utl",
"ca_path": "lOp1nhPa",
"cert_file": "dfJ4oPln",
"key_file": "aL1Knkpo",
"tls_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"tls_min_version": "lPo1MklP",
"verify_incoming": true,
"verify_outgoing": true
},
"https": {
"ca_file": "7Yu1PolM",
"ca_path": "nu4PlHzn",
"cert_file": "1yrhPlMk",
"key_file": "1bHapOkL",
"tls_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"tls_min_version": "mK14iOpz",
"verify_incoming": true,
"verify_outgoing": true
},
"grpc": {
"ca_file": "lOp1nhJk",
"ca_path": "fLponKpl",
"cert_file": "a674klPn",
"key_file": "1y4prKjl",
"tls_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"tls_min_version": "lPo4fNkl",
"verify_incoming": true
}
},
"tls_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"tls_min_version": "pAOWafkR",
"tls_prefer_server_cipher_suites": true,

View File

@ -280,19 +280,8 @@ func (ac *AutoConfig) updateTLSSettingsInConfig(_ AutoConfigOptions, resp *pbaut
return nil
}
// add in TLS configuration
if resp.Config.TLS == nil {
resp.Config.TLS = &pbconfig.TLS{}
}
resp.Config.TLS.VerifyServerHostname = ac.tlsConfigurator.VerifyServerHostname()
base := ac.tlsConfigurator.Base()
resp.Config.TLS.VerifyOutgoing = base.VerifyOutgoing
resp.Config.TLS.MinVersion = base.TLSMinVersion
resp.Config.TLS.PreferServerCipherSuites = base.PreferServerCipherSuites
var err error
resp.Config.TLS.CipherSuites, err = tlsutil.CipherString(base.CipherSuites)
resp.Config.TLS, err = ac.tlsConfigurator.AutoConfigTLSSettings()
return err
}

View File

@ -11,11 +11,12 @@ import (
"testing"
"time"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/memberlist"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest"
@ -166,14 +167,13 @@ func TestAutoConfigInitialConfiguration(t *testing.T) {
err = ioutil.WriteFile(keyfile, []byte(key), 0600)
require.NoError(t, err)
c.TLSConfig.CAFile = cafile
c.TLSConfig.CertFile = certfile
c.TLSConfig.KeyFile = keyfile
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.VerifyIncoming = true
c.TLSConfig.VerifyServerHostname = true
c.TLSConfig.TLSMinVersion = "tls12"
c.TLSConfig.PreferServerCipherSuites = true
c.TLSConfig.InternalRPC.CAFile = cafile
c.TLSConfig.InternalRPC.CertFile = certfile
c.TLSConfig.InternalRPC.KeyFile = keyfile
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.VerifyIncoming = true
c.TLSConfig.InternalRPC.VerifyServerHostname = true
c.TLSConfig.InternalRPC.TLSMinVersion = "tls12"
c.ConnectEnabled = true
c.AutoEncryptAllowTLS = true
@ -187,10 +187,12 @@ func TestAutoConfigInitialConfiguration(t *testing.T) {
// TODO: use s.config.TLSConfig directly instead of creating a new one?
conf := tlsutil.Config{
CAFile: s.config.TLSConfig.CAFile,
VerifyServerHostname: s.config.TLSConfig.VerifyServerHostname,
VerifyOutgoing: s.config.TLSConfig.VerifyOutgoing,
Domain: s.config.TLSConfig.Domain,
InternalRPC: tlsutil.ProtocolConfig{
CAFile: s.config.TLSConfig.InternalRPC.CAFile,
VerifyServerHostname: s.config.TLSConfig.InternalRPC.VerifyServerHostname,
VerifyOutgoing: s.config.TLSConfig.InternalRPC.VerifyOutgoing,
},
Domain: s.config.TLSConfig.Domain,
}
codec, err := insecureRPCClient(s, conf)
require.NoError(t, err)
@ -281,10 +283,9 @@ func TestAutoConfigInitialConfiguration(t *testing.T) {
RetryJoinLAN: []string{joinAddr.String()},
},
TLS: &pbconfig.TLS{
VerifyOutgoing: true,
VerifyServerHostname: true,
MinVersion: "tls12",
PreferServerCipherSuites: true,
VerifyOutgoing: true,
VerifyServerHostname: true,
MinVersion: "tls12",
},
},
},
@ -414,42 +415,42 @@ func TestAutoConfig_updateTLSSettingsInConfig(t *testing.T) {
cases := map[string]testCase{
"secure": {
tlsConfig: tlsutil.Config{
VerifyOutgoing: true,
VerifyServerHostname: true,
TLSMinVersion: "tls12",
PreferServerCipherSuites: true,
CAFile: cafile,
CipherSuites: parseCiphers(t, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
InternalRPC: tlsutil.ProtocolConfig{
VerifyServerHostname: true,
VerifyOutgoing: true,
TLSMinVersion: "tls12",
CAFile: cafile,
CipherSuites: parseCiphers(t, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
},
},
expected: pbautoconf.AutoConfigResponse{
Config: &pbconfig.Config{
TLS: &pbconfig.TLS{
VerifyOutgoing: true,
VerifyServerHostname: true,
MinVersion: "tls12",
PreferServerCipherSuites: true,
CipherSuites: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
VerifyOutgoing: true,
VerifyServerHostname: true,
MinVersion: "tls12",
CipherSuites: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
},
},
},
},
"less-secure": {
tlsConfig: tlsutil.Config{
VerifyOutgoing: true,
VerifyServerHostname: false,
TLSMinVersion: "tls10",
PreferServerCipherSuites: false,
CAFile: cafile,
CipherSuites: parseCiphers(t, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
InternalRPC: tlsutil.ProtocolConfig{
VerifyServerHostname: false,
VerifyOutgoing: true,
TLSMinVersion: "tls10",
CAFile: cafile,
CipherSuites: parseCiphers(t, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
},
},
expected: pbautoconf.AutoConfigResponse{
Config: &pbconfig.Config{
TLS: &pbconfig.TLS{
VerifyOutgoing: true,
VerifyServerHostname: false,
MinVersion: "tls10",
PreferServerCipherSuites: false,
CipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
VerifyOutgoing: true,
VerifyServerHostname: false,
MinVersion: "tls10",
CipherSuites: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
},
},
},
@ -631,12 +632,13 @@ func TestAutoConfig_updateTLSCertificatesInConfig(t *testing.T) {
ConnectEnabled: true,
},
tlsConfig: tlsutil.Config{
VerifyOutgoing: true,
VerifyServerHostname: true,
TLSMinVersion: "tls12",
PreferServerCipherSuites: true,
CAFile: cafile,
CipherSuites: parseCiphers(t, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
InternalRPC: tlsutil.ProtocolConfig{
VerifyServerHostname: true,
VerifyOutgoing: true,
TLSMinVersion: "tls12",
CAFile: cafile,
CipherSuites: parseCiphers(t, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
},
},
expected: pbautoconf.AutoConfigResponse{
CARoots: pbroots,
@ -649,12 +651,13 @@ func TestAutoConfig_updateTLSCertificatesInConfig(t *testing.T) {
ConnectEnabled: true,
},
tlsConfig: tlsutil.Config{
VerifyOutgoing: true,
VerifyServerHostname: true,
TLSMinVersion: "tls12",
PreferServerCipherSuites: true,
CAFile: cafile,
CipherSuites: parseCiphers(t, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
InternalRPC: tlsutil.ProtocolConfig{
VerifyServerHostname: true,
VerifyOutgoing: true,
TLSMinVersion: "tls12",
CAFile: cafile,
CipherSuites: parseCiphers(t, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
},
},
opts: AutoConfigOptions{
NodeName: "test",

View File

@ -8,10 +8,11 @@ import (
"strings"
"testing"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/testrpc"
@ -38,11 +39,11 @@ func TestAutoEncryptSign(t *testing.T) {
tests := []test{
{Name: "Works with defaults", Config: tlsutil.Config{}, ConnError: false},
{Name: "Works with good root", Config: tlsutil.Config{CAFile: root}, ConnError: false},
{Name: "VerifyOutgoing fails because of bad root", Config: tlsutil.Config{CAFile: badRoot}, ConnError: true},
{Name: "VerifyServerHostname fails", Config: tlsutil.Config{VerifyServerHostname: true, CAFile: root}, ConnError: false, RPCError: true},
{Name: "Works with good root", Config: tlsutil.Config{InternalRPC: tlsutil.ProtocolConfig{CAFile: root}}, ConnError: false},
{Name: "VerifyOutgoing fails because of bad root", Config: tlsutil.Config{InternalRPC: tlsutil.ProtocolConfig{CAFile: badRoot}}, ConnError: true},
{Name: "VerifyServerHostname fails", Config: tlsutil.Config{InternalRPC: tlsutil.ProtocolConfig{CAFile: root, VerifyServerHostname: true}}, ConnError: false, RPCError: true},
{Name: "VerifyServerHostname succeeds", Cert: "../../test/key/ourdomain_server.cer", Key: "../../test/key/ourdomain_server.key",
Config: tlsutil.Config{VerifyServerHostname: true, CAFile: root}, ConnError: false, RPCError: false},
Config: tlsutil.Config{InternalRPC: tlsutil.ProtocolConfig{VerifyServerHostname: true, CAFile: root}}, ConnError: false, RPCError: false},
}
for i, test := range tests {
@ -59,10 +60,10 @@ func TestAutoEncryptSign(t *testing.T) {
c.AutoEncryptAllowTLS = true
c.PrimaryDatacenter = "dc1"
c.Bootstrap = true
c.TLSConfig.CAFile = root
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.CertFile = cert
c.TLSConfig.KeyFile = key
c.TLSConfig.InternalRPC.CAFile = root
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.CertFile = cert
c.TLSConfig.InternalRPC.KeyFile = key
})
defer os.RemoveAll(dir)
defer s.Shutdown()

View File

@ -10,12 +10,13 @@ import (
"testing"
"time"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/serf/serf"
"github.com/stretchr/testify/require"
"golang.org/x/time/rate"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/consul/agent/grpc"
"github.com/hashicorp/consul/agent/grpc/resolver"
"github.com/hashicorp/consul/agent/pool"
@ -447,8 +448,8 @@ func TestClient_RPC_ConsulServerPing(t *testing.T) {
func TestClient_RPC_TLS(t *testing.T) {
t.Parallel()
_, conf1 := testServerConfig(t)
conf1.TLSConfig.VerifyIncoming = true
conf1.TLSConfig.VerifyOutgoing = true
conf1.TLSConfig.InternalRPC.VerifyIncoming = true
conf1.TLSConfig.InternalRPC.VerifyOutgoing = true
configureTLS(conf1)
s1, err := newServer(t, conf1)
if err != nil {
@ -457,7 +458,7 @@ func TestClient_RPC_TLS(t *testing.T) {
defer s1.Shutdown()
_, conf2 := testClientConfig(t)
conf2.TLSConfig.VerifyOutgoing = true
conf2.TLSConfig.InternalRPC.VerifyOutgoing = true
configureTLS(conf2)
c1 := newClient(t, conf2)
@ -660,8 +661,8 @@ func TestClient_SnapshotRPC_TLS(t *testing.T) {
t.Parallel()
_, conf1 := testServerConfig(t)
conf1.TLSConfig.VerifyIncoming = true
conf1.TLSConfig.VerifyOutgoing = true
conf1.TLSConfig.InternalRPC.VerifyIncoming = true
conf1.TLSConfig.InternalRPC.VerifyOutgoing = true
configureTLS(conf1)
s1, err := newServer(t, conf1)
if err != nil {
@ -670,7 +671,7 @@ func TestClient_SnapshotRPC_TLS(t *testing.T) {
defer s1.Shutdown()
_, conf2 := testClientConfig(t)
conf2.TLSConfig.VerifyOutgoing = true
conf2.TLSConfig.InternalRPC.VerifyOutgoing = true
configureTLS(conf2)
c1 := newClient(t, conf2)

View File

@ -19,8 +19,6 @@ import (
"testing"
"time"
"github.com/hashicorp/consul-net-rpc/go-msgpack/codec"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-memdb"
"github.com/hashicorp/raft"
@ -28,6 +26,9 @@ import (
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"github.com/hashicorp/consul-net-rpc/go-msgpack/codec"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/agent/consul/state"
@ -565,12 +566,12 @@ func TestRPC_TLSHandshakeTimeout(t *testing.T) {
dir1, s1 := testServerWithConfig(t, func(c *Config) {
c.RPCHandshakeTimeout = 10 * time.Millisecond
c.TLSConfig.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.CertFile = "../../test/hostname/Alice.crt"
c.TLSConfig.KeyFile = "../../test/hostname/Alice.key"
c.TLSConfig.VerifyServerHostname = true
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.VerifyIncoming = true
c.TLSConfig.InternalRPC.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/hostname/Alice.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/hostname/Alice.key"
c.TLSConfig.InternalRPC.VerifyServerHostname = true
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.VerifyIncoming = true
})
defer os.RemoveAll(dir1)
defer s1.Shutdown()
@ -661,12 +662,12 @@ func TestRPC_PreventsTLSNesting(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
dir1, s1 := testServerWithConfig(t, func(c *Config) {
c.TLSConfig.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.CertFile = "../../test/hostname/Alice.crt"
c.TLSConfig.KeyFile = "../../test/hostname/Alice.key"
c.TLSConfig.VerifyServerHostname = true
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.VerifyIncoming = false // saves us getting client cert setup
c.TLSConfig.InternalRPC.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/hostname/Alice.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/hostname/Alice.key"
c.TLSConfig.InternalRPC.VerifyServerHostname = true
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.VerifyIncoming = false // saves us getting client cert setup
c.TLSConfig.Domain = "consul"
})
defer os.RemoveAll(dir1)
@ -818,12 +819,12 @@ func TestRPC_RPCMaxConnsPerClient(t *testing.T) {
dir1, s1 := testServerWithConfig(t, func(c *Config) {
c.RPCMaxConnsPerClient = 2
if tc.tlsEnabled {
c.TLSConfig.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.CertFile = "../../test/hostname/Alice.crt"
c.TLSConfig.KeyFile = "../../test/hostname/Alice.key"
c.TLSConfig.VerifyServerHostname = true
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.VerifyIncoming = false // saves us getting client cert setup
c.TLSConfig.InternalRPC.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/hostname/Alice.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/hostname/Alice.key"
c.TLSConfig.InternalRPC.VerifyServerHostname = true
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.VerifyIncoming = false // saves us getting client cert setup
c.TLSConfig.Domain = "consul"
}
})
@ -1416,11 +1417,11 @@ func TestRPC_AuthorizeRaftRPC(t *testing.T) {
_, srv := testServerWithConfig(t, func(c *Config) {
c.TLSConfig.Domain = "consul." // consul. is the default value in agent/config
c.TLSConfig.CAFile = filepath.Join(dir, "ca.pem")
c.TLSConfig.CertFile = filepath.Join(dir, "srv1-server.dc1.consul.pem")
c.TLSConfig.KeyFile = filepath.Join(dir, "srv1-server.dc1.consul.key")
c.TLSConfig.VerifyIncoming = true
c.TLSConfig.VerifyServerHostname = true
c.TLSConfig.InternalRPC.CAFile = filepath.Join(dir, "ca.pem")
c.TLSConfig.InternalRPC.CertFile = filepath.Join(dir, "srv1-server.dc1.consul.pem")
c.TLSConfig.InternalRPC.KeyFile = filepath.Join(dir, "srv1-server.dc1.consul.key")
c.TLSConfig.InternalRPC.VerifyIncoming = true
c.TLSConfig.InternalRPC.VerifyServerHostname = true
// Enable Auto-Encrypt so that Connect CA roots are added to the
// tlsutil.Configurator.
c.AutoEncryptAllowTLS = true
@ -1509,12 +1510,14 @@ func TestRPC_AuthorizeRaftRPC(t *testing.T) {
certPath := tc.setupCert(t)
cfg := tlsutil.Config{
VerifyOutgoing: true,
VerifyServerHostname: true,
CAFile: filepath.Join(dir, "ca.pem"),
CertFile: certPath + ".pem",
KeyFile: certPath + ".key",
Domain: "consul",
InternalRPC: tlsutil.ProtocolConfig{
VerifyOutgoing: true,
VerifyServerHostname: true,
CAFile: filepath.Join(dir, "ca.pem"),
CertFile: certPath + ".pem",
KeyFile: certPath + ".key",
},
Domain: "consul",
}
c, err := tlsutil.NewConfigurator(cfg, hclog.New(nil))
require.NoError(t, err)

View File

@ -22,7 +22,6 @@ import (
"go.etcd.io/bbolt"
"github.com/armon/go-metrics"
"github.com/hashicorp/consul-net-rpc/net/rpc"
connlimit "github.com/hashicorp/go-connlimit"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-memdb"
@ -33,6 +32,8 @@ import (
"golang.org/x/time/rate"
"google.golang.org/grpc"
"github.com/hashicorp/consul-net-rpc/net/rpc"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/consul/authmethod"
"github.com/hashicorp/consul/agent/consul/authmethod/ssoauth"

View File

@ -115,7 +115,7 @@ func (s *Server) setupSerfConfig(opts setupSerfOptions) (*serf.Config, error) {
conf.Tags["nonvoter"] = "1"
conf.Tags["read_replica"] = "1"
}
if s.config.TLSConfig.CAPath != "" || s.config.TLSConfig.CAFile != "" {
if s.config.TLSConfig.InternalRPC.CAPath != "" || s.config.TLSConfig.InternalRPC.CAFile != "" {
conf.Tags["use_tls"] = "1"
}

View File

@ -16,10 +16,11 @@ import (
"github.com/hashicorp/consul/ipaddr"
"github.com/hashicorp/consul-net-rpc/net/rpc"
"github.com/hashicorp/go-uuid"
"golang.org/x/time/rate"
"github.com/hashicorp/consul-net-rpc/net/rpc"
"github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/agent/metadata"
"github.com/hashicorp/consul/agent/structs"
@ -75,9 +76,9 @@ func testServerACLConfig(c *Config) {
}
func configureTLS(config *Config) {
config.TLSConfig.CAFile = "../../test/ca/root.cer"
config.TLSConfig.CertFile = "../../test/key/ourdomain.cer"
config.TLSConfig.KeyFile = "../../test/key/ourdomain.key"
config.TLSConfig.InternalRPC.CAFile = "../../test/ca/root.cer"
config.TLSConfig.InternalRPC.CertFile = "../../test/key/ourdomain.cer"
config.TLSConfig.InternalRPC.KeyFile = "../../test/key/ourdomain.key"
}
var id int64
@ -709,12 +710,12 @@ func TestServer_JoinWAN_viaMeshGateway(t *testing.T) {
c.PrimaryDatacenter = "dc1"
c.Bootstrap = true
// tls
c.TLSConfig.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.CertFile = "../../test/hostname/Bob.crt"
c.TLSConfig.KeyFile = "../../test/hostname/Bob.key"
c.TLSConfig.VerifyIncoming = true
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.VerifyServerHostname = true
c.TLSConfig.InternalRPC.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/hostname/Bob.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/hostname/Bob.key"
c.TLSConfig.InternalRPC.VerifyIncoming = true
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.VerifyServerHostname = true
// wanfed
c.ConnectMeshGatewayWANFederationEnabled = true
})
@ -728,12 +729,12 @@ func TestServer_JoinWAN_viaMeshGateway(t *testing.T) {
c.PrimaryDatacenter = "dc1"
c.Bootstrap = true
// tls
c.TLSConfig.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.CertFile = "../../test/hostname/Betty.crt"
c.TLSConfig.KeyFile = "../../test/hostname/Betty.key"
c.TLSConfig.VerifyIncoming = true
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.VerifyServerHostname = true
c.TLSConfig.InternalRPC.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/hostname/Betty.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/hostname/Betty.key"
c.TLSConfig.InternalRPC.VerifyIncoming = true
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.VerifyServerHostname = true
// wanfed
c.ConnectMeshGatewayWANFederationEnabled = true
})
@ -747,12 +748,12 @@ func TestServer_JoinWAN_viaMeshGateway(t *testing.T) {
c.PrimaryDatacenter = "dc1"
c.Bootstrap = true
// tls
c.TLSConfig.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.CertFile = "../../test/hostname/Bonnie.crt"
c.TLSConfig.KeyFile = "../../test/hostname/Bonnie.key"
c.TLSConfig.VerifyIncoming = true
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.VerifyServerHostname = true
c.TLSConfig.InternalRPC.CAFile = "../../test/hostname/CertAuth.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/hostname/Bonnie.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/hostname/Bonnie.key"
c.TLSConfig.InternalRPC.VerifyIncoming = true
c.TLSConfig.InternalRPC.VerifyOutgoing = true
c.TLSConfig.InternalRPC.VerifyServerHostname = true
// wanfed
c.ConnectMeshGatewayWANFederationEnabled = true
})
@ -1136,8 +1137,8 @@ func TestServer_JoinLAN_TLS(t *testing.T) {
t.Parallel()
_, conf1 := testServerConfig(t)
conf1.TLSConfig.VerifyIncoming = true
conf1.TLSConfig.VerifyOutgoing = true
conf1.TLSConfig.InternalRPC.VerifyIncoming = true
conf1.TLSConfig.InternalRPC.VerifyOutgoing = true
configureTLS(conf1)
s1, err := newServer(t, conf1)
if err != nil {
@ -1148,8 +1149,8 @@ func TestServer_JoinLAN_TLS(t *testing.T) {
_, conf2 := testServerConfig(t)
conf2.Bootstrap = false
conf2.TLSConfig.VerifyIncoming = true
conf2.TLSConfig.VerifyOutgoing = true
conf2.TLSConfig.InternalRPC.VerifyIncoming = true
conf2.TLSConfig.InternalRPC.VerifyOutgoing = true
configureTLS(conf2)
s2, err := newServer(t, conf2)
if err != nil {
@ -1410,9 +1411,9 @@ func TestServer_TLSToNoTLS(t *testing.T) {
// Add a second server with TLS configured
dir2, s2 := testServerWithConfig(t, func(c *Config) {
c.Bootstrap = false
c.TLSConfig.CAFile = "../../test/client_certs/rootca.crt"
c.TLSConfig.CertFile = "../../test/client_certs/server.crt"
c.TLSConfig.KeyFile = "../../test/client_certs/server.key"
c.TLSConfig.InternalRPC.CAFile = "../../test/client_certs/rootca.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/client_certs/server.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/client_certs/server.key"
})
defer os.RemoveAll(dir2)
defer s2.Shutdown()
@ -1442,10 +1443,10 @@ func TestServer_TLSForceOutgoingToNoTLS(t *testing.T) {
// Add a second server with TLS and VerifyOutgoing set
dir2, s2 := testServerWithConfig(t, func(c *Config) {
c.Bootstrap = false
c.TLSConfig.CAFile = "../../test/client_certs/rootca.crt"
c.TLSConfig.CertFile = "../../test/client_certs/server.crt"
c.TLSConfig.KeyFile = "../../test/client_certs/server.key"
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.InternalRPC.CAFile = "../../test/client_certs/rootca.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/client_certs/server.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/client_certs/server.key"
c.TLSConfig.InternalRPC.VerifyOutgoing = true
})
defer os.RemoveAll(dir2)
defer s2.Shutdown()
@ -1464,10 +1465,10 @@ func TestServer_TLSToFullVerify(t *testing.T) {
t.Parallel()
// Set up a server with TLS and VerifyIncoming set
dir1, s1 := testServerWithConfig(t, func(c *Config) {
c.TLSConfig.CAFile = "../../test/client_certs/rootca.crt"
c.TLSConfig.CertFile = "../../test/client_certs/server.crt"
c.TLSConfig.KeyFile = "../../test/client_certs/server.key"
c.TLSConfig.VerifyOutgoing = true
c.TLSConfig.InternalRPC.CAFile = "../../test/client_certs/rootca.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/client_certs/server.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/client_certs/server.key"
c.TLSConfig.InternalRPC.VerifyOutgoing = true
})
defer os.RemoveAll(dir1)
defer s1.Shutdown()
@ -1477,9 +1478,9 @@ func TestServer_TLSToFullVerify(t *testing.T) {
// Add a second server with TLS configured
dir2, s2 := testServerWithConfig(t, func(c *Config) {
c.Bootstrap = false
c.TLSConfig.CAFile = "../../test/client_certs/rootca.crt"
c.TLSConfig.CertFile = "../../test/client_certs/server.crt"
c.TLSConfig.KeyFile = "../../test/client_certs/server.key"
c.TLSConfig.InternalRPC.CAFile = "../../test/client_certs/rootca.crt"
c.TLSConfig.InternalRPC.CertFile = "../../test/client_certs/server.crt"
c.TLSConfig.InternalRPC.KeyFile = "../../test/client_certs/server.key"
})
defer os.RemoveAll(dir2)
defer s2.Shutdown()

View File

@ -6,9 +6,10 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/consul-net-rpc/net/rpc"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/agent/pool"
"github.com/hashicorp/consul/agent/structs"

View File

@ -29,8 +29,8 @@ func TestSubscribeBackend_IntegrationWithServer_TLSEnabled(t *testing.T) {
// TODO(rb): add tests for the wanfed/alpn variations
_, conf1 := testServerConfig(t)
conf1.TLSConfig.VerifyIncoming = true
conf1.TLSConfig.VerifyOutgoing = true
conf1.TLSConfig.InternalRPC.VerifyIncoming = true
conf1.TLSConfig.InternalRPC.VerifyOutgoing = true
conf1.RPCConfig.EnableStreaming = true
configureTLS(conf1)
server, err := newServer(t, conf1)
@ -161,11 +161,11 @@ func TestSubscribeBackend_IntegrationWithServer_TLSReload(t *testing.T) {
// Set up a server with initially bad certificates.
_, conf1 := testServerConfig(t)
conf1.TLSConfig.VerifyIncoming = true
conf1.TLSConfig.VerifyOutgoing = true
conf1.TLSConfig.CAFile = "../../test/ca/root.cer"
conf1.TLSConfig.CertFile = "../../test/key/ssl-cert-snakeoil.pem"
conf1.TLSConfig.KeyFile = "../../test/key/ssl-cert-snakeoil.key"
conf1.TLSConfig.InternalRPC.VerifyIncoming = true
conf1.TLSConfig.InternalRPC.VerifyOutgoing = true
conf1.TLSConfig.InternalRPC.CAFile = "../../test/ca/root.cer"
conf1.TLSConfig.InternalRPC.CertFile = "../../test/key/ssl-cert-snakeoil.pem"
conf1.TLSConfig.InternalRPC.KeyFile = "../../test/key/ssl-cert-snakeoil.key"
conf1.RPCConfig.EnableStreaming = true
server, err := newServer(t, conf1)
@ -199,8 +199,8 @@ func TestSubscribeBackend_IntegrationWithServer_TLSReload(t *testing.T) {
// Reload the server with valid certs
newConf := server.config.TLSConfig
newConf.CertFile = "../../test/key/ourdomain.cer"
newConf.KeyFile = "../../test/key/ourdomain.key"
newConf.InternalRPC.CertFile = "../../test/key/ourdomain.cer"
newConf.InternalRPC.KeyFile = "../../test/key/ourdomain.key"
server.tlsConfigurator.Update(newConf)
// Try the subscribe call again
@ -212,7 +212,7 @@ func TestSubscribeBackend_IntegrationWithServer_TLSReload(t *testing.T) {
}
func clientConfigVerifyOutgoing(config *Config) {
config.TLSConfig.VerifyOutgoing = true
config.TLSConfig.InternalRPC.VerifyOutgoing = true
}
// retryFailedConn forces the ClientConn to reset its backoff timer and retry the connection,

View File

@ -143,11 +143,13 @@ func TestNewDialer_IntegrationWithTLSEnabledHandler(t *testing.T) {
registerWithGRPC(t, res)
tlsConf, err := tlsutil.NewConfigurator(tlsutil.Config{
VerifyIncoming: true,
VerifyOutgoing: true,
CAFile: "../../test/hostname/CertAuth.crt",
CertFile: "../../test/hostname/Alice.crt",
KeyFile: "../../test/hostname/Alice.key",
InternalRPC: tlsutil.ProtocolConfig{
VerifyIncoming: true,
CAFile: "../../test/hostname/CertAuth.crt",
CertFile: "../../test/hostname/Alice.crt",
KeyFile: "../../test/hostname/Alice.key",
VerifyOutgoing: true,
},
}, hclog.New(nil))
require.NoError(t, err)
@ -188,14 +190,16 @@ func TestNewDialer_IntegrationWithTLSEnabledHandler_viaMeshGateway(t *testing.T)
registerWithGRPC(t, res)
tlsConf, err := tlsutil.NewConfigurator(tlsutil.Config{
VerifyIncoming: true,
VerifyOutgoing: true,
VerifyServerHostname: true,
CAFile: "../../test/hostname/CertAuth.crt",
CertFile: "../../test/hostname/Bob.crt",
KeyFile: "../../test/hostname/Bob.key",
Domain: "consul",
NodeName: "bob",
InternalRPC: tlsutil.ProtocolConfig{
VerifyIncoming: true,
CAFile: "../../test/hostname/CertAuth.crt",
CertFile: "../../test/hostname/Bob.crt",
KeyFile: "../../test/hostname/Bob.key",
VerifyOutgoing: true,
VerifyServerHostname: true,
},
Domain: "consul",
NodeName: "bob",
}, hclog.New(nil))
require.NoError(t, err)
@ -216,14 +220,16 @@ func TestNewDialer_IntegrationWithTLSEnabledHandler_viaMeshGateway(t *testing.T)
t.Cleanup(srv.shutdown)
clientTLSConf, err := tlsutil.NewConfigurator(tlsutil.Config{
VerifyIncoming: true,
VerifyOutgoing: true,
VerifyServerHostname: true,
CAFile: "../../test/hostname/CertAuth.crt",
CertFile: "../../test/hostname/Betty.crt",
KeyFile: "../../test/hostname/Betty.key",
Domain: "consul",
NodeName: "betty",
InternalRPC: tlsutil.ProtocolConfig{
VerifyIncoming: true,
CAFile: "../../test/hostname/CertAuth.crt",
CertFile: "../../test/hostname/Betty.crt",
KeyFile: "../../test/hostname/Betty.key",
VerifyOutgoing: true,
VerifyServerHostname: true,
},
Domain: "consul",
NodeName: "betty",
}, hclog.New(nil))
require.NoError(t, err)

View File

@ -14,11 +14,12 @@ import (
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/consul/agent/grpc/internal/testservice"
"github.com/hashicorp/consul/agent/metadata"
"github.com/hashicorp/consul/agent/pool"
"github.com/hashicorp/consul/tlsutil"
"github.com/hashicorp/go-hclog"
)
type testServer struct {

View File

@ -11,9 +11,10 @@ import (
"sync/atomic"
"time"
"github.com/hashicorp/yamux"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/consul-net-rpc/net/rpc"
"github.com/hashicorp/yamux"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib"

View File

@ -93,7 +93,7 @@ func NewBaseDeps(configLoader ConfigLoader, logOut io.Writer) (BaseDeps, error)
return d, fmt.Errorf("failed to initialize telemetry: %w", err)
}
d.TLSConfigurator, err = tlsutil.NewConfigurator(cfg.ToTLSUtilConfig(), d.Logger)
d.TLSConfigurator, err = tlsutil.NewConfigurator(cfg.TLS, d.Logger)
if err != nil {
return d, err
}

View File

@ -222,11 +222,9 @@ func NewGRPCServer(s *Server, tlsConfigurator *tlsutil.Configurator) *grpc.Serve
recovery.StreamServerInterceptor(recoveryOpts...),
),
}
if tlsConfigurator != nil {
if tlsConfigurator.Cert() != nil {
creds := credentials.NewTLS(tlsConfigurator.IncomingGRPCConfig())
opts = append(opts, grpc.Creds(creds))
}
if tlsConfigurator != nil && tlsConfigurator.GRPCTLSConfigured() {
creds := credentials.NewTLS(tlsConfigurator.IncomingGRPCConfig())
opts = append(opts, grpc.Creds(creds))
}
srv := grpc.NewServer(opts...)
envoy_discovery_v3.RegisterAggregatedDiscoveryServiceServer(srv, s)

View File

@ -207,7 +207,7 @@ func (c *cmd) run(args []string) int {
ui.Info(fmt.Sprintf(" Cluster Addr: %v (LAN: %d, WAN: %d)", config.AdvertiseAddrLAN,
config.SerfPortLAN, config.SerfPortWAN))
ui.Info(fmt.Sprintf(" Encrypt: Gossip: %v, TLS-Outgoing: %v, TLS-Incoming: %v, Auto-Encrypt-TLS: %t",
config.EncryptKey != "", config.VerifyOutgoing, config.VerifyIncoming, config.AutoEncryptTLS || config.AutoEncryptAllowTLS))
config.EncryptKey != "", config.TLS.InternalRPC.VerifyOutgoing, config.TLS.InternalRPC.VerifyIncoming, config.AutoEncryptTLS || config.AutoEncryptAllowTLS))
// Enable log streaming
ui.Output("")
ui.Output("Log data will now stream in as it occurs:\n")

View File

@ -252,14 +252,16 @@ func (m *GossipEncryption) GetVerifyOutgoing() bool {
}
type TLS struct {
VerifyOutgoing bool `protobuf:"varint,1,opt,name=VerifyOutgoing,proto3" json:"VerifyOutgoing,omitempty"`
VerifyServerHostname bool `protobuf:"varint,2,opt,name=VerifyServerHostname,proto3" json:"VerifyServerHostname,omitempty"`
CipherSuites string `protobuf:"bytes,3,opt,name=CipherSuites,proto3" json:"CipherSuites,omitempty"`
MinVersion string `protobuf:"bytes,4,opt,name=MinVersion,proto3" json:"MinVersion,omitempty"`
PreferServerCipherSuites bool `protobuf:"varint,5,opt,name=PreferServerCipherSuites,proto3" json:"PreferServerCipherSuites,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
VerifyOutgoing bool `protobuf:"varint,1,opt,name=VerifyOutgoing,proto3" json:"VerifyOutgoing,omitempty"`
VerifyServerHostname bool `protobuf:"varint,2,opt,name=VerifyServerHostname,proto3" json:"VerifyServerHostname,omitempty"`
CipherSuites string `protobuf:"bytes,3,opt,name=CipherSuites,proto3" json:"CipherSuites,omitempty"`
MinVersion string `protobuf:"bytes,4,opt,name=MinVersion,proto3" json:"MinVersion,omitempty"`
// Deprecated_PreferServerCipherSuites is deprecated. It is no longer
// populated and should be ignored by clients.
Deprecated_PreferServerCipherSuites bool `protobuf:"varint,5,opt,name=Deprecated_PreferServerCipherSuites,json=DeprecatedPreferServerCipherSuites,proto3" json:"Deprecated_PreferServerCipherSuites,omitempty"` // Deprecated: Do not use.
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *TLS) Reset() { *m = TLS{} }
@ -323,9 +325,10 @@ func (m *TLS) GetMinVersion() string {
return ""
}
func (m *TLS) GetPreferServerCipherSuites() bool {
// Deprecated: Do not use.
func (m *TLS) GetDeprecated_PreferServerCipherSuites() bool {
if m != nil {
return m.PreferServerCipherSuites
return m.Deprecated_PreferServerCipherSuites
}
return false
}
@ -687,59 +690,59 @@ func init() {
func init() { proto.RegisterFile("proto/pbconfig/config.proto", fileDescriptor_aefa824db7b74d77) }
var fileDescriptor_aefa824db7b74d77 = []byte{
// 823 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x55, 0xdd, 0x6e, 0xe3, 0x44,
0x14, 0xc6, 0xf1, 0xd6, 0x6d, 0x26, 0xb0, 0xda, 0x9d, 0x5d, 0x8a, 0xc5, 0x4f, 0x88, 0x2c, 0xb4,
0x2a, 0x08, 0xb5, 0xa8, 0x08, 0x04, 0x88, 0x9b, 0x34, 0x59, 0x41, 0xd8, 0x34, 0x44, 0x76, 0x58,
0x24, 0x6e, 0x90, 0xe3, 0x9c, 0x24, 0x23, 0x9c, 0x19, 0x6b, 0x3c, 0xe9, 0xca, 0xaf, 0xc0, 0x13,
0xf0, 0x2e, 0xbc, 0x00, 0x77, 0xf0, 0x08, 0x50, 0x5e, 0x64, 0x75, 0x66, 0xc6, 0x8e, 0xdd, 0x26,
0x57, 0xc9, 0xf9, 0xbe, 0x6f, 0xce, 0x9c, 0x33, 0xe7, 0xc7, 0xe4, 0xbd, 0x4c, 0x0a, 0x25, 0x2e,
0xb2, 0x79, 0x22, 0xf8, 0x92, 0xad, 0x2e, 0xcc, 0xcf, 0xb9, 0x46, 0xa9, 0x67, 0xac, 0xe0, 0xef,
0x16, 0xf1, 0x06, 0xfa, 0x2f, 0xed, 0x12, 0x32, 0x8c, 0x55, 0x9c, 0x00, 0x57, 0x20, 0x7d, 0xa7,
0xe7, 0x9c, 0xb5, 0xc3, 0x1a, 0x42, 0x3f, 0x25, 0x8f, 0xa7, 0x92, 0x6d, 0x62, 0x59, 0xd4, 0x64,
0x2d, 0x2d, 0xbb, 0x4f, 0xd0, 0x77, 0xc9, 0xc9, 0x44, 0x2c, 0x60, 0x12, 0x6f, 0xc0, 0x77, 0xb5,
0xa8, 0xb2, 0x69, 0x8f, 0x74, 0x22, 0x58, 0x6d, 0x80, 0x2b, 0x4d, 0x3f, 0xd0, 0x74, 0x1d, 0xa2,
0xef, 0x93, 0xf6, 0x34, 0x96, 0x8a, 0x29, 0x26, 0xb8, 0xdf, 0xd6, 0xfc, 0x0e, 0xa0, 0x1f, 0x10,
0xb7, 0x3f, 0x18, 0xfb, 0x47, 0x3d, 0xe7, 0xac, 0x73, 0xd9, 0x39, 0xb7, 0x89, 0xf5, 0x07, 0xe3,
0x10, 0x71, 0xfa, 0x05, 0xe9, 0xf4, 0xb7, 0x4a, 0x3c, 0xe7, 0x89, 0x2c, 0x32, 0xe5, 0x7b, 0x5a,
0xf6, 0xa4, 0x92, 0xed, 0xa8, 0xb0, 0xae, 0xa3, 0xcf, 0x88, 0xf7, 0x9d, 0xc8, 0x73, 0x96, 0xf9,
0xc7, 0xfa, 0xc4, 0xc3, 0xf2, 0x84, 0x41, 0x43, 0xcb, 0xe2, 0xed, 0xb3, 0x71, 0xe4, 0x9f, 0x34,
0x6f, 0x9f, 0x8d, 0xa3, 0x10, 0xf1, 0x60, 0x59, 0xba, 0xa1, 0x5f, 0x11, 0x62, 0x7d, 0x63, 0x16,
0x8e, 0xd6, 0xfb, 0x4d, 0xa7, 0x3b, 0x3e, 0xac, 0x69, 0x69, 0x40, 0xde, 0x0c, 0x41, 0xc9, 0xe2,
0x07, 0xc1, 0xf8, 0xb8, 0x3f, 0xf1, 0x5b, 0x3d, 0xf7, 0xac, 0x1d, 0x36, 0xb0, 0x40, 0x91, 0x47,
0x77, 0x7d, 0xd0, 0x47, 0xc4, 0x7d, 0x01, 0x85, 0xad, 0x1d, 0xfe, 0xa5, 0xcf, 0xc8, 0xc3, 0x97,
0x20, 0xd9, 0xb2, 0x18, 0xf1, 0x44, 0x6c, 0x18, 0x5f, 0xe9, 0x8a, 0x9d, 0x84, 0x77, 0xd0, 0x9d,
0xee, 0xc7, 0xad, 0x5a, 0x09, 0xd4, 0xb9, 0x75, 0x5d, 0x89, 0x06, 0xff, 0x39, 0x3a, 0xfb, 0x3d,
0x7a, 0x67, 0x9f, 0x9e, 0x5e, 0x92, 0xa7, 0x06, 0x89, 0x40, 0xde, 0x80, 0xfc, 0x5e, 0xe4, 0x8a,
0x63, 0xcd, 0x4d, 0x14, 0x7b, 0x39, 0xcc, 0x7e, 0xc0, 0xb2, 0x35, 0xc8, 0x68, 0xcb, 0x14, 0xe4,
0xb6, 0x7d, 0x1a, 0x18, 0x36, 0xeb, 0x35, 0xe3, 0x2f, 0x41, 0xe6, 0xf8, 0xb6, 0xa6, 0x83, 0x6a,
0x08, 0xfd, 0x86, 0xf8, 0x53, 0x09, 0x4b, 0x90, 0xc6, 0x77, 0xc3, 0xdf, 0x91, 0xbe, 0xfb, 0x20,
0x1f, 0xfc, 0xe9, 0xea, 0xfe, 0xa2, 0x3e, 0x39, 0x7e, 0xce, 0xe3, 0x79, 0x0a, 0x0b, 0x9b, 0x5c,
0x69, 0xea, 0xf6, 0x14, 0x29, 0x4b, 0x8a, 0xd9, 0x6c, 0x6c, 0x47, 0x60, 0x07, 0xe0, 0xb9, 0x50,
0xa4, 0x80, 0x9c, 0x09, 0xbd, 0x34, 0x71, 0x28, 0x66, 0xe2, 0x37, 0xe0, 0x48, 0x99, 0x98, 0x2b,
0x5b, 0x8f, 0x9f, 0x78, 0xc5, 0x8d, 0x1b, 0x1d, 0x23, 0x8e, 0x5f, 0x85, 0xd0, 0x8f, 0xc8, 0x5b,
0x43, 0x58, 0xc6, 0xdb, 0x54, 0x59, 0x89, 0xa7, 0x25, 0x4d, 0x90, 0x7e, 0x46, 0x9e, 0x98, 0x20,
0x5f, 0x40, 0x31, 0x66, 0x79, 0xa9, 0x3d, 0xd6, 0xf1, 0xef, 0xa3, 0xe8, 0xc7, 0xc4, 0xd3, 0x31,
0xe4, 0xb6, 0xa3, 0x1f, 0xd7, 0xe6, 0xc9, 0x10, 0xa1, 0x15, 0xd0, 0xaf, 0xc9, 0xe9, 0x10, 0x32,
0x09, 0x49, 0xac, 0x60, 0xf1, 0xeb, 0x90, 0xe5, 0xfa, 0x35, 0x30, 0x19, 0x3d, 0xa2, 0x57, 0x2d,
0xdf, 0x09, 0xdf, 0xde, 0x29, 0x6a, 0x02, 0xfa, 0x25, 0x39, 0x35, 0x97, 0x6b, 0x57, 0x53, 0xac,
0x52, 0xae, 0x80, 0x27, 0xe0, 0x13, 0x1d, 0xda, 0x01, 0x16, 0xf3, 0xb9, 0x8e, 0xa6, 0xd6, 0xd3,
0x95, 0x10, 0x2a, 0x57, 0x32, 0xce, 0xfc, 0x8e, 0xc9, 0x67, 0x0f, 0x15, 0xfc, 0xde, 0x22, 0xed,
0x2a, 0x74, 0x5c, 0x5a, 0x23, 0xce, 0x14, 0x8b, 0xd3, 0xeb, 0x98, 0xc7, 0x2b, 0xc0, 0x0d, 0x63,
0xe7, 0xe3, 0x3e, 0x81, 0x8b, 0x29, 0x84, 0x2c, 0x65, 0x49, 0xac, 0x47, 0xd6, 0x54, 0xb6, 0x0e,
0x61, 0x15, 0xfa, 0x2b, 0xe0, 0x2a, 0x84, 0x44, 0xdc, 0x80, 0x2c, 0x6c, 0x85, 0x9b, 0x20, 0x76,
0x80, 0x2d, 0x8b, 0x2d, 0x73, 0x69, 0xd2, 0xa7, 0xe4, 0x48, 0x4b, 0x6d, 0x81, 0x8d, 0x41, 0x7f,
0x26, 0xa7, 0x26, 0x8a, 0x05, 0xb6, 0x23, 0x4b, 0x60, 0x2a, 0xc5, 0x0d, 0x5b, 0x80, 0xf4, 0xbd,
0x9e, 0x7b, 0xd6, 0xb9, 0xfc, 0xb0, 0x56, 0x93, 0x3b, 0x0a, 0x9d, 0x67, 0x78, 0xe0, 0x78, 0xf0,
0x13, 0x79, 0xe7, 0xc0, 0x11, 0xec, 0xb7, 0x7e, 0x92, 0x40, 0x9e, 0x0b, 0x39, 0x1a, 0x96, 0xeb,
0x7e, 0x87, 0x60, 0xaf, 0x46, 0x90, 0x48, 0x50, 0xa3, 0xa1, 0x7d, 0x88, 0xca, 0x0e, 0x58, 0x63,
0xc3, 0xe2, 0xda, 0xc1, 0x8d, 0x68, 0x86, 0x44, 0xaf, 0x87, 0x53, 0xe2, 0x0d, 0x27, 0x51, 0x54,
0xad, 0x2e, 0x6b, 0x61, 0xfa, 0xa3, 0x29, 0xc2, 0xae, 0x86, 0x8d, 0x81, 0x57, 0xf5, 0xd3, 0x54,
0xbc, 0x42, 0x27, 0x0f, 0xb4, 0x93, 0xca, 0xbe, 0xfa, 0xf6, 0xaf, 0xdb, 0xae, 0xf3, 0xcf, 0x6d,
0xd7, 0xf9, 0xf7, 0xb6, 0xeb, 0xfc, 0xf1, 0x7f, 0xf7, 0x8d, 0x5f, 0x3e, 0x59, 0x31, 0xb5, 0xde,
0xce, 0xcf, 0x13, 0xb1, 0xb9, 0x58, 0xc7, 0xf9, 0x9a, 0x25, 0x42, 0x66, 0xf8, 0x75, 0xcb, 0xb7,
0xe9, 0x45, 0xf3, 0x9b, 0x37, 0xf7, 0xb4, 0xfd, 0xf9, 0xeb, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5d,
0x66, 0xca, 0x39, 0x0c, 0x07, 0x00, 0x00,
// 831 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x55, 0xdd, 0x8e, 0xdb, 0x44,
0x14, 0xc6, 0x71, 0xeb, 0xdd, 0x4c, 0xa0, 0x6a, 0xa7, 0x65, 0xb1, 0xf8, 0x09, 0x91, 0x41, 0xd5,
0x82, 0xd0, 0x2e, 0x5a, 0x04, 0x02, 0x89, 0x9b, 0xec, 0xa6, 0x82, 0xd0, 0x6c, 0x88, 0xec, 0x50,
0x24, 0x6e, 0x90, 0xe3, 0x9c, 0x24, 0x23, 0x9c, 0x19, 0x6b, 0x3c, 0xd9, 0xca, 0xaf, 0xc0, 0x13,
0xf0, 0x2e, 0xbc, 0x00, 0x77, 0xf0, 0x08, 0x68, 0x79, 0x0b, 0xae, 0xaa, 0x33, 0x33, 0xfe, 0xdb,
0x26, 0x57, 0xc9, 0xf9, 0xbe, 0x6f, 0xce, 0x9c, 0x33, 0xe7, 0xc7, 0xe4, 0xbd, 0x4c, 0x0a, 0x25,
0xce, 0xb3, 0x45, 0x22, 0xf8, 0x8a, 0xad, 0xcf, 0xcd, 0xcf, 0x99, 0x46, 0xa9, 0x67, 0xac, 0xe0,
0xef, 0x0e, 0xf1, 0xae, 0xf4, 0x5f, 0xda, 0x27, 0x64, 0x14, 0xab, 0x38, 0x01, 0xae, 0x40, 0xfa,
0xce, 0xc0, 0x39, 0xed, 0x86, 0x0d, 0x84, 0x7e, 0x46, 0x1e, 0xcd, 0x24, 0xdb, 0xc6, 0xb2, 0x68,
0xc8, 0x3a, 0x5a, 0xf6, 0x3a, 0x41, 0xdf, 0x25, 0xc7, 0x53, 0xb1, 0x84, 0x69, 0xbc, 0x05, 0xdf,
0xd5, 0xa2, 0xca, 0xa6, 0x03, 0xd2, 0x8b, 0x60, 0xbd, 0x05, 0xae, 0x34, 0x7d, 0x4f, 0xd3, 0x4d,
0x88, 0xbe, 0x4f, 0xba, 0xb3, 0x58, 0x2a, 0xa6, 0x98, 0xe0, 0x7e, 0x57, 0xf3, 0x35, 0x40, 0x3f,
0x20, 0xee, 0xf0, 0x6a, 0xe2, 0xdf, 0x1f, 0x38, 0xa7, 0xbd, 0x8b, 0xde, 0x99, 0x4d, 0x6c, 0x78,
0x35, 0x09, 0x11, 0xa7, 0x5f, 0x92, 0xde, 0x70, 0xa7, 0xc4, 0x33, 0x9e, 0xc8, 0x22, 0x53, 0xbe,
0xa7, 0x65, 0x8f, 0x2b, 0x59, 0x4d, 0x85, 0x4d, 0x1d, 0x7d, 0x4a, 0xbc, 0xef, 0x44, 0x9e, 0xb3,
0xcc, 0x3f, 0xd2, 0x27, 0x1e, 0x94, 0x27, 0x0c, 0x1a, 0x5a, 0x16, 0x6f, 0x9f, 0x4f, 0x22, 0xff,
0xb8, 0x7d, 0xfb, 0x7c, 0x12, 0x85, 0x88, 0x07, 0xab, 0xd2, 0x0d, 0xfd, 0x9a, 0x10, 0xeb, 0x1b,
0xb3, 0x70, 0xb4, 0xde, 0x6f, 0x3b, 0xad, 0xf9, 0xb0, 0xa1, 0xa5, 0x01, 0x79, 0x33, 0x04, 0x25,
0x8b, 0x1f, 0x04, 0xe3, 0x93, 0xe1, 0xd4, 0xef, 0x0c, 0xdc, 0xd3, 0x6e, 0xd8, 0xc2, 0x02, 0x45,
0x1e, 0xde, 0xf5, 0x41, 0x1f, 0x12, 0xf7, 0x39, 0x14, 0xb6, 0x76, 0xf8, 0x97, 0x3e, 0x25, 0x0f,
0x5e, 0x80, 0x64, 0xab, 0x62, 0xcc, 0x13, 0xb1, 0x65, 0x7c, 0xad, 0x2b, 0x76, 0x1c, 0xde, 0x41,
0x6b, 0xdd, 0x8f, 0x3b, 0xb5, 0x16, 0xa8, 0x73, 0x9b, 0xba, 0x12, 0x0d, 0xfe, 0x77, 0x74, 0xf6,
0x7b, 0xf4, 0xce, 0x3e, 0x3d, 0xbd, 0x20, 0x4f, 0x0c, 0x12, 0x81, 0xbc, 0x01, 0xf9, 0xbd, 0xc8,
0x15, 0xc7, 0x9a, 0x9b, 0x28, 0xf6, 0x72, 0x98, 0xfd, 0x15, 0xcb, 0x36, 0x20, 0xa3, 0x1d, 0x53,
0x90, 0xdb, 0xf6, 0x69, 0x61, 0xd8, 0xac, 0xd7, 0x8c, 0xbf, 0x00, 0x99, 0xe3, 0xdb, 0x9a, 0x0e,
0x6a, 0x20, 0x34, 0x22, 0x1f, 0x8d, 0x20, 0x93, 0x90, 0xc4, 0x0a, 0x96, 0xbf, 0xce, 0x24, 0xac,
0x40, 0x9a, 0x6b, 0x5a, 0xae, 0xb1, 0x85, 0x8e, 0x2f, 0x3b, 0xbe, 0x13, 0x06, 0xb5, 0xfc, 0x90,
0x3a, 0xf8, 0xd3, 0xd5, 0x8d, 0x47, 0x7d, 0x72, 0xf4, 0x8c, 0xc7, 0x8b, 0x14, 0x96, 0x36, 0xeb,
0xd2, 0xd4, 0x7d, 0x2b, 0x52, 0x96, 0x14, 0xf3, 0xf9, 0xc4, 0xce, 0x46, 0x0d, 0xe0, 0xb9, 0x50,
0xa4, 0x80, 0x9c, 0xc9, 0xa9, 0x34, 0x71, 0x5a, 0xe6, 0xe2, 0x37, 0xe0, 0x48, 0x99, 0x64, 0x2a,
0x5b, 0xcf, 0xa5, 0x78, 0xc9, 0x8d, 0x1b, 0x1d, 0x31, 0xce, 0x65, 0x85, 0xd0, 0x8f, 0xc9, 0x5b,
0x23, 0x58, 0xc5, 0xbb, 0x54, 0x59, 0x89, 0xa7, 0x25, 0x6d, 0x90, 0x7e, 0x4e, 0x1e, 0x9b, 0x20,
0x9f, 0x43, 0x31, 0x61, 0x79, 0xa9, 0x3d, 0xd2, 0xf1, 0xef, 0xa3, 0xe8, 0x27, 0xc4, 0xd3, 0x31,
0xe4, 0xb6, 0xd5, 0x1f, 0x35, 0x06, 0xcd, 0x10, 0xa1, 0x15, 0xd0, 0x6f, 0xc8, 0x49, 0xe3, 0xb5,
0x47, 0x2c, 0xd7, 0xaf, 0x81, 0xc9, 0xe8, 0xd9, 0xd5, 0x0f, 0xfc, 0x76, 0xad, 0x68, 0x08, 0xe8,
0x57, 0xe4, 0xc4, 0x5c, 0xae, 0x5d, 0xcd, 0xb0, 0x7c, 0xb9, 0x02, 0x9e, 0x80, 0x4f, 0x74, 0x68,
0x07, 0x58, 0xcc, 0xe7, 0x3a, 0x9a, 0x59, 0x4f, 0x97, 0x42, 0xa8, 0x5c, 0xc9, 0x38, 0xf3, 0x7b,
0x26, 0x9f, 0x3d, 0x54, 0xf0, 0x7b, 0x87, 0x74, 0xab, 0xd0, 0x71, 0x9b, 0x8d, 0x39, 0x53, 0x2c,
0x4e, 0xaf, 0x63, 0x1e, 0xaf, 0x01, 0x57, 0x8f, 0x1d, 0x9c, 0xd7, 0x09, 0xdc, 0x58, 0x21, 0x64,
0x29, 0x4b, 0x62, 0x3d, 0xcb, 0xa6, 0xb2, 0x4d, 0x08, 0xab, 0x30, 0x5c, 0x03, 0x57, 0x21, 0x24,
0xe2, 0x06, 0x64, 0x61, 0x2b, 0xdc, 0x06, 0xb1, 0x03, 0x6c, 0x59, 0x6c, 0x99, 0x4b, 0x93, 0x3e,
0x21, 0xf7, 0xb5, 0xd4, 0x16, 0xd8, 0x18, 0xf4, 0x67, 0x72, 0x62, 0xa2, 0x58, 0x62, 0x3b, 0xb2,
0x04, 0x66, 0x52, 0xdc, 0xb0, 0x25, 0x48, 0xdf, 0x1b, 0xb8, 0xa7, 0xbd, 0x8b, 0x0f, 0x1b, 0x35,
0xb9, 0xa3, 0xd0, 0x79, 0x86, 0x07, 0x8e, 0x07, 0x3f, 0x91, 0x77, 0x0e, 0x1c, 0xc1, 0x7e, 0x1b,
0x26, 0x09, 0xe4, 0xb9, 0x90, 0xe3, 0x51, 0xf9, 0x1d, 0xa8, 0x11, 0xec, 0xd5, 0x08, 0x12, 0x09,
0x6a, 0x3c, 0xb2, 0x0f, 0x51, 0xd9, 0x01, 0x6b, 0xad, 0x5e, 0xdc, 0x47, 0xb8, 0x2a, 0xcd, 0x90,
0xe8, 0xbd, 0x71, 0x42, 0xbc, 0xd1, 0x34, 0x8a, 0xaa, 0x9d, 0x66, 0x2d, 0x4c, 0x7f, 0x3c, 0x43,
0xd8, 0xd5, 0xb0, 0x31, 0xf0, 0xaa, 0x61, 0x9a, 0x8a, 0x97, 0xe8, 0xe4, 0x9e, 0x76, 0x52, 0xd9,
0x97, 0xdf, 0xfe, 0x75, 0xdb, 0x77, 0xfe, 0xb9, 0xed, 0x3b, 0xff, 0xde, 0xf6, 0x9d, 0x3f, 0xfe,
0xeb, 0xbf, 0xf1, 0xcb, 0xa7, 0x6b, 0xa6, 0x36, 0xbb, 0xc5, 0x59, 0x22, 0xb6, 0xe7, 0x9b, 0x38,
0xdf, 0xb0, 0x44, 0xc8, 0x0c, 0x3f, 0x7b, 0xf9, 0x2e, 0x3d, 0x6f, 0x7f, 0x0c, 0x17, 0x9e, 0xb6,
0xbf, 0x78, 0x15, 0x00, 0x00, 0xff, 0xff, 0x4f, 0xaf, 0xda, 0x68, 0x25, 0x07, 0x00, 0x00,
}
func (m *Config) Marshal() (dAtA []byte, err error) {
@ -978,9 +981,9 @@ func (m *TLS) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if m.PreferServerCipherSuites {
if m.Deprecated_PreferServerCipherSuites {
i--
if m.PreferServerCipherSuites {
if m.Deprecated_PreferServerCipherSuites {
dAtA[i] = 1
} else {
dAtA[i] = 0
@ -1451,7 +1454,7 @@ func (m *TLS) Size() (n int) {
if l > 0 {
n += 1 + l + sovConfig(uint64(l))
}
if m.PreferServerCipherSuites {
if m.Deprecated_PreferServerCipherSuites {
n += 2
}
if m.XXX_unrecognized != nil {
@ -2338,7 +2341,7 @@ func (m *TLS) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field PreferServerCipherSuites", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Deprecated_PreferServerCipherSuites", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
@ -2355,7 +2358,7 @@ func (m *TLS) Unmarshal(dAtA []byte) error {
break
}
}
m.PreferServerCipherSuites = bool(v != 0)
m.Deprecated_PreferServerCipherSuites = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipConfig(dAtA[iNdEx:])

View File

@ -32,7 +32,9 @@ message TLS {
bool VerifyServerHostname = 2;
string CipherSuites = 3;
string MinVersion = 4;
bool PreferServerCipherSuites = 5;
// Deprecated_PreferServerCipherSuites is deprecated. It is no longer
// populated and should be ignored by clients.
bool Deprecated_PreferServerCipherSuites = 5 [deprecated = true];
}
message ACL {

View File

@ -18,6 +18,7 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/consul/logging"
"github.com/hashicorp/consul/proto/pbconfig"
)
// ALPNWrapper is a function that is used to wrap a non-TLS connection and
@ -44,42 +45,14 @@ var tlsLookup = map[string]uint16{
"tls13": tls.VersionTLS13,
}
// Config used to create tls.Config
type Config struct {
// ProtocolConfig contains configuration for a given protocol.
type ProtocolConfig struct {
// VerifyIncoming is used to verify the authenticity of incoming
// connections. This means that TCP requests are forbidden, only
// allowing for TLS. TLS connections must match a provided certificate
// authority. This can be used to force client auth.
VerifyIncoming bool
// VerifyIncomingRPC is used to verify the authenticity of incoming RPC
// connections. This means that TCP requests are forbidden, only
// allowing for TLS. TLS connections must match a provided certificate
// authority. This can be used to force client auth.
VerifyIncomingRPC bool
// VerifyIncomingHTTPS is used to verify the authenticity of incoming
// HTTPS connections. This means that TCP requests are forbidden, only
// allowing for TLS. TLS connections must match a provided certificate
// authority. This can be used to force client auth.
VerifyIncomingHTTPS bool
// VerifyOutgoing is used to verify the authenticity of outgoing
// connections. This means that TLS requests are used, and TCP
// requests are not made. TLS connections must match a provided
// certificate authority. This is used to verify authenticity of server
// nodes.
VerifyOutgoing bool
// VerifyServerHostname is used to enable hostname verification of
// servers. This ensures that the certificate presented is valid for
// server.<datacenter>.<domain>. This prevents a compromised client
// from being restarted as a server, and then intercepting request
// traffic as well as being added as a raft peer. This should be
// enabled by default with VerifyOutgoing, but for legacy reasons we
// cannot break existing clients.
VerifyServerHostname bool
// CAFile is a path to a certificate authority file. This is used with
// VerifyIncoming or VerifyOutgoing to verify the TLS connection.
CAFile string
@ -97,6 +70,62 @@ type Config struct {
// connections. Must be provided to serve TLS connections.
KeyFile string
// TLSMinVersion is the minimum accepted TLS version that can be used.
TLSMinVersion string
// CipherSuites is the list of TLS cipher suites to use.
//
// The values should be a list of the following values:
//
// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
// TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
// TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
// TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
//
// todo(fs): IMHO, we should also support the raw 0xNNNN values from
// todo(fs): https://golang.org/pkg/crypto/tls/#pkg-constants
// todo(fs): since they are standardized by IANA.
CipherSuites []uint16
// VerifyOutgoing is used to verify the authenticity of outgoing
// connections. This means that TLS requests are used, and TCP
// requests are not made. TLS connections must match a provided
// certificate authority. This is used to verify authenticity of server
// nodes.
//
// Note: this setting doesn't apply to the gRPC configuration, as Consul
// makes no outgoing connections using this protocol.
VerifyOutgoing bool
// VerifyServerHostname is used to enable hostname verification of
// servers. This ensures that the certificate presented is valid for
// server.<datacenter>.<domain>. This prevents a compromised client
// from being restarted as a server, and then intercepting request
// traffic as well as being added as a raft peer. This should be
// enabled by default with VerifyOutgoing, but for legacy reasons we
// cannot break existing clients.
//
// Note: this setting only applies to the Internal RPC configuration.
VerifyServerHostname bool
}
// Config configures the Configurator.
type Config struct {
// InternalRPC is used to configure the internal multiplexed RPC protocol.
InternalRPC ProtocolConfig
// GRPC is used to configure the external (e.g. xDS) gRPC protocol.
GRPC ProtocolConfig
// HTTPS is used to configure the external HTTPS protocol.
HTTPS ProtocolConfig
// Node name is the name we use to advertise. Defaults to hostname.
NodeName string
@ -107,16 +136,6 @@ type Config struct {
// Domain is the Consul TLD being used. Defaults to "consul."
Domain string
// TLSMinVersion is the minimum accepted TLS version that can be used.
TLSMinVersion string
// CipherSuites is the list of TLS cipher suites to use.
CipherSuites []uint16
// PreferServerCipherSuites specifies whether to prefer the server's
// ciphersuite over the client ciphersuites.
PreferServerCipherSuites bool
// EnableAgentTLSForChecks is used to apply the agent's TLS settings in
// order to configure the HTTP client used for health checks. Enabling
// this allows HTTP checks to present a client certificate and verify
@ -151,27 +170,30 @@ func SpecificDC(dc string, tlsWrap DCWrapper) Wrapper {
}
}
// autoTLS stores configuration that is received from the auto-encrypt or
// auto-config features.
type autoTLS struct {
extraCAPems []string
connectCAPems []string
cert *tls.Certificate
verifyServerHostname bool
}
// protocolConfig contains the loaded state (e.g. x509 certificates) for a given
// ProtocolConfig.
type protocolConfig struct {
// cert is the TLS certificate configured manually by the cert_file/key_file
// options in the configuration file.
cert *tls.Certificate
// manual stores the TLS CA and cert received from Configurator.Update which
// generally comes from the agent configuration.
type manual struct {
caPems []string
cert *tls.Certificate
// caPool containing only the caPems. This CertPool should be used instead of
// the Configurator.caPool when only the Agent TLS CA is allowed.
caPool *x509.CertPool
// manualCAPEMs contains the PEM-encoded CA certificates provided manually by
// the ca_file/ca_path options in the configuration file.
manualCAPEMs []string
// manualCAPool is a pool containing only manualCAPEM, for cases where it is
// not appropriate to trust the Connect CA (e.g. when verifying server identity
// in AuthorizeServerConn).
manualCAPool *x509.CertPool
// combinedCAPool is a pool containing both manualCAPEMs and the certificates
// received from auto-config/auto-encrypt.
combinedCAPool *x509.CertPool
}
// Configurator provides tls.Config and net.Dial wrappers to enable TLS for
// clients and servers, for both HTTPS and RPC requests.
// clients and servers, for internal RPC, and external gRPC and HTTPS connections.
//
// Configurator receives an initial TLS configuration from agent configuration,
// and receives updates from config reloads, auto-encrypt, and auto-config.
type Configurator struct {
@ -181,15 +203,25 @@ type Configurator struct {
version uint64
// lock synchronizes access to all fields on this struct except for logger and version.
lock sync.RWMutex
base *Config
autoTLS autoTLS
manual manual
caPool *x509.CertPool
lock sync.RWMutex
base *Config
// peerDatacenterUseTLS is a map of DC name to a bool indicating if the DC
// uses TLS for RPC requests.
peerDatacenterUseTLS map[string]bool
grpc protocolConfig
https protocolConfig
internalRPC protocolConfig
// autoTLS stores configuration that is received from the auto-encrypt or
// auto-config features.
autoTLS struct {
extraCAPems []string
connectCAPems []string
cert *tls.Certificate
verifyServerHostname bool
}
// logger is not protected by a lock. It must never be changed after
// Configurator is created.
logger hclog.Logger
@ -215,11 +247,12 @@ func NewConfigurator(config Config, logger hclog.Logger) (*Configurator, error)
return c, nil
}
// ManualCAPems returns the currently loaded CAs in PEM format.
// ManualCAPems returns the currently loaded CAs for the internal RPC protocol
// in PEM format. It is used in the auto-config/auto-encrypt endpoints.
func (c *Configurator) ManualCAPems() []string {
c.lock.RLock()
defer c.lock.RUnlock()
return c.manual.caPems
return c.internalRPC.manualCAPEMs
}
// Update updates the internal configuration which is used to generate
@ -229,36 +262,92 @@ func (c *Configurator) Update(config Config) error {
c.lock.Lock()
defer c.lock.Unlock()
cert, err := loadKeyPair(config.CertFile, config.KeyFile)
grpc, err := c.loadProtocolConfig(config, config.GRPC)
if err != nil {
return err
}
pems, err := LoadCAs(config.CAFile, config.CAPath)
https, err := c.loadProtocolConfig(config, config.HTTPS)
if err != nil {
return err
}
caPool, err := newX509CertPool(pems, c.autoTLS.extraCAPems, c.autoTLS.connectCAPems)
if err != nil {
return err
}
if err = validateConfig(config, caPool, cert); err != nil {
return err
}
manualCAPool, err := newX509CertPool(pems)
internalRPC, err := c.loadProtocolConfig(config, config.InternalRPC)
if err != nil {
return err
}
c.base = &config
c.manual.cert = cert
c.manual.caPems = pems
c.manual.caPool = manualCAPool
c.caPool = caPool
c.grpc = *grpc
c.https = *https
c.internalRPC = *internalRPC
atomic.AddUint64(&c.version, 1)
c.log("Update")
return nil
}
// loadProtocolConfig loads the certificates etc. for a given ProtocolConfig
// and performs validation.
func (c *Configurator) loadProtocolConfig(base Config, lc ProtocolConfig) (*protocolConfig, error) {
if min := lc.TLSMinVersion; min != "" {
if _, ok := tlsLookup[min]; !ok {
versions := strings.Join(tlsVersions(), ", ")
return nil, fmt.Errorf("TLSMinVersion: value %s not supported, please specify one of [%s]", min, versions)
}
}
cert, err := loadKeyPair(lc.CertFile, lc.KeyFile)
if err != nil {
return nil, err
}
pems, err := LoadCAs(lc.CAFile, lc.CAPath)
if err != nil {
return nil, err
}
manualPool, err := newX509CertPool(pems)
if err != nil {
return nil, err
}
combinedPool, err := newX509CertPool(pems, c.autoTLS.connectCAPems, c.autoTLS.extraCAPems)
if err != nil {
return nil, err
}
if lc.VerifyIncoming {
// Both auto-config and auto-encrypt require verifying the connection from the
// client to the server for secure operation. In order to be able to verify the
// server's certificate we must have some CA certs already provided. Therefore,
// even though both of those features can push down extra CA certificates which
// could be used to verify incoming connections, we still must consider it an
// error if none are provided in the initial configuration as those features
// cannot be successfully enabled without providing CA certificates to use those
// features.
if combinedPool == nil {
return nil, fmt.Errorf("VerifyIncoming set but no CA certificates were provided")
}
// We will use the auto_encrypt/auto_config cert for TLS in the incoming APIs
// when available. Therefore the check here will ensure that either we enabled
// one of those two features or a certificate and key were provided manually
if cert == nil && !base.AutoTLS {
return nil, fmt.Errorf("VerifyIncoming requires either a Cert and Key pair in the configuration file, or auto_encrypt/auto_config be enabled")
}
}
// Ensure we have a CA if VerifyOutgoing is set.
if lc.VerifyOutgoing && combinedPool == nil {
return nil, fmt.Errorf("VerifyOutgoing set but no CA certificates were provided")
}
return &protocolConfig{
cert: cert,
manualCAPEMs: pems,
manualCAPool: manualPool,
combinedCAPool: combinedPool,
}, nil
}
// UpdateAutoTLSCA updates the autoEncrypt.caPems. This is supposed to be called
// from the server in order to be able to accept TLS connections with TLS
// certificates.
@ -267,15 +356,30 @@ func (c *Configurator) UpdateAutoTLSCA(connectCAPems []string) error {
c.lock.Lock()
defer c.lock.Unlock()
pool, err := newX509CertPool(c.manual.caPems, c.autoTLS.extraCAPems, connectCAPems)
makePool := func(l protocolConfig) (*x509.CertPool, error) {
return newX509CertPool(l.manualCAPEMs, c.autoTLS.extraCAPems, connectCAPems)
}
// Make all of the pools up-front (before assigning anything) so that if any of
// them fails, we aren't left in a half-applied state.
internalRPCPool, err := makePool(c.internalRPC)
if err != nil {
return err
}
if err = validateConfig(*c.base, pool, c.manual.cert); err != nil {
grpcPool, err := makePool(c.grpc)
if err != nil {
return err
}
httpsPool, err := makePool(c.https)
if err != nil {
return err
}
c.autoTLS.connectCAPems = connectCAPems
c.caPool = pool
c.internalRPC.combinedCAPool = internalRPCPool
c.grpc.combinedCAPool = grpcPool
c.https.combinedCAPool = httpsPool
atomic.AddUint64(&c.version, 1)
c.log("UpdateAutoTLSCA")
return nil
@ -308,15 +412,33 @@ func (c *Configurator) UpdateAutoTLS(manualCAPems, connectCAPems []string, pub,
c.lock.Lock()
defer c.lock.Unlock()
pool, err := newX509CertPool(c.manual.caPems, manualCAPems, connectCAPems)
makePool := func(l protocolConfig) (*x509.CertPool, error) {
return newX509CertPool(l.manualCAPEMs, manualCAPems, connectCAPems)
}
// Make all of the pools up-front (before assigning anything) so that if any of
// them fails, we aren't left in a half-applied state.
internalRPCPool, err := makePool(c.internalRPC)
if err != nil {
return err
}
grpcPool, err := makePool(c.grpc)
if err != nil {
return err
}
httpsPool, err := makePool(c.https)
if err != nil {
return err
}
c.autoTLS.extraCAPems = manualCAPems
c.autoTLS.connectCAPems = connectCAPems
c.autoTLS.cert = &cert
c.caPool = pool
c.autoTLS.verifyServerHostname = verifyServerHostname
c.internalRPC.combinedCAPool = internalRPCPool
c.grpc.combinedCAPool = grpcPool
c.https.combinedCAPool = httpsPool
atomic.AddUint64(&c.version, 1)
c.log("UpdateAutoTLS")
return nil
@ -368,46 +490,6 @@ func newX509CertPool(groups ...[]string) (*x509.CertPool, error) {
return pool, nil
}
// validateConfig checks that config is valid and does not conflict with the pool
// or cert.
func validateConfig(config Config, pool *x509.CertPool, cert *tls.Certificate) error {
// Check if a minimum TLS version was set
if config.TLSMinVersion != "" {
if _, ok := tlsLookup[config.TLSMinVersion]; !ok {
versions := strings.Join(tlsVersions(), ", ")
return fmt.Errorf("TLSMinVersion: value %s not supported, please specify one of [%s]", config.TLSMinVersion, versions)
}
}
// Ensure we have a CA if VerifyOutgoing is set
if config.VerifyOutgoing && pool == nil {
return fmt.Errorf("VerifyOutgoing set, and no CA certificate provided!")
}
// Ensure we have a CA and cert if VerifyIncoming is set
if config.anyVerifyIncoming() {
if pool == nil {
// both auto-config and auto-encrypt require verifying the connection from the client to the server for secure
// operation. In order to be able to verify the servers certificate we must have some CA certs already provided.
// Therefore, even though both of those features can push down extra CA certificates which could be used to
// verify incoming connections, we still must consider it an error if none are provided in the initial configuration
// as those features cannot be successfully enabled without providing CA certificates to use those features.
return fmt.Errorf("VerifyIncoming set but no CA certificates were provided")
}
// We will use the auto_encrypt/auto_config cert for TLS in the incoming APIs when available. Therefore the check
// here will ensure that either we enabled one of those two features or a certificate and key were provided manually
if cert == nil && !config.AutoTLS {
return fmt.Errorf("VerifyIncoming requires either a Cert and Key pair in the configuration file, or auto_encrypt/auto_config be enabled")
}
}
return nil
}
func (c Config) anyVerifyIncoming() bool {
return c.VerifyIncoming || c.VerifyIncomingRPC || c.VerifyIncomingHTTPS
}
func loadKeyPair(certFile, keyFile string) (*tls.Certificate, error) {
if certFile == "" || keyFile == "" {
return nil, nil
@ -465,33 +547,43 @@ func LoadCAs(caFile, caPath string) ([]string, error) {
return pems, nil
}
// internalRPCTLSConfig generates a *tls.Config for the internal RPC protocol.
//
// This function acquires a read lock because it reads from the config.
func (c *Configurator) internalRPCTLSConfig(verifyIncoming bool) *tls.Config {
c.lock.RLock()
defer c.lock.RUnlock()
config := c.commonTLSConfig(
c.internalRPC,
c.base.InternalRPC,
verifyIncoming,
)
config.InsecureSkipVerify = !c.base.InternalRPC.VerifyServerHostname
return config
}
// commonTLSConfig generates a *tls.Config from the base configuration the
// Configurator has. It accepts an additional flag in case a config is needed
// for incoming TLS connections.
// This function acquires a read lock because it reads from the config.
func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config {
// this needs to be outside of RLock because it acquires an RLock itself
verifyServerHostname := c.VerifyServerHostname()
c.lock.RLock()
defer c.lock.RUnlock()
tlsConfig := &tls.Config{
InsecureSkipVerify: !verifyServerHostname,
}
func (c *Configurator) commonTLSConfig(state protocolConfig, cfg ProtocolConfig, verifyIncoming bool) *tls.Config {
var tlsConfig tls.Config
// Set the cipher suites
if len(c.base.CipherSuites) != 0 {
tlsConfig.CipherSuites = c.base.CipherSuites
if len(cfg.CipherSuites) != 0 {
tlsConfig.CipherSuites = cfg.CipherSuites
}
tlsConfig.PreferServerCipherSuites = c.base.PreferServerCipherSuites
// GetCertificate is used when acting as a server and responding to
// client requests. Default to the manually configured cert, but allow
// autoEncrypt cert too so that a client can encrypt incoming
// connections without having a manual cert configured.
tlsConfig.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
return c.Cert(), nil
if state.cert != nil {
return state.cert, nil
}
return c.autoTLS.cert, nil
}
// GetClientCertificate is used when acting as a client and responding
@ -500,7 +592,7 @@ func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config {
tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
cert := c.autoTLS.cert
if cert == nil {
cert = c.manual.cert
cert = state.cert
}
if cert == nil {
@ -512,39 +604,53 @@ func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config {
return cert, nil
}
tlsConfig.ClientCAs = c.caPool
tlsConfig.RootCAs = c.caPool
tlsConfig.ClientCAs = state.combinedCAPool
tlsConfig.RootCAs = state.combinedCAPool
// This is possible because tlsLookup also contains "" with golang's
// default (tls10). And because the initial check makes sure the
// version correctly matches.
tlsConfig.MinVersion = tlsLookup[c.base.TLSMinVersion]
tlsConfig.MinVersion = tlsLookup[cfg.TLSMinVersion]
// Set ClientAuth if necessary
if verifyIncoming {
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
}
return tlsConfig
return &tlsConfig
}
// Cert returns the certificate used for connections on the internal RPC protocol.
//
// This function acquires a read lock because it reads from the config.
func (c *Configurator) Cert() *tls.Certificate {
c.lock.RLock()
defer c.lock.RUnlock()
cert := c.manual.cert
cert := c.internalRPC.cert
if cert == nil {
cert = c.autoTLS.cert
}
return cert
}
// VerifyIncomingRPC returns true if the configuration has enabled either
// VerifyIncoming, or VerifyIncomingRPC
// GRPCTLSConfigured returns whether there's a TLS certificate configured for
// gRPC (either manually or by auto-config/auto-encrypt). It is checked, along
// with the presence of an HTTPS port, to determine whether to enable TLS on
// incoming gRPC connections.
//
// This function acquires a read lock because it reads from the config.
func (c *Configurator) GRPCTLSConfigured() bool {
c.lock.RLock()
defer c.lock.RUnlock()
return c.grpc.cert != nil || c.autoTLS.cert != nil
}
// VerifyIncomingRPC returns true if we should verify incoming connnections to
// the internal RPC protocol.
func (c *Configurator) VerifyIncomingRPC() bool {
c.lock.RLock()
defer c.lock.RUnlock()
return c.base.VerifyIncoming || c.base.VerifyIncomingRPC
return c.base.InternalRPC.VerifyIncoming
}
// This function acquires a read lock because it reads from the config.
@ -553,15 +659,15 @@ func (c *Configurator) outgoingRPCTLSEnabled() bool {
defer c.lock.RUnlock()
// use TLS if AutoEncrypt or VerifyOutgoing are enabled.
return c.base.AutoTLS || c.base.VerifyOutgoing
return c.base.AutoTLS || c.base.InternalRPC.VerifyOutgoing
}
// MutualTLSCapable returns true if Configurator has a CA and a local TLS
// certificate configured.
// MutualTLSCapable returns true if Configurator has a CA and a local TL
// certificate configured on the internal RPC protocol.
func (c *Configurator) MutualTLSCapable() bool {
c.lock.RLock()
defer c.lock.RUnlock()
return c.caPool != nil && (c.autoTLS.cert != nil || c.manual.cert != nil)
return c.internalRPC.combinedCAPool != nil && (c.autoTLS.cert != nil || c.internalRPC.cert != nil)
}
// This function acquires a read lock because it reads from the config.
@ -571,13 +677,14 @@ func (c *Configurator) verifyOutgoing() bool {
// If AutoEncryptTLS is enabled and there is a CA, then verify
// outgoing.
if c.base.AutoTLS && c.caPool != nil {
if c.base.AutoTLS && c.internalRPC.combinedCAPool != nil {
return true
}
return c.base.VerifyOutgoing
return c.base.InternalRPC.VerifyOutgoing
}
// This function acquires a read lock because it reads from the config.
func (c *Configurator) ServerSNI(dc, nodeName string) string {
// Strip the trailing '.' from the domain if any
domain := strings.TrimSuffix(c.domain(), ".")
@ -610,19 +717,45 @@ func (c *Configurator) serverNameOrNodeName() string {
func (c *Configurator) VerifyServerHostname() bool {
c.lock.RLock()
defer c.lock.RUnlock()
return c.base.VerifyServerHostname || c.autoTLS.verifyServerHostname
return c.base.InternalRPC.VerifyServerHostname || c.autoTLS.verifyServerHostname
}
// IncomingGRPCConfig generates a *tls.Config for incoming GRPC connections.
func (c *Configurator) IncomingGRPCConfig() *tls.Config {
c.log("IncomingGRPCConfig")
// AutoConfigTLSSettings constructs the pbconfig.TLS that will be returned by
// servers in the auto-config endpoint.
func (c *Configurator) AutoConfigTLSSettings() (*pbconfig.TLS, error) {
c.lock.RLock()
defer c.lock.RUnlock()
// false has the effect that this config doesn't require a client cert
// verification. This is because there is no verify_incoming_grpc
// configuration option. And using verify_incoming would be backwards
// incompatible, because even if it was set before, it didn't have an
// effect on the grpc server.
config := c.commonTLSConfig(false)
cfg := c.base.InternalRPC
cipherString, err := CipherString(cfg.CipherSuites)
if err != nil {
return nil, err
}
return &pbconfig.TLS{
VerifyOutgoing: cfg.VerifyOutgoing,
VerifyServerHostname: cfg.VerifyServerHostname || c.autoTLS.verifyServerHostname,
MinVersion: cfg.TLSMinVersion,
CipherSuites: cipherString,
}, nil
}
// IncomingGRPCConfig generates a *tls.Config for incoming external (e.g. xDS)
// GRPC connections.
//
// This function acquires a read lock because it reads from the config.
func (c *Configurator) IncomingGRPCConfig() *tls.Config {
c.log("IncomingGRPConfig")
c.lock.RLock()
defer c.lock.RUnlock()
config := c.commonTLSConfig(
c.grpc,
c.base.GRPC,
c.base.GRPC.VerifyIncoming,
)
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return c.IncomingGRPCConfig(), nil
}
@ -632,7 +765,7 @@ func (c *Configurator) IncomingGRPCConfig() *tls.Config {
// IncomingRPCConfig generates a *tls.Config for incoming RPC connections.
func (c *Configurator) IncomingRPCConfig() *tls.Config {
c.log("IncomingRPCConfig")
config := c.commonTLSConfig(c.VerifyIncomingRPC())
config := c.internalRPCTLSConfig(c.base.InternalRPC.VerifyIncoming)
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return c.IncomingRPCConfig(), nil
}
@ -645,7 +778,7 @@ func (c *Configurator) IncomingALPNRPCConfig(alpnProtos []string) *tls.Config {
c.log("IncomingALPNRPCConfig")
// Since the ALPN-RPC variation is indirectly exposed to the internet via
// mesh gateways we force mTLS and full server name verification.
config := c.commonTLSConfig(true)
config := c.internalRPCTLSConfig(true)
config.InsecureSkipVerify = false
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
@ -662,7 +795,7 @@ func (c *Configurator) IncomingALPNRPCConfig(alpnProtos []string) *tls.Config {
// usecase ever.
func (c *Configurator) IncomingInsecureRPCConfig() *tls.Config {
c.log("IncomingInsecureRPCConfig")
config := c.commonTLSConfig(false)
config := c.internalRPCTLSConfig(false)
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return c.IncomingInsecureRPCConfig(), nil
}
@ -674,10 +807,13 @@ func (c *Configurator) IncomingHTTPSConfig() *tls.Config {
c.log("IncomingHTTPSConfig")
c.lock.RLock()
verifyIncoming := c.base.VerifyIncoming || c.base.VerifyIncomingHTTPS
c.lock.RUnlock()
defer c.lock.RUnlock()
config := c.commonTLSConfig(verifyIncoming)
config := c.commonTLSConfig(
c.https,
c.base.HTTPS,
c.base.HTTPS.VerifyIncoming,
)
config.NextProtos = []string{"h2", "http/1.1"}
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return c.IncomingHTTPSConfig(), nil
@ -706,22 +842,22 @@ func (c *Configurator) OutgoingTLSConfigForCheck(skipVerify bool, serverName str
if serverName == "" {
serverName = c.serverNameOrNodeName()
}
config := c.commonTLSConfig(false)
config := c.internalRPCTLSConfig(false)
config.InsecureSkipVerify = skipVerify
config.ServerName = serverName
return config
}
// OutgoingRPCConfig generates a *tls.Config for outgoing RPC connections. If
// there is a CA or VerifyOutgoing is set, a *tls.Config will be provided,
// otherwise we assume that no TLS should be used.
// OutgoingRPCConfig generates a *tls.Config for outgoing internal RPC
// connections. If there is a CA or VerifyOutgoing is set, a *tls.Config
// will be provided, otherwise we assume that no TLS should be used.
func (c *Configurator) OutgoingRPCConfig() *tls.Config {
c.log("OutgoingRPCConfig")
if !c.outgoingRPCTLSEnabled() {
return nil
}
return c.commonTLSConfig(false)
return c.internalRPCTLSConfig(false)
}
// outgoingALPNRPCConfig generates a *tls.Config for outgoing RPC connections
@ -737,7 +873,7 @@ func (c *Configurator) outgoingALPNRPCConfig() *tls.Config {
// Since the ALPN-RPC variation is indirectly exposed to the internet via
// mesh gateways we force mTLS and full server name verification.
config := c.commonTLSConfig(true)
config := c.internalRPCTLSConfig(true)
config.InsecureSkipVerify = false
return config
}
@ -912,7 +1048,7 @@ func (c *Configurator) AuthorizeServerConn(dc string, conn TLSConn) error {
}
c.lock.RLock()
caPool := c.manual.caPool
caPool := c.internalRPC.manualCAPool
c.lock.RUnlock()
expected := c.ServerSNI(dc, "")

File diff suppressed because it is too large Load Diff

View File

@ -245,7 +245,7 @@ Refer to the [Security](/docs/security) chapter for additional information about
```hcl
node_name = "consul-server"
server = true
server = true
ui_config {
enabled = true
}
@ -257,13 +257,21 @@ retry_join = [
"consul-server2",
"consul-server3"
]
encrypt = "aPuGh+5UDskRAbkLaXRzFoSOcSM+5vAK+NEYOWHJH7w="
verify_incoming = true
verify_outgoing = true
verify_server_hostname = true
ca_file = "/consul/config/certs/consul-agent-ca.pem"
cert_file = "/consul/config/certs/dc1-server-consul-0.pem"
key_file = "/consul/config/certs/dc1-server-consul-0-key.pem"
encrypt = "aPuGh+5UDskRAbkLaXRzFoSOcSM+5vAK+NEYOWHJH7w="
tls {
defaults {
verify_incoming = true
verify_outgoing = true
ca_file = "/consul/config/certs/consul-agent-ca.pem"
cert_file = "/consul/config/certs/dc1-server-consul-0.pem"
key_file = "/consul/config/certs/dc1-server-consul-0-key.pem"
}
internal_rpc {
verify_server_hostname = true
}
}
```
@ -281,12 +289,18 @@ key_file = "/consul/config/certs/dc1-server-consul-0-key.pem"
},
"retry_join": ["consul-server1", "consul-server2"],
"encrypt": "aPuGh+5UDskRAbkLaXRzFoSOcSM+5vAK+NEYOWHJH7w=",
"verify_incoming": true,
"verify_outgoing": true,
"verify_server_hostname": true,
"ca_file": "/consul/config/certs/consul-agent-ca.pem",
"cert_file": "/consul/config/certs/dc1-server-consul-0.pem",
"key_file": "/consul/config/certs/dc1-server-consul-0-key.pem"
"tls": {
"defaults": {
"verify_incoming": true,
"verify_outgoing": true,
"ca_file": "/consul/config/certs/consul-agent-ca.pem",
"cert_file": "/consul/config/certs/dc1-server-consul-0.pem",
"key_file": "/consul/config/certs/dc1-server-consul-0-key.pem"
},
"internal_rpc": {
"verify_server_hostname": true
}
}
}
```

View File

@ -2446,114 +2446,197 @@ There are also a number of common configuration options supported by all provide
## TLS Configuration Reference
This section documents all of the configuration settings that apply to Agent TLS. Agent
TLS is used by the HTTP API, server RPC, and xDS interfaces. Some of these settings may also be
applied automatically by [auto_config](#auto_config) or [auto_encrypt](#auto_encrypt).
TLS is used by the HTTP API, internal RPC, and gRPC/xDS interfaces. Some of these settings
may also be applied automatically by [auto_config](#auto_config) or [auto_encrypt](#auto_encrypt).
~> **Security Note:** The Certificate Authority (CA) specified by `ca_file` or `ca_path`
should be a private CA, not a public one. We recommend using a dedicated CA
which should not be used with any other systems. Any certificate signed by the
CA will be allowed to communicate with the cluster and a specially crafted certificate
signed by the CA can be used to gain full access to Consul.
~> **Security Note:** The Certificate Authority (CA) configured on the internal RPC interface
(either explicitly by `tls.internal_rpc` or implicitly by `tls.defaults`) should be a private
CA, not a public one. We recommend using a dedicated CA which should not be used with any other
systems. Any certificate signed by the CA will be allowed to communicate with the cluster and a
specially crafted certificate signed by the CA can be used to gain full access to Consul.
- `ca_file` This provides a file path to a PEM-encoded certificate
authority. The certificate authority is used to check the authenticity of client
and server connections with the appropriate [`verify_incoming`](#verify_incoming)
or [`verify_outgoing`](#verify_outgoing) flags.
- `tls` Added in Consul 1.12, for previous versions see
[Deprecated Options](#tls_deprecated_options).
- `ca_path` This provides a path to a directory of PEM-encoded
certificate authority files. These certificate authorities are used to check the
authenticity of client and server connections with the appropriate [`verify_incoming`](#verify_incoming) or [`verify_outgoing`](#verify_outgoing) flags.
- `defaults` ((#tls_defaults)) Provides default settings that will be applied
to every interface unless explicitly overridden by `tls.grpc`, `tls.https`,
or `tls.internal_rpc`.
- `cert_file` This provides a file path to a PEM-encoded
certificate. The certificate is provided to clients or servers to verify the agent's
authenticity. It must be provided along with [`key_file`](#key_file).
- `ca_file` ((#tls_defaults_ca_file)) This provides a file path to a
PEM-encoded certificate authority. The certificate authority is used to
check the authenticity of client and server connections with the
appropriate [`verify_incoming`](#tls_defaults_verify_incoming) or
[`verify_outgoing`](#tls_defaults_verify_outgoing) flags.
- `key_file` This provides a the file path to a PEM-encoded
private key. The key is used with the certificate to verify the agent's authenticity.
This must be provided along with [`cert_file`](#cert_file).
- `ca_path` ((#tls_defaults_ca_path)) This provides a path to a directory
of PEM-encoded certificate authority files. These certificate authorities
are used to check the authenticity of client and server connections with
the appropriate [`verify_incoming`](#tls_defaults_verify_incoming) or
[`verify_outgoing`](#tls_defaults_verify_outgoing) flags.
- `cert_file` ((#tls_defaults_cert_file)) This provides a file path to a
PEM-encoded certificate. The certificate is provided to clients or servers
to verify the agent's authenticity. It must be provided along with
[`key_file`](#tls_defaults_key_file).
- `key_file` ((#tls_defaults_key_file)) This provides a the file path to a
PEM-encoded private key. The key is used with the certificate to verify
the agent's authenticity. This must be provided along with
[`cert_file`](#tls_defaults_cert_file).
- `tls_min_version` ((#tls_defaults_tls_min_version)) This specifies the
minimum supported version of TLS. Accepted values are "tls10", "tls11",
"tls12", or "tls13". This defaults to "tls12". **WARNING: TLS 1.1 and
lower are generally considered less secure; avoid using these if
possible.**
- `tls_cipher_suites` ((#tls_defaults_tls_cipher_suites)) This specifies
the list of supported ciphersuites as a comma-separated-list. Applicable
to TLS 1.2 and below only. The list of all supported ciphersuites is
available through [this search](https://github.com/hashicorp/consul/search?q=cipherMap+%3A%3D+map&unscoped_q=cipherMap+%3A%3D+map).
~> **Note:** The ordering of cipher suites will not be guaranteed from
Consul 1.11 onwards. See this [post](https://go.dev/blog/tls-cipher-suites)
for details.
- `verify_incoming` - ((#tls_defaults_verify_incoming)) If set to true,
Consul requires that all incoming connections make use of TLS and that
the client provides a certificate signed by a Certificate Authority from
the [`ca_file`](#tls_defaults_ca_file) or [`ca_path`](#tls_defaults_ca_path).
By default, this is false, and Consul will not enforce the use of TLS or
verify a client's authenticity.
- `verify_outgoing` - ((#tls_defaults_verify_outgoing)) If set to true,
Consul requires that all outgoing connections from this agent make use
of TLS and that the server provides a certificate that is signed by a
Certificate Authority from the [`ca_file`](#tls_defaults_ca_file) or
[`ca_path`](#tls_defaults_ca_path). By default, this is false, and Consul
will not make use of TLS for outgoing connections. This applies to clients
and servers as both will make outgoing connections. This setting *does not*
apply to the gRPC interface as Consul makes no outgoing connections on this
interface.
- `grpc` ((#tls_grpc)) Provides settings for the gRPC/xDS interface. To enable
the gRPC interface you must define a port via [`ports.grpc`](#grpc_port).
To enable TLS on the gRPC interface you also must define an HTTPS port via
[`ports.https`](#https_port).
- `ca_file` ((#tls_grpc_ca_file)) Overrides [`tls.defaults.ca_file`](#tls_defaults_ca_file).
- `ca_path` ((#tls_grpc_ca_path)) Overrides [`tls.defaults.ca_path`](#tls_defaults_ca_path).
- `cert_file` ((#tls_grpc_cert_file)) Overrides [`tls.defaults.cert_file`](#tls_defaults_cert_file).
- `key_file` ((#tls_grpc_key_file)) Overrides [`tls.defaults.key_file`](#tls_defaults_key_file).
- `tls_min_version` ((#tls_grpc_tls_min_version)) Overrides [`tls.defaults.tls_min_version`](#tls_defaults_tls_min_version).
- `tls_cipher_suites` ((#tls_grpc_tls_cipher_suites)) Overrides [`tls.defaults.tls_cipher_suites`](#tls_defaults_tls_cipher_suites).
- `verify_incoming` - ((#tls_grpc_verify_incoming)) Overrides [`tls.defaults.verify_incoming`](#tls_defaults_verify_incoming).
- `https` ((#tls_https)) Provides settings for the HTTPS interface. To enable
the HTTPS interface you must define a port via [`ports.https`](#https_port).
- `ca_file` ((#tls_https_ca_file)) Overrides [`tls.defaults.ca_file`](#tls_defaults_ca_file).
- `ca_path` ((#tls_https_ca_path)) Overrides [`tls.defaults.ca_path`](#tls_defaults_ca_path).
- `cert_file` ((#tls_https_cert_file)) Overrides [`tls.defaults.cert_file`](#tls_defaults_cert_file).
- `key_file` ((#tls_https_key_file)) Overrides [`tls.defaults.key_file`](#tls_defaults_key_file).
- `tls_min_version` ((#tls_https_tls_min_version)) Overrides [`tls.defaults.tls_min_version`](#tls_defaults_tls_min_version).
- `tls_cipher_suites` ((#tls_https_tls_cipher_suites)) Overrides [`tls.defaults.tls_cipher_suites`](#tls_defaults_tls_cipher_suites).
- `verify_incoming` - ((#tls_https_verify_incoming)) Overrides [`tls.defaults.verify_incoming`](#tls_defaults_verify_incoming).
- `verify_outgoing` - ((#tls_https_verify_outgoing)) Overrides [`tls.defaults.verify_outgoing`](#tls_defaults_verify_outgoing).
- `internal_rpc` ((#tls_internal_rpc)) Provides settings for the internal
"server" RPC interface configured by [`ports.server`](#server_rpc_port).
- `ca_file` ((#tls_internal_rpc_ca_file)) Overrides [`tls.defaults.ca_file`](#tls_defaults_ca_file).
- `ca_path` ((#tls_internal_rpc_ca_path)) Overrides [`tls.defaults.ca_path`](#tls_defaults_ca_path).
- `cert_file` ((#tls_internal_rpc_cert_file)) Overrides [`tls.defaults.cert_file`](#tls_defaults_cert_file).
- `key_file` ((#tls_internal_rpc_key_file)) Overrides [`tls.defaults.key_file`](#tls_defaults_key_file).
- `tls_min_version` ((#tls_internal_rpc_tls_min_version)) Overrides [`tls.defaults.tls_min_version`](#tls_defaults_tls_min_version).
- `tls_cipher_suites` ((#tls_internal_rpc_tls_cipher_suites)) Overrides [`tls.defaults.tls_cipher_suites`](#tls_defaults_tls_cipher_suites).
- `verify_incoming` - ((#tls_internal_rpc_verify_incoming)) Overrides [`tls.defaults.verify_incoming`](#tls_defaults_verify_incoming).
~> **Security Note:** `verify_incoming` *must* be set to true to prevent
anyone with access to the internal RPC port from gaining full access to
the Consul cluster.
- `verify_outgoing` ((#tls_internal_rpc_verify_outgoing)) Overrides [`tls.defaults.verify_outgoing`](#tls_defaults_verify_outgoing).
~> **Security Note:** Servers that specify `verify_outgoing = true` will
always talk to other servers over TLS, but they still _accept_ non-TLS
connections to allow for a transition of all clients to TLS. Currently the
only way to enforce that no client can communicate with a server unencrypted
is to also enable `verify_incoming` which requires client certificates too.
- `verify_server_hostname` ((#tls_internal_rpc_verify_server_hostname)) When
set to true, Consul verifies the TLS certificate presented by the servers
match the hostname `server.<datacenter>.<domain>`. By default this is false,
and Consul does not verify the hostname of the certificate, only that it
is signed by a trusted CA. This setting *must* be enabled to prevent a
compromised client from gaining full read and write access to all cluster
data *including all ACL tokens and Connect CA root keys*.
- `server_name` When provided, this overrides the [`node_name`](#_node)
for the TLS certificate. It can be used to ensure that the certificate name matches
the hostname we declare.
- `tls_min_version` Added in Consul 0.7.4, this specifies
the minimum supported version of TLS. Accepted values are "tls10", "tls11", "tls12",
or "tls13". This defaults to "tls12". WARNING: TLS 1.1 and lower are generally
considered less secure; avoid using these if possible.
### Deprecated Options ((#tls_deprecated_options))
- `tls_cipher_suites` Added in Consul 0.8.2, this specifies the list of
supported ciphersuites as a comma-separated-list. Applicable to TLS 1.2 and below only.
The list of all supported ciphersuites is available through
[this search](https://github.com/hashicorp/consul/search?q=cipherMap+%3A%3D+map&unscoped_q=cipherMap+%3A%3D+map).
The following options were deprecated in Consul 1.12, please use the
[`tls`](#tls) stanza instead.
~> **Note:** The ordering of cipher suites will not be guaranteed from Consul 1.11 onwards. See this
[post](https://go.dev/blog/tls-cipher-suites) for details.
- `ca_file` See: [`tls.defaults.ca_file`](#tls_defaults_ca_file).
- `tls_prefer_server_cipher_suites` Added in Consul 0.8.2, this
will cause Consul to prefer the server's ciphersuite over the client ciphersuites.
- `ca_path` See: [`tls.defaults.ca_path`](#tls_defaults_ca_path).
~> **Note:** This config will be deprecated in Consul 1.11. See this
[post](https://go.dev/blog/tls-cipher-suites) for details.
- `cert_file` See: [`tls.defaults.cert_file`](#tls_defaults_cert_file).
- `verify_incoming` - If set to true, Consul
requires that all incoming connections make use of TLS and that the client
provides a certificate signed by a Certificate Authority from the
[`ca_file`](#ca_file) or [`ca_path`](#ca_path). This applies to both server
RPC and to the HTTPS API. By default, this is false, and Consul will not
enforce the use of TLS or verify a client's authenticity. Turning on
`verify_incoming` on consul clients protects the HTTPS endpoint, by ensuring
that the certificate that is presented by a 3rd party tool to the HTTPS
endpoint was created by the CA that the consul client was setup with. If the
UI is served, the same checks are performed.
- `key_file` See: [`tls.defaults.key_file`](#tls_defaults_key_file).
- `verify_incoming_rpc` - When set to true, Consul
requires that all incoming RPC connections use TLS and that the client
provides a certificate signed by a Certificate Authority from the [`ca_file`](#ca_file)
or [`ca_path`](#ca_path). By default, this is false, and Consul will not enforce
the use of TLS or verify a client's authenticity.
- `tls_min_version` Added in Consul 0.7.4.
See: [`tls.defaults.tls_min_version`](#tls_defaults_tls_min_version).
~> **Security Note:** `verify_incoming_rpc` _must_ be set to true to prevent anyone
with access to the RPC port from gaining full access to the Consul cluster.
- `tls_cipher_suites` Added in Consul 0.8.2.
See: [`tls.defaults.tls_cipher_suites`](#tls_defaults_tls_cipher_suites).
- `verify_incoming_https` - If set to true,
Consul requires that all incoming HTTPS connections make use of TLS and that the
client provides a certificate signed by a Certificate Authority from the [`ca_file`](#ca_file)
or [`ca_path`](#ca_path). By default, this is false, and Consul will not enforce
the use of TLS or verify a client's authenticity. To enable the HTTPS API, you
must define an HTTPS port via the [`ports`](#ports) configuration. By default,
HTTPS is disabled.
- `tls_prefer_server_cipher_suites` Added in Consul 0.8.2. This setting will
be ignored (see [this post](https://go.dev/blog/tls-cipher-suites) for details).
- `verify_outgoing` - If set to true, Consul requires
that all outgoing connections from this agent make use of TLS and that the server
provides a certificate that is signed by a Certificate Authority from the [`ca_file`](#ca_file)
or [`ca_path`](#ca_path). By default, this is false, and Consul will not make use
of TLS for outgoing connections. This applies to clients and servers as both will
make outgoing connections.
- `verify_incoming` See: [`tls.defaults.verify_incoming`](#tls_defaults_verify_incoming).
~> **Security Note:** Note that servers that specify `verify_outgoing = true` will always talk to other servers over TLS, but they still _accept_
non-TLS connections to allow for a transition of all clients to TLS.
Currently the only way to enforce that no client can communicate with a
server unencrypted is to also enable `verify_incoming` which requires client
certificates too.
- `verify_incoming_rpc` See: [`tls.internal_rpc.verify_incoming`](#tls_internal_rpc_verify_incoming).
- `verify_server_hostname` - When set to true, Consul verifies the TLS certificate
presented by the servers match the hostname `server.<datacenter>.<domain>`.
By default this is false, and Consul does not verify the hostname
of the certificate, only that it is signed by a trusted CA. This setting _must_ be enabled
to prevent a compromised client from gaining full read and write access to all
cluster data _including all ACL tokens and Connect CA root keys_. This is new in 0.5.1.
- `verify_incoming_https` See: [`tls.https.verify_incoming`](#tls_https_verify_incoming).
~> **Security Note:** From versions 0.5.1 to 1.4.0, due to a bug, setting
this flag alone _does not_ imply `verify_outgoing` and leaves client to server
and server to server RPCs unencrypted despite the documentation stating otherwise. See
[CVE-2018-19653](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19653)
for more details. For those versions you **must also set `verify_outgoing = true`** to ensure encrypted RPC connections.
- `verify_outgoing` See: [`tls.defaults.verify_outgoing`](#tls_defaults_verify_outgoing).
- `verify_server_hostname` See: [`tls.internal_rpc.verify_server_hostname`](#tls_internal_rpc_verify_server_hostname).
### Example Configuration File, with TLS
~> **Security Note:** all three verify options should be set as `true` to enable secure mTLS communication, enabling both
encryption and authentication. Failing to set [`verify_incoming`](#verify_incoming) or [`verify_outgoing`](#verify_outgoing)
will result in TLS not being enabled at all, even when specifying a [`ca_file`](#ca_file), [`cert_file`](#cert_file), and [`key_file`](#key_file).
~> **Security Note:** all three verify options should be set as `true` to enable
secure mTLS communication, enabling both encryption and authentication. Failing
to set [`verify_incoming`](#tls_defaults_verify_incoming) or
[`verify_outgoing`](#tls_defaults_verify_outgoing) either in the
interface-specific stanza (e.g. `tls.internal_rpc`, `tls.https`) or in
`tls.defaults` will result in TLS not being enabled at all, even when specifying
a [`ca_file`](#tls_defaults_ca_file), [`cert_file`](#tls_defaults_cert_file),
and [`key_file`](#tls_defaults_key_file).
See, especially, the use of the `ports` setting highlighted below.
@ -2575,12 +2658,19 @@ ports {
https = 8501
}
key_file = "/etc/pki/tls/private/my.key"
cert_file = "/etc/pki/tls/certs/my.crt"
ca_file = "/etc/pki/tls/certs/ca-bundle.crt"
verify_incoming = true
verify_outgoing = true
verify_server_hostname = true
tls {
defaults {
key_file = "/etc/pki/tls/private/my.key"
cert_file = "/etc/pki/tls/certs/my.crt"
ca_file = "/etc/pki/tls/certs/ca-bundle.crt"
verify_incoming = true
verify_outgoing = true
}
internal_rpc {
verify_server_hostname = true
}
}
```
</CodeBlockConfig>
@ -2600,12 +2690,18 @@ verify_server_hostname = true
"ports": {
"https": 8501
},
"key_file": "/etc/pki/tls/private/my.key",
"cert_file": "/etc/pki/tls/certs/my.crt",
"ca_file": "/etc/pki/tls/certs/ca-bundle.crt",
"verify_incoming": true,
"verify_outgoing": true,
"verify_server_hostname": true
"tls": {
"defaults": {
"key_file": "/etc/pki/tls/private/my.key",
"cert_file": "/etc/pki/tls/certs/my.crt",
"ca_file": "/etc/pki/tls/certs/ca-bundle.crt",
"verify_incoming": true,
"verify_outgoing": true
},
"internal_rpc": {
"verify_server_hostname": true
}
}
}
```
@ -2613,8 +2709,8 @@ verify_server_hostname = true
</CodeTabs>
Consul will not enable TLS for the HTTP API unless the `https` port has been
assigned a port number `> 0`. We recommend using `8501` for `https` as this
Consul will not enable TLS for the HTTP or gRPC API unless the `https` port has
been assigned a port number `> 0`. We recommend using `8501` for `https` as this
default will automatically work with some tooling.
## Ports Used

View File

@ -46,7 +46,7 @@ configuration file include:
- [certificate authority settings](/docs/agent/options#connect)
- [token replication](/docs/agent/options#acl_tokens_replication)
- [dev mode](/docs/agent/options#_dev)
- [server host name verification](/docs/agent/options#verify_server_hostname)
- [server host name verification](/docs/agent/options#tls_internal_rpc_verify_server_hostname)
If you would like to use Envoy as your Connect proxy you will need to [enable
gRPC](/docs/agent/options#grpc_port).

View File

@ -157,8 +157,12 @@ auto_encrypt = {
tls = true
ip_san = ["$ECS_IPV4"]
}
ca_file = "/tmp/consul-ca-cert.pem"
verify_outgoing = true
tls {
defaults {
ca_file = "/tmp/consul-ca-cert.pem"
verify_outgoing = true
}
}
# Configure ACLs
acl {
@ -177,12 +181,12 @@ EOF
The following table describes the additional fields that must be included in the Consul client configuration file.
| Field name | Type | Description |
| --------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------ |
| [`encrypt`](/docs/agent/options#_encrypt) | string | Specifies the gossip encryption key |
| [`ca_file`](/docs/agent/options#ca_file) | string | Specifies the Consul server CA cert for TLS verification. |
| [`acl.enabled`](/docs/agent/options#acl_enabled) | boolen | Enable ACLs for this agent. |
| [`acl.tokens.agent`](/docs/agent/options#acl_tokens_agent) | string | Specifies the Consul client token which authorizes this agent with Consul servers. |
| Field name | Type | Description |
| --------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------ |
| [`encrypt`](/docs/agent/options#_encrypt) | string | Specifies the gossip encryption key |
| [`tls.defaults.ca_file`](/docs/agent/options#tls_defaults_ca_file) | string | Specifies the Consul server CA cert for TLS verification. |
| [`acl.enabled`](/docs/agent/options#acl_enabled) | boolean | Enable ACLs for this agent. |
| [`acl.tokens.agent`](/docs/agent/options#acl_tokens_agent) | string | Specifies the Consul client token which authorizes this agent with Consul servers. |
## Configure `consul-ecs-mesh-init` and `consul-ecs-health-sync`

View File

@ -294,11 +294,11 @@ Use these links to navigate to a particular top-level stanza.
in the server certificate. This is useful when you need to access the
Consul server(s) externally, for example, if you're using the UI.
- `verify` ((#v-global-tls-verify)) (`boolean: true`) - If true, `verify_outgoing`, `verify_server_hostname`,
and `verify_incoming_rpc` will be set to `true` for Consul servers and clients.
Set this to false to incrementally roll out TLS on an existing Consul cluster.
Please see https://consul.io/docs/k8s/operations/tls-on-existing-cluster
for more details.
- `verify` ((#v-global-tls-verify)) (`boolean: true`) - If true, `tls.defaults.verify_outgoing`,
`tls.internal_rpc.verify_server_hostname`, and `tls.internal_rpc.verify_incoming` will be set
to `true` for Consul servers and clients. Set this to false to incrementally roll out TLS
on an existing Consul cluster.
Please see https://consul.io/docs/k8s/operations/tls-on-existing-cluster for more details.
- `httpsOnly` ((#v-global-tls-httpsonly)) (`boolean: true`) - If true, the Helm chart will configure Consul to disable the HTTP port on
both clients and servers and to only accept HTTPS connections.

View File

@ -56,7 +56,7 @@ You may also consider adopting Consul Enterprise for
-> **Note:** Consul on Kubernetes currently does not support external servers that require mutual authentication
for the HTTPS clients of the Consul servers, that is when servers have either
`verify_incoming` or `verify_incoming_https` set to `true`.
`tls.defaults.verify_incoming` or `tls.https.verify_incoming` set to `true`.
As noted in the [Security Model](/docs/security#secure-configuration),
that setting isn't strictly necessary to support Consul's threat model as it is recommended that
all requests contain a valid ACL token.

View File

@ -75,9 +75,13 @@ The following sections detail how to export this data.
<CodeBlockConfig filename="server.hcl">
```hcl
cert_file = "vm-dc-server-consul-0.pem"
key_file = "vm-dc-server-consul-0-key.pem"
ca_file = "consul-agent-ca.pem"
tls {
defaults {
cert_file = "vm-dc-server-consul-0.pem"
key_file = "vm-dc-server-consul-0-key.pem"
ca_file = "consul-agent-ca.pem"
}
}
```
</CodeBlockConfig>
@ -160,9 +164,19 @@ A final example server config file might look like:
```hcl
# From above
cert_file = "vm-dc-server-consul-0.pem"
key_file = "vm-dc-server-consul-0-key.pem"
ca_file = "consul-agent-ca.pem"
tls {
defaults {
cert_file = "vm-dc-server-consul-0.pem"
key_file = "vm-dc-server-consul-0-key.pem"
ca_file = "consul-agent-ca.pem"
}
internal_rpc {
verify_incoming = true
verify_outgoing = true
verify_server_hostname = true
}
}
primary_gateways = ["1.2.3.4:443"]
acl {
enabled = true
@ -185,9 +199,6 @@ connect {
enabled = true
enable_mesh_gateway_wan_federation = true
}
verify_incoming_rpc = true
verify_outgoing = true
verify_server_hostname = true
ports {
https = 8501
http = -1

View File

@ -75,17 +75,17 @@ CA then signs keys for each of the agents, as in
~> Certificates need to be created with x509v3 extendedKeyUsage attributes for both clientAuth and serverAuth since Consul uses a single cert/key pair for both server and client communications.
TLS can be used to verify the authenticity of the servers or verify the authenticity of clients.
These modes are controlled by the [`verify_outgoing`](/docs/agent/options#verify_outgoing),
[`verify_server_hostname`](/docs/agent/options#verify_server_hostname),
and [`verify_incoming`](/docs/agent/options#verify_incoming) options, respectively.
These modes are controlled by the [`verify_outgoing`](/docs/agent/options#tls_internal_rpc_verify_outgoing),
[`verify_server_hostname`](/docs/agent/options#tls_internal_rpc_verify_server_hostname),
and [`verify_incoming`](/docs/agent/options#tls_internal_rpc_verify_incoming) options, respectively.
If [`verify_outgoing`](/docs/agent/options#verify_outgoing) is set, agents verify the
If [`verify_outgoing`](/docs/agent/options#tls_internal_rpc_verify_outgoing) is set, agents verify the
authenticity of Consul for outgoing connections. Server nodes must present a certificate signed
by a common certificate authority present on all agents, set via the agent's
[`ca_file`](/docs/agent/options#ca_file) and [`ca_path`](/docs/agent/options#ca_path)
options. All server nodes must have an appropriate key pair set using [`cert_file`](/docs/agent/options#cert_file) and [`key_file`](/docs/agent/options#key_file).
[`ca_file`](/docs/agent/options#tls_internal_rpc_ca_file) and [`ca_path`](/docs/agent/options#tls_internal_rpc_ca_path)
options. All server nodes must have an appropriate key pair set using [`cert_file`](/docs/agent/options#tls_internal_rpc_cert_file) and [`key_file`](/docs/agent/options#tls_internal_rpc_key_file).
If [`verify_server_hostname`](/docs/agent/options#verify_server_hostname) is set, then
If [`verify_server_hostname`](/docs/agent/options#tls_internal_rpc_verify_server_hostname) is set, then
outgoing connections perform hostname verification. All servers must have a certificate
valid for `server.<datacenter>.<domain>` or the client will reject the handshake. This is
a new configuration as of 0.5.1, and it is used to prevent a compromised client from being
@ -93,12 +93,12 @@ able to restart in server mode and perform a MITM (Man-In-The-Middle) attack. Ne
to true, and generate the proper certificates, but this is defaulted to false to avoid breaking
existing deployments.
If [`verify_incoming`](/docs/agent/options#verify_incoming) is set, the servers verify the
If [`verify_incoming`](/docs/agent/options#tls_internal_rpc_verify_incoming) is set, the servers verify the
authenticity of all incoming connections. All clients must have a valid key pair set using
[`cert_file`](/docs/agent/options#cert_file) and
[`key_file`](/docs/agent/options#key_file). Servers will
[`cert_file`](/docs/agent/options#tls_internal_rpc_cert_file) and
[`key_file`](/docs/agent/options#tls_internal_rpc_key_file). Servers will
also disallow any non-TLS connections. To force clients to use TLS,
[`verify_outgoing`](/docs/agent/options#verify_outgoing) must also be set.
[`verify_outgoing`](/docs/agent/options#tls_internal_rpc_verify_outgoing) must also be set.
TLS is used to secure the RPC calls between agents, but gossip between nodes is done over UDP
and is secured using a symmetric key. See above for enabling gossip encryption.

View File

@ -72,29 +72,33 @@ environment and adapt these configurations accordingly.
- **mTLS** - Mutual authentication of both the TLS server and client x509 certificates prevents internal abuse through
unauthorized access to Consul agents within the cluster.
- [`verify_incoming`](/docs/agent/options#verify_incoming) - By default this is false, and should almost always be set
to true to require TLS verification for incoming client connections. This applies to both server RPC and to the
HTTPS API.
- [`tls.defaults.verify_incoming`](/docs/agent/options#tls_defaults_verify_incoming) - By default this is false, and
should almost always be set to true to require TLS verification for incoming client connections. This applies to the
internal RPC, HTTPS and gRPC APIs.
- [`verify_incoming_https`](/docs/agent/options#verify_incoming_https) - By default this is false, and should be set
to true to require clients to provide a valid TLS certificate when the Consul HTTPS API is enabled. TLS for the API
may be not be necessary if it is exclusively served over a loopback interface such as `localhost`.
- [`tls.https.verify_incoming`](/docs/agent/options#tls_https_verify_incoming) - By default this is false, and should
be set to true to require clients to provide a valid TLS certificate when the Consul HTTPS API is enabled. TLS for
the API may be not be necessary if it is exclusively served over a loopback interface such as `localhost`.
- [`verify_incoming_rpc`](/docs/agent/options#verify_incoming_rpc) - By default this is false, and should almost
always be set to true to require clients to provide a valid TLS certificate for Consul agent RPCs.
- [`tls.internal_rpc.verify_incoming`](/docs/agent/options#tls_internal_rpc_verify_incoming) - By default this is false,
and should almost always be set to true to require clients to provide a valid TLS certificate for Consul agent RPCs.
- [`verify_outgoing`](/docs/agent/options#verify_outgoing) - By default this is false, and should be set to true to
require TLS for outgoing connections from server or client agents. Servers that specify `verify_outgoing = true`
will always talk to other servers over TLS, but they still accept non-TLS connections to allow for a transition of
all clients to TLS. Currently the only way to enforce that no client can communicate with a server unencrypted is
to also enable `verify_incoming` which requires client certificates too.
- [`tls.grpc.verify_incoming`](/docs/agent/options#tls_grpc_verify_incoming) - By default this is false, and should
be set to true to require clients to provide a valid TLS certificate when the Consul gRPC API is enabled. TLS for
the API may be not be necessary if it is exclusively served over a loopback interface such as `localhost`.
- [`tls.internal_rpc.verify_outgoing`](/docs/agent/options#tls_internal_rpc_verify_outgoing) - By default this is false,
and should be set to true to require TLS for outgoing connections from server or client agents. Servers that specify
`verify_outgoing = true` will always talk to other servers over TLS, but they still accept non-TLS connections to allow
for a transition of all clients to TLS. Currently the only way to enforce that no client can communicate with a server
unencrypted is to also enable `verify_incoming` which requires client certificates too.
- [`enable_agent_tls_for_checks`](/docs/agent/options#enable_agent_tls_for_checks) - By default this is false, and
should almost always be set to true to require mTLS to set up the client for HTTP or gRPC health checks. This was
added in Consul 1.0.1.
- [`verify_server_hostname`](/docs/agent/options#verify_server_hostname) - By default this is false, and should be
set to true to require that the TLS certificate presented by the servers matches
- [`tls.internal_rpc.verify_server_hostname`](/docs/agent/options#tls_internal_rpc_verify_server_hostname) - By default
this is false, and should be set to true to require that the TLS certificate presented by the servers matches
`server.<datacenter>.<domain>` hostname for outgoing TLS connections. The default configuration does not verify the
hostname of the certificate, only that it is signed by a trusted CA. This setting is critical to prevent a
compromised client agent from being restarted as a server and having all cluster state including all ACL tokens and
@ -105,7 +109,7 @@ environment and adapt these configurations accordingly.
in 1.4.1.
- [`auto_encrypt`](/docs/agent/options#auto_encrypt) - Enables automated TLS certificate distribution for client
agent RPC communication using the Connect CA. Using this configuration a [`ca_file`](/docs/agent/options#ca_file)
agent RPC communication using the Connect CA. Using this configuration a [`ca_file`](/docs/agent/options#tls_defaults_ca_file)
and ACL token would still need to be distributed to client agents.
- [`allow_tls`](/docs/agent/options#allow_tls) - By default this is false, and should be set to true on server
@ -117,35 +121,48 @@ environment and adapt these configurations accordingly.
**Example Server Agent TLS Configuration**
```hcl
verify_incoming = true
verify_outgoing = true
verify_server_hostname = true
tls {
defaults {
verify_incoming = true
verify_outgoing = true
ca_file = "consul-agent-ca.pem"
cert_file = "dc1-server-consul-0.pem"
key_file = "dc1-server-consul-0-key.pem"
}
ca_file = "consul-agent-ca.pem"
cert_file = "dc1-server-consul-0.pem"
key_file = "dc1-server-consul-0-key.pem"
internal_rpc {
verify_server_hostname = true
}
}
auto_encrypt {
allow_tls = true
allow_tls = true
}
```
**Example Client Agent TLS Configuration**
```hcl
verify_incoming = false
verify_outgoing = true
verify_server_hostname = true
tls {
defaults {
verify_incoming = false
verify_outgoing = true
ca_file = "consul-agent-ca.pem"
}
internal_rpc {
verify_server_hostname = true
}
}
ca_file = "consul-agent-ca.pem"
auto_encrypt {
tls = true
tls = true
}
```
-> The client agent TLS configuration from above sets [`verify_incoming`](/docs/agent/options#verify_incoming) to
false which assumes all incoming traffic is restricted to `localhost`. The primary benefit for this configuration
-> The client agent TLS configuration from above sets [`verify_incoming`](/docs/agent/options#tls_defaults_verify_incoming)
to false which assumes all incoming traffic is restricted to `localhost`. The primary benefit for this configuration
would be to avoid provisioning client TLS certificates (in addition to ACL tokens) for all tools or applications
using the local Consul agent. In this case ACLs should be enabled to provide authorization and only ACL tokens would
need to be distributed.
@ -223,15 +240,12 @@ environment and adapt these configurations accordingly.
- **Linux Security Modules** - Use of security modules that can be directly integrated into operating systems such as
AppArmor, SElinux, and Seccomp on Consul agent hosts.
- **Customize TLS Settings** - TLS settings such as the [available cipher suites](/docs/agent/options#tls_cipher_suites),
- **Customize TLS Settings** - TLS settings such as the [available cipher suites](/docs/agent/options#tls_defaults_tls_cipher_suites),
should be tuned to fit the needs of your environment.
- [`tls_min_version`](/docs/agent/options#tls_min_version) - Used to specify the minimum TLS version to use.
- [`tls_min_version`](/docs/agent/options#tls_defaults_tls_min_version) - Used to specify the minimum TLS version to use.
- [`tls_cipher_suites`](/docs/agent/options#tls_cipher_suites) - Used to specify which TLS cipher suites are allowed.
- [`tls_prefer_server_cipher_suites`](/docs/agent/options#tls_prefer_server_cipher_suites) - Used to specify which TLS
cipher suites are preferred on the server side.
- [`tls_cipher_suites`](/docs/agent/options#tls_defaults_tls_cipher_suites) - Used to specify which TLS cipher suites are allowed.
- **Customize HTTP Response Headers** - Additional security headers, such as
[`X-XSS-Protection`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection), can be