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 c.NodeID = a.config.NodeID
a.config = c 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) 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.Build = fmt.Sprintf("%s%s:%s", runtimeCfg.Version, runtimeCfg.VersionPrerelease, revision)
cfg.TLSConfig = runtimeCfg.ToTLSUtilConfig() cfg.TLSConfig = runtimeCfg.TLS
cfg.DefaultQueryTime = runtimeCfg.DefaultQueryTime cfg.DefaultQueryTime = runtimeCfg.DefaultQueryTime
cfg.MaxQueryTime = runtimeCfg.MaxQueryTime cfg.MaxQueryTime = runtimeCfg.MaxQueryTime
@ -3748,7 +3748,7 @@ func (a *Agent) reloadConfigInternal(newCfg *config.RuntimeConfig) error {
// the checks and service registrations. // the checks and service registrations.
a.tokens.Load(newCfg.ACLTokens, a.logger) 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) 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 { if !autoEncrypt {
// auto-encrypt doesn't modify the config but rather sets the value // auto-encrypt doesn't modify the config but rather sets the value
// in the TLS configurator // in the TLS configurator
require.True(t, cfg.VerifyServerHostname) require.True(t, cfg.TLS.InternalRPC.VerifyServerHostname)
} }
ctx, cancel := context.WithCancel(context.Background()) 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 { if t := c.TLS; t != nil {
result.VerifyOutgoing = &t.VerifyOutgoing result.TLS.Defaults = config.TLSProtocolConfig{
result.VerifyServerHostname = &t.VerifyServerHostname VerifyOutgoing: &t.VerifyOutgoing,
result.TLSMinVersion = stringPtrOrNil(t.MinVersion) TLSMinVersion: stringPtrOrNil(t.MinVersion),
result.TLSCipherSuites = stringPtrOrNil(t.CipherSuites) TLSCipherSuites: stringPtrOrNil(t.CipherSuites),
result.TLSPreferServerCipherSuites = &t.PreferServerCipherSuites }
result.TLS.InternalRPC.VerifyServerHostname = &t.VerifyServerHostname
} }
return result return result

View File

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

View File

@ -747,18 +747,6 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
enableRemoteScriptChecks := boolVal(c.EnableScriptChecks) enableRemoteScriptChecks := boolVal(c.EnableScriptChecks)
enableLocalScriptChecks := boolValWithDefault(c.EnableLocalScriptChecks, enableRemoteScriptChecks) 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 var configEntries []structs.ConfigEntry
if len(c.ConfigEntries.Bootstrap) > 0 { if len(c.ConfigEntries.Bootstrap) > 0 {
@ -963,9 +951,6 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
c.Cache.EntryFetchMaxBurst, cache.DefaultEntryFetchMaxBurst, 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), CheckUpdateInterval: b.durationVal("check_update_interval", c.CheckUpdateInterval),
CheckOutputMaxSize: intValWithDefault(c.CheckOutputMaxSize, 4096), CheckOutputMaxSize: intValWithDefault(c.CheckOutputMaxSize, 4096),
Checks: checks, Checks: checks,
@ -1012,7 +997,6 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
GRPCAddrs: grpcAddrs, GRPCAddrs: grpcAddrs,
HTTPMaxConnsPerClient: intVal(c.Limits.HTTPMaxConnsPerClient), HTTPMaxConnsPerClient: intVal(c.Limits.HTTPMaxConnsPerClient),
HTTPSHandshakeTimeout: b.durationVal("limits.https_handshake_timeout", c.Limits.HTTPSHandshakeTimeout), HTTPSHandshakeTimeout: b.durationVal("limits.https_handshake_timeout", c.Limits.HTTPSHandshakeTimeout),
KeyFile: stringVal(c.KeyFile),
KVMaxValueSize: uint64Val(c.Limits.KVMaxValueSize), KVMaxValueSize: uint64Val(c.Limits.KVMaxValueSize),
LeaveDrainTime: b.durationVal("performance.leave_drain_time", c.Performance.LeaveDrainTime), LeaveDrainTime: b.durationVal("performance.leave_drain_time", c.Performance.LeaveDrainTime),
LeaveOnTerm: leaveOnTerm, LeaveOnTerm: leaveOnTerm,
@ -1026,72 +1010,69 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
LogRotateBytes: intVal(c.LogRotateBytes), LogRotateBytes: intVal(c.LogRotateBytes),
LogRotateMaxFiles: intVal(c.LogRotateMaxFiles), LogRotateMaxFiles: intVal(c.LogRotateMaxFiles),
}, },
MaxQueryTime: b.durationVal("max_query_time", c.MaxQueryTime), MaxQueryTime: b.durationVal("max_query_time", c.MaxQueryTime),
NodeID: types.NodeID(stringVal(c.NodeID)), NodeID: types.NodeID(stringVal(c.NodeID)),
NodeMeta: c.NodeMeta, NodeMeta: c.NodeMeta,
NodeName: b.nodeName(c.NodeName), NodeName: b.nodeName(c.NodeName),
ReadReplica: boolVal(c.ReadReplica), ReadReplica: boolVal(c.ReadReplica),
PidFile: stringVal(c.PidFile), PidFile: stringVal(c.PidFile),
PrimaryDatacenter: primaryDatacenter, PrimaryDatacenter: primaryDatacenter,
PrimaryGateways: b.expandAllOptionalAddrs("primary_gateways", c.PrimaryGateways), PrimaryGateways: b.expandAllOptionalAddrs("primary_gateways", c.PrimaryGateways),
PrimaryGatewaysInterval: b.durationVal("primary_gateways_interval", c.PrimaryGatewaysInterval), PrimaryGatewaysInterval: b.durationVal("primary_gateways_interval", c.PrimaryGatewaysInterval),
RPCAdvertiseAddr: rpcAdvertiseAddr, RPCAdvertiseAddr: rpcAdvertiseAddr,
RPCBindAddr: rpcBindAddr, RPCBindAddr: rpcBindAddr,
RPCHandshakeTimeout: b.durationVal("limits.rpc_handshake_timeout", c.Limits.RPCHandshakeTimeout), RPCHandshakeTimeout: b.durationVal("limits.rpc_handshake_timeout", c.Limits.RPCHandshakeTimeout),
RPCHoldTimeout: b.durationVal("performance.rpc_hold_timeout", c.Performance.RPCHoldTimeout), RPCHoldTimeout: b.durationVal("performance.rpc_hold_timeout", c.Performance.RPCHoldTimeout),
RPCMaxBurst: intVal(c.Limits.RPCMaxBurst), RPCMaxBurst: intVal(c.Limits.RPCMaxBurst),
RPCMaxConnsPerClient: intVal(c.Limits.RPCMaxConnsPerClient), RPCMaxConnsPerClient: intVal(c.Limits.RPCMaxConnsPerClient),
RPCProtocol: intVal(c.RPCProtocol), RPCProtocol: intVal(c.RPCProtocol),
RPCRateLimit: rate.Limit(float64Val(c.Limits.RPCRate)), RPCRateLimit: rate.Limit(float64Val(c.Limits.RPCRate)),
RPCConfig: consul.RPCConfig{EnableStreaming: boolValWithDefault(c.RPC.EnableStreaming, serverMode)}, RPCConfig: consul.RPCConfig{EnableStreaming: boolValWithDefault(c.RPC.EnableStreaming, serverMode)},
RaftProtocol: intVal(c.RaftProtocol), RaftProtocol: intVal(c.RaftProtocol),
RaftSnapshotThreshold: intVal(c.RaftSnapshotThreshold), RaftSnapshotThreshold: intVal(c.RaftSnapshotThreshold),
RaftSnapshotInterval: b.durationVal("raft_snapshot_interval", c.RaftSnapshotInterval), RaftSnapshotInterval: b.durationVal("raft_snapshot_interval", c.RaftSnapshotInterval),
RaftTrailingLogs: intVal(c.RaftTrailingLogs), RaftTrailingLogs: intVal(c.RaftTrailingLogs),
ReconnectTimeoutLAN: b.durationVal("reconnect_timeout", c.ReconnectTimeoutLAN), ReconnectTimeoutLAN: b.durationVal("reconnect_timeout", c.ReconnectTimeoutLAN),
ReconnectTimeoutWAN: b.durationVal("reconnect_timeout_wan", c.ReconnectTimeoutWAN), ReconnectTimeoutWAN: b.durationVal("reconnect_timeout_wan", c.ReconnectTimeoutWAN),
RejoinAfterLeave: boolVal(c.RejoinAfterLeave), RejoinAfterLeave: boolVal(c.RejoinAfterLeave),
RetryJoinIntervalLAN: b.durationVal("retry_interval", c.RetryJoinIntervalLAN), RetryJoinIntervalLAN: b.durationVal("retry_interval", c.RetryJoinIntervalLAN),
RetryJoinIntervalWAN: b.durationVal("retry_interval_wan", c.RetryJoinIntervalWAN), RetryJoinIntervalWAN: b.durationVal("retry_interval_wan", c.RetryJoinIntervalWAN),
RetryJoinLAN: b.expandAllOptionalAddrs("retry_join", c.RetryJoinLAN), RetryJoinLAN: b.expandAllOptionalAddrs("retry_join", c.RetryJoinLAN),
RetryJoinMaxAttemptsLAN: intVal(c.RetryJoinMaxAttemptsLAN), RetryJoinMaxAttemptsLAN: intVal(c.RetryJoinMaxAttemptsLAN),
RetryJoinMaxAttemptsWAN: intVal(c.RetryJoinMaxAttemptsWAN), RetryJoinMaxAttemptsWAN: intVal(c.RetryJoinMaxAttemptsWAN),
RetryJoinWAN: b.expandAllOptionalAddrs("retry_join_wan", c.RetryJoinWAN), RetryJoinWAN: b.expandAllOptionalAddrs("retry_join_wan", c.RetryJoinWAN),
SegmentName: stringVal(c.SegmentName), SegmentName: stringVal(c.SegmentName),
Segments: segments, Segments: segments,
SegmentLimit: intVal(c.SegmentLimit), SegmentLimit: intVal(c.SegmentLimit),
SerfAdvertiseAddrLAN: serfAdvertiseAddrLAN, SerfAdvertiseAddrLAN: serfAdvertiseAddrLAN,
SerfAdvertiseAddrWAN: serfAdvertiseAddrWAN, SerfAdvertiseAddrWAN: serfAdvertiseAddrWAN,
SerfAllowedCIDRsLAN: serfAllowedCIDRSLAN, SerfAllowedCIDRsLAN: serfAllowedCIDRSLAN,
SerfAllowedCIDRsWAN: serfAllowedCIDRSWAN, SerfAllowedCIDRsWAN: serfAllowedCIDRSWAN,
SerfBindAddrLAN: serfBindAddrLAN, SerfBindAddrLAN: serfBindAddrLAN,
SerfBindAddrWAN: serfBindAddrWAN, SerfBindAddrWAN: serfBindAddrWAN,
SerfPortLAN: serfPortLAN, SerfPortLAN: serfPortLAN,
SerfPortWAN: serfPortWAN, SerfPortWAN: serfPortWAN,
ServerMode: serverMode, ServerMode: serverMode,
ServerName: stringVal(c.ServerName), ServerName: stringVal(c.ServerName),
ServerPort: serverPort, ServerPort: serverPort,
Services: services, Services: services,
SessionTTLMin: b.durationVal("session_ttl_min", c.SessionTTLMin), SessionTTLMin: b.durationVal("session_ttl_min", c.SessionTTLMin),
SkipLeaveOnInt: skipLeaveOnInt, SkipLeaveOnInt: skipLeaveOnInt,
StartJoinAddrsLAN: b.expandAllOptionalAddrs("start_join", c.StartJoinAddrsLAN), StartJoinAddrsLAN: b.expandAllOptionalAddrs("start_join", c.StartJoinAddrsLAN),
StartJoinAddrsWAN: b.expandAllOptionalAddrs("start_join_wan", c.StartJoinAddrsWAN), StartJoinAddrsWAN: b.expandAllOptionalAddrs("start_join_wan", c.StartJoinAddrsWAN),
TLSCipherSuites: b.tlsCipherSuites("tls_cipher_suites", c.TLSCipherSuites), TaggedAddresses: c.TaggedAddresses,
TLSMinVersion: stringVal(c.TLSMinVersion), TranslateWANAddrs: boolVal(c.TranslateWANAddrs),
TLSPreferServerCipherSuites: boolVal(c.TLSPreferServerCipherSuites), TxnMaxReqLen: uint64Val(c.Limits.TxnMaxReqLen),
TaggedAddresses: c.TaggedAddresses, UIConfig: b.uiConfigVal(c.UIConfig),
TranslateWANAddrs: boolVal(c.TranslateWANAddrs), UnixSocketGroup: stringVal(c.UnixSocket.Group),
TxnMaxReqLen: uint64Val(c.Limits.TxnMaxReqLen), UnixSocketMode: stringVal(c.UnixSocket.Mode),
UIConfig: b.uiConfigVal(c.UIConfig), UnixSocketUser: stringVal(c.UnixSocket.User),
UnixSocketGroup: stringVal(c.UnixSocket.Group), Watches: c.Watches,
UnixSocketMode: stringVal(c.UnixSocket.Mode), }
UnixSocketUser: stringVal(c.UnixSocket.User),
VerifyIncoming: boolVal(c.VerifyIncoming), rt.TLS, err = b.buildTLSConfig(rt, c.TLS)
VerifyIncomingHTTPS: boolVal(c.VerifyIncomingHTTPS), if err != nil {
VerifyIncomingRPC: boolVal(c.VerifyIncomingRPC), return RuntimeConfig{}, err
VerifyOutgoing: verifyOutgoing,
VerifyServerHostname: verifyServerName,
Watches: c.Watches,
} }
rt.UseStreamingBackend = boolValWithDefault(c.UseStreamingBackend, true) 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") b.warn("rpc.enable_streaming = true has no effect when not running in server mode")
} }
if rt.AutoEncryptAllowTLS { if rt.AutoEncryptAllowTLS && !rt.TLS.InternalRPC.VerifyIncoming {
if !rt.VerifyIncoming && !rt.VerifyIncomingRPC { 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.")
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 err := checkLimitsFromMaxConnsPerClient(rt.HTTPMaxConnsPerClient); err != nil { 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 // 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. // 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") 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 // 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. // 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") 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 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"` Bootstrap *bool `mapstructure:"bootstrap"`
BootstrapExpect *int `mapstructure:"bootstrap_expect"` BootstrapExpect *int `mapstructure:"bootstrap_expect"`
Cache Cache `mapstructure:"cache"` 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 Check *CheckDefinition `mapstructure:"check"` // needs to be a pointer to avoid partial merges
CheckOutputMaxSize *int `mapstructure:"check_output_max_size"` CheckOutputMaxSize *int `mapstructure:"check_output_max_size"`
CheckUpdateInterval *string `mapstructure:"check_update_interval"` CheckUpdateInterval *string `mapstructure:"check_update_interval"`
@ -186,7 +183,6 @@ type Config struct {
GossipLAN GossipLANConfig `mapstructure:"gossip_lan"` GossipLAN GossipLANConfig `mapstructure:"gossip_lan"`
GossipWAN GossipWANConfig `mapstructure:"gossip_wan"` GossipWAN GossipWANConfig `mapstructure:"gossip_wan"`
HTTPConfig HTTPConfig `mapstructure:"http_config"` HTTPConfig HTTPConfig `mapstructure:"http_config"`
KeyFile *string `mapstructure:"key_file"`
LeaveOnTerm *bool `mapstructure:"leave_on_terminate"` LeaveOnTerm *bool `mapstructure:"leave_on_terminate"`
LicensePath *string `mapstructure:"license_path"` LicensePath *string `mapstructure:"license_path"`
Limits Limits `mapstructure:"limits"` Limits Limits `mapstructure:"limits"`
@ -233,9 +229,7 @@ type Config struct {
StartJoinAddrsLAN []string `mapstructure:"start_join"` StartJoinAddrsLAN []string `mapstructure:"start_join"`
StartJoinAddrsWAN []string `mapstructure:"start_join_wan"` StartJoinAddrsWAN []string `mapstructure:"start_join_wan"`
SyslogFacility *string `mapstructure:"syslog_facility"` SyslogFacility *string `mapstructure:"syslog_facility"`
TLSCipherSuites *string `mapstructure:"tls_cipher_suites"` TLS TLS `mapstructure:"tls"`
TLSMinVersion *string `mapstructure:"tls_min_version"`
TLSPreferServerCipherSuites *bool `mapstructure:"tls_prefer_server_cipher_suites"`
TaggedAddresses map[string]string `mapstructure:"tagged_addresses"` TaggedAddresses map[string]string `mapstructure:"tagged_addresses"`
Telemetry Telemetry `mapstructure:"telemetry"` Telemetry Telemetry `mapstructure:"telemetry"`
TranslateWANAddrs *bool `mapstructure:"translate_wan_addrs"` TranslateWANAddrs *bool `mapstructure:"translate_wan_addrs"`
@ -248,13 +242,8 @@ type Config struct {
UIDir *string `mapstructure:"ui_dir"` UIDir *string `mapstructure:"ui_dir"`
UIConfig RawUIConfig `mapstructure:"ui_config"` UIConfig RawUIConfig `mapstructure:"ui_config"`
UnixSocket UnixSocket `mapstructure:"unix_sockets"` UnixSocket UnixSocket `mapstructure:"unix_sockets"`
VerifyIncoming *bool `mapstructure:"verify_incoming"` Watches []map[string]interface{} `mapstructure:"watches"`
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"`
RPC RPC `mapstructure:"rpc"` RPC RPC `mapstructure:"rpc"`
@ -859,3 +848,22 @@ type RawUIMetricsProxyAddHeader struct {
type RPC struct { type RPC struct {
EnableStreaming *bool `mapstructure:"enable_streaming"` 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 server = false
syslog_facility = "LOCAL0" syslog_facility = "LOCAL0"
tls_min_version = "tls12"
tls = {
defaults = {
tls_min_version = "tls12"
}
}
// TODO (slackpad) - Until #3744 is done, we need to keep these // TODO (slackpad) - Until #3744 is done, we need to keep these
// in sync with agent/consul/config.go. // in sync with agent/consul/config.go.

View File

@ -1,6 +1,8 @@
package config package config
import "fmt" import (
"fmt"
)
type DeprecatedConfig struct { type DeprecatedConfig struct {
// DEPRECATED (ACL-Legacy-Compat) - moved into the "acl.tokens" stanza // DEPRECATED (ACL-Legacy-Compat) - moved into the "acl.tokens" stanza
@ -28,6 +30,42 @@ type DeprecatedConfig struct {
ACLDownPolicy *string `mapstructure:"acl_down_policy"` ACLDownPolicy *string `mapstructure:"acl_down_policy"`
// DEPRECATED (ACL-Legacy-Compat) - moved to "acl.token_ttl" // DEPRECATED (ACL-Legacy-Compat) - moved to "acl.token_ttl"
ACLTTL *string `mapstructure:"acl_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) { 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, deprecationWarning("acl_enable_key_list_policy", "acl.enable_key_list_policy"))
} }
warns = append(warns, applyDeprecatedTLSConfig(dep, &d.Config)...)
return d.Config, warns 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 { func deprecationWarning(old, new string) string {
return fmt.Sprintf("The '%v' field is deprecated. Use the '%v' field instead.", old, new) return fmt.Sprintf("The '%v' field is deprecated. Use the '%v' field instead.", old, new)
} }

View File

@ -1,11 +1,14 @@
package config package config
import ( import (
"crypto/tls"
"sort" "sort"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/hashicorp/consul/tlsutil"
) )
func TestLoad_DeprecatedConfig(t *testing.T) { func TestLoad_DeprecatedConfig(t *testing.T) {
@ -26,6 +29,18 @@ acl_down_policy = "async-cache"
acl_ttl = "3h" acl_ttl = "3h"
acl_enable_key_list_policy = true 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) patchLoadOptsShims(&opts)
@ -41,9 +56,20 @@ acl_enable_key_list_policy = true
deprecationWarning("acl_replication_token", "acl.tokens.replication"), deprecationWarning("acl_replication_token", "acl.tokens.replication"),
deprecationWarning("acl_token", "acl.tokens.default"), deprecationWarning("acl_token", "acl.tokens.default"),
deprecationWarning("acl_ttl", "acl.token_ttl"), 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.ElementsMatch(t, expectWarns, result.Warnings)
require.Equal(t, expectWarns, result.Warnings)
// Ideally this would compare against the entire result.RuntimeConfig, but // 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 // 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 // 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, "async-cache", rt.ACLResolverSettings.ACLDownPolicy)
require.Equal(t, 3*time.Hour, rt.ACLResolverSettings.ACLTokenTTL) require.Equal(t, 3*time.Hour, rt.ACLResolverSettings.ACLTokenTTL)
require.Equal(t, true, rt.ACLEnableKeyListPolicy) 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) { func TestLoad_DeprecatedConfig_ACLReplication(t *testing.T) {

View File

@ -377,24 +377,6 @@ type RuntimeConfig struct {
// Cache represent cache configuration of agent // Cache represent cache configuration of agent
Cache cache.Options 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 // 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 // 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 // state may run every 5 second generating a unique output (timestamp, etc), forcing
@ -767,12 +749,6 @@ type RuntimeConfig struct {
// flags: -https-port int // flags: -https-port int
HTTPSPort 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 // KVMaxValueSize controls the max allowed value size. If not set defaults
// to raft's suggested max value size. // to raft's suggested max value size.
// //
@ -1338,40 +1314,11 @@ type RuntimeConfig struct {
// flag: -join-wan string -join-wan string // flag: -join-wan string -join-wan string
StartJoinAddrsWAN []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: // hcl: tls { ... }
// TLS tlsutil.Config
// 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
// TaggedAddresses are used to publish a set of addresses for // TaggedAddresses are used to publish a set of addresses for
// for a node, which can be used by the remote agent. We currently // 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 } // hcl: unix_sockets { user = string }
UnixSocketUser 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 // Watches are used to monitor various endpoints and to invoke a
// handler to act appropriately. These are managed entirely in the // handler to act appropriately. These are managed entirely in the
// agent layer using the standard APIs. // 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) { func (c *RuntimeConfig) APIConfig(includeClientCerts bool) (*api.Config, error) {
tls := c.TLS.HTTPS
cfg := &api.Config{ cfg := &api.Config{
Datacenter: c.Datacenter, Datacenter: c.Datacenter,
TLSConfig: api.TLSConfig{InsecureSkipVerify: !c.VerifyOutgoing}, TLSConfig: api.TLSConfig{InsecureSkipVerify: !tls.VerifyOutgoing},
} }
unixAddr, httpAddr, httpsAddr := c.ClientAddress() unixAddr, httpAddr, httpsAddr := c.ClientAddress()
@ -1686,11 +1592,11 @@ func (c *RuntimeConfig) APIConfig(includeClientCerts bool) (*api.Config, error)
if httpsAddr != "" { if httpsAddr != "" {
cfg.Address = httpsAddr cfg.Address = httpsAddr
cfg.Scheme = "https" cfg.Scheme = "https"
cfg.TLSConfig.CAFile = c.CAFile cfg.TLSConfig.CAFile = tls.CAFile
cfg.TLSConfig.CAPath = c.CAPath cfg.TLSConfig.CAPath = tls.CAPath
if includeClientCerts { if includeClientCerts {
cfg.TLSConfig.CertFile = c.CertFile cfg.TLSConfig.CertFile = tls.CertFile
cfg.TLSConfig.KeyFile = c.KeyFile cfg.TLSConfig.KeyFile = tls.KeyFile
} }
} else if httpAddr != "" { } else if httpAddr != "" {
cfg.Address = 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{}) 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 // isSecret determines whether a field name represents a field which
// may contain a secret. // may contain a secret.
func isSecret(name string) bool { func isSecret(name string) bool {

View File

@ -32,6 +32,7 @@ import (
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/logging"
"github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/tlsutil"
"github.com/hashicorp/consul/types" "github.com/hashicorp/consul/types"
) )
@ -386,6 +387,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}, },
expected: func(rt *RuntimeConfig) { expected: func(rt *RuntimeConfig) {
rt.DNSDomain = "a" rt.DNSDomain = "a"
rt.TLS.Domain = "a"
rt.DataDir = dataDir rt.DataDir = dataDir
}, },
}) })
@ -590,6 +592,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}, },
expected: func(rt *RuntimeConfig) { expected: func(rt *RuntimeConfig) {
rt.NodeName = "a" rt.NodeName = "a"
rt.TLS.NodeName = "a"
rt.DataDir = dataDir 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`, 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{ run(t, testCase{
desc: "translated keys", desc: "translated keys",
args: []string{ args: []string{
@ -2920,8 +3015,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
`}, `},
expected: func(rt *RuntimeConfig) { expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir rt.DataDir = dataDir
rt.VerifyServerHostname = true rt.TLS.InternalRPC.VerifyServerHostname = true
rt.VerifyOutgoing = true rt.TLS.InternalRPC.VerifyOutgoing = true
},
expectedWarnings: []string{
deprecationWarning("verify_server_hostname", "tls.internal_rpc.verify_server_hostname"),
}, },
}) })
run(t, testCase{ run(t, testCase{
@ -2930,18 +3028,18 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
`-data-dir=` + dataDir, `-data-dir=` + dataDir,
}, },
json: []string{`{ json: []string{`{
"verify_incoming": true, "tls": { "internal_rpc": { "verify_incoming": true } },
"auto_encrypt": { "allow_tls": true }, "auto_encrypt": { "allow_tls": true },
"server": true "server": true
}`}, }`},
hcl: []string{` hcl: []string{`
verify_incoming = true tls { internal_rpc { verify_incoming = true } }
auto_encrypt { allow_tls = true } auto_encrypt { allow_tls = true }
server = true server = true
`}, `},
expected: func(rt *RuntimeConfig) { expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir rt.DataDir = dataDir
rt.VerifyIncoming = true rt.TLS.InternalRPC.VerifyIncoming = true
rt.AutoEncryptAllowTLS = true rt.AutoEncryptAllowTLS = true
rt.ConnectEnabled = true rt.ConnectEnabled = true
@ -2953,26 +3051,29 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}, },
}) })
run(t, testCase{ 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{ args: []string{
`-data-dir=` + dataDir, `-data-dir=` + dataDir,
}, },
json: []string{`{ json: []string{`{
"verify_incoming": true, "tls": { "defaults": { "verify_incoming": true } },
"auto_encrypt": { "allow_tls": true }, "auto_encrypt": { "allow_tls": true },
"server": true "server": true
}`}, }`},
hcl: []string{` hcl: []string{`
verify_incoming = true tls { defaults { verify_incoming = true } }
auto_encrypt { allow_tls = true } auto_encrypt { allow_tls = true }
server = true server = true
`}, `},
expected: func(rt *RuntimeConfig) { expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir rt.DataDir = dataDir
rt.VerifyIncoming = true
rt.AutoEncryptAllowTLS = true rt.AutoEncryptAllowTLS = true
rt.ConnectEnabled = true rt.ConnectEnabled = true
rt.TLS.InternalRPC.VerifyIncoming = true
rt.TLS.GRPC.VerifyIncoming = true
rt.TLS.HTTPS.VerifyIncoming = true
// server things // server things
rt.ServerMode = true rt.ServerMode = true
rt.LeaveOnTerm = false rt.LeaveOnTerm = false
@ -2981,25 +3082,25 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}, },
}) })
run(t, testCase{ 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{ args: []string{
`-data-dir=` + dataDir, `-data-dir=` + dataDir,
}, },
json: []string{`{ json: []string{`{
"verify_incoming_rpc": true, "tls": { "internal_rpc": { "verify_incoming": true } },
"auto_encrypt": { "allow_tls": true }, "auto_encrypt": { "allow_tls": true },
"server": true "server": true
}`}, }`},
hcl: []string{` hcl: []string{`
verify_incoming_rpc = true tls { internal_rpc { verify_incoming = true } }
auto_encrypt { allow_tls = true } auto_encrypt { allow_tls = true }
server = true server = true
`}, `},
expected: func(rt *RuntimeConfig) { expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir rt.DataDir = dataDir
rt.VerifyIncomingRPC = true
rt.AutoEncryptAllowTLS = true rt.AutoEncryptAllowTLS = true
rt.ConnectEnabled = true rt.ConnectEnabled = true
rt.TLS.InternalRPC.VerifyIncoming = true
// server things // server things
rt.ServerMode = true rt.ServerMode = true
@ -3009,7 +3110,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
}, },
}) })
run(t, testCase{ 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{ args: []string{
`-data-dir=` + dataDir, `-data-dir=` + dataDir,
}, },
@ -3021,7 +3122,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
auto_encrypt { allow_tls = true } auto_encrypt { allow_tls = true }
server = 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) { expected: func(rt *RuntimeConfig) {
rt.DataDir = dataDir rt.DataDir = dataDir
rt.AutoEncryptAllowTLS = true rt.AutoEncryptAllowTLS = true
@ -4436,7 +4537,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
auto_encrypt { auto_encrypt {
tls = true tls = true
} }
verify_outgoing = true tls {
internal_rpc {
verify_outgoing = true
}
}
`}, `},
json: []string{`{ json: []string{`{
"auto_config": { "auto_config": {
@ -4447,7 +4552,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"auto_encrypt": { "auto_encrypt": {
"tls": true "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.", 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" intro_token = "blah"
server_addresses = ["198.18.0.1"] server_addresses = ["198.18.0.1"]
} }
verify_outgoing = true tls {
internal_rpc {
verify_outgoing = true
}
}
`}, `},
json: []string{` json: []string{`
{ {
@ -4473,7 +4586,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"intro_token": "blah", "intro_token": "blah",
"server_addresses": ["198.18.0.1"] "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", expectedErr: "auto_config.enabled cannot be set to true for server agents",
}) })
@ -4536,7 +4653,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
enabled = true enabled = true
server_addresses = ["198.18.0.1"] server_addresses = ["198.18.0.1"]
} }
verify_outgoing = true tls {
internal_rpc {
verify_outgoing = true
}
}
`}, `},
json: []string{` json: []string{`
{ {
@ -4544,7 +4665,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"enabled": true, "enabled": true,
"server_addresses": ["198.18.0.1"] "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", 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 enabled = true
intro_token = "blah" intro_token = "blah"
} }
verify_outgoing = true tls {
internal_rpc {
verify_outgoing = true
}
}
`}, `},
json: []string{` json: []string{`
{ {
@ -4567,7 +4696,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"enabled": true, "enabled": true,
"intro_token": "blah" "intro_token": "blah"
}, },
"verify_outgoing": true "tls": {
"internal_rpc": {
"verify_outgoing": true
}
}
}`}, }`},
expectedErr: "auto_config.enabled is set without providing a list of addresses", 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"] dns_sans = ["foo"]
ip_sans = ["invalid", "127.0.0.1"] ip_sans = ["invalid", "127.0.0.1"]
} }
verify_outgoing = true tls {
internal_rpc {
verify_outgoing = true
}
}
`}, `},
json: []string{` json: []string{`
{ {
@ -4598,7 +4735,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"dns_sans": ["foo"], "dns_sans": ["foo"],
"ip_sans": ["invalid", "127.0.0.1"] "ip_sans": ["invalid", "127.0.0.1"]
}, },
"verify_outgoing": true "tls": {
"internal_rpc": {
"verify_outgoing": true
}
}
}`}, }`},
expectedWarnings: []string{ expectedWarnings: []string{
"Cannot parse ip \"invalid\" from auto_config.ip_sans", "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.DNSSANs = []string{"foo"}
rt.AutoConfig.IPSANs = []net.IP{net.IPv4(127, 0, 0, 1)} rt.AutoConfig.IPSANs = []net.IP{net.IPv4(127, 0, 0, 1)}
rt.DataDir = dataDir 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 enabled = true
} }
} }
cert_file = "foo" tls {
internal_rpc {
cert_file = "foo"
}
}
`}, `},
json: []string{` json: []string{`
{ {
@ -4661,7 +4807,11 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
"enabled": true "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"`, 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{` 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"`, 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{` 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)`, 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{` 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`, 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{` 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) { expected: func(rt *RuntimeConfig) {
rt.AutoConfig.Authorizer.Enabled = true rt.AutoConfig.Authorizer.Enabled = true
@ -4831,7 +5013,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) {
rt.LeaveOnTerm = false rt.LeaveOnTerm = false
rt.ServerMode = true rt.ServerMode = true
rt.SkipLeaveOnInt = true rt.SkipLeaveOnInt = true
rt.CertFile = "foo" rt.TLS.InternalRPC.CertFile = "foo"
rt.RPCConfig.EnableStreaming = true 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", 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) { func (tc testCase) run(format string, dataDir string) func(t *testing.T) {
@ -5382,9 +5723,6 @@ func TestLoad_FullConfig(t *testing.T) {
EntryFetchMaxBurst: 42, EntryFetchMaxBurst: 42,
EntryFetchRate: 0.334, EntryFetchRate: 0.334,
}, },
CAFile: "erA7T0PM",
CAPath: "mQEN1Mfp",
CertFile: "7s4QAzDk",
CheckOutputMaxSize: checks.DefaultBufSize, CheckOutputMaxSize: checks.DefaultBufSize,
Checks: []*structs.CheckDefinition{ Checks: []*structs.CheckDefinition{
{ {
@ -5592,7 +5930,6 @@ func TestLoad_FullConfig(t *testing.T) {
HTTPSHandshakeTimeout: 2391 * time.Millisecond, HTTPSHandshakeTimeout: 2391 * time.Millisecond,
HTTPSPort: 15127, HTTPSPort: 15127,
HTTPUseCache: false, HTTPUseCache: false,
KeyFile: "IEkkwgIA",
KVMaxValueSize: 1234567800, KVMaxValueSize: 1234567800,
LeaveDrainTime: 8265 * time.Second, LeaveDrainTime: 8265 * time.Second,
LeaveOnTerm: true, LeaveOnTerm: true,
@ -5966,9 +6303,43 @@ func TestLoad_FullConfig(t *testing.T) {
Name: "ftO6DySn", // notice this is the same as the metrics prefix 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}, TLS: tlsutil.Config{
TLSMinVersion: "pAOWafkR", InternalRPC: tlsutil.ProtocolConfig{
TLSPreferServerCipherSuites: true, 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{ TaggedAddresses: map[string]string{
"7MYgHrYH": "dALJAhLD", "7MYgHrYH": "dALJAhLD",
"h6DdBy6K": "ebrr9zZ8", "h6DdBy6K": "ebrr9zZ8",
@ -5997,14 +6368,9 @@ func TestLoad_FullConfig(t *testing.T) {
}, },
DashboardURLTemplates: map[string]string{"u2eziu2n_lower_case": "http://lkjasd.otr"}, DashboardURLTemplates: map[string]string{"u2eziu2n_lower_case": "http://lkjasd.otr"},
}, },
UnixSocketUser: "E0nB1DwA", UnixSocketUser: "E0nB1DwA",
UnixSocketGroup: "8pFodrV8", UnixSocketGroup: "8pFodrV8",
UnixSocketMode: "E8sAwOv4", UnixSocketMode: "E8sAwOv4",
VerifyIncoming: true,
VerifyIncomingHTTPS: true,
VerifyIncomingRPC: true,
VerifyOutgoing: true,
VerifyServerHostname: true,
Watches: []map[string]interface{}{ Watches: []map[string]interface{}{
{ {
"type": "key", "type": "key",
@ -6038,6 +6404,18 @@ func TestLoad_FullConfig(t *testing.T) {
deprecationWarning("acl_ttl", "acl.token_ttl"), deprecationWarning("acl_ttl", "acl.token_ttl"),
deprecationWarning("acl_enable_key_list_policy", "acl.enable_key_list_policy"), deprecationWarning("acl_enable_key_list_policy", "acl.enable_key_list_policy"),
`bootstrap_expect > 0: expecting 53 servers`, `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...) expectedWarns = append(expectedWarns, enterpriseConfigKeyWarnings...)
@ -6350,34 +6728,38 @@ func TestRuntime_APIConfigHTTPS(t *testing.T) {
HTTPSAddrs: []net.Addr{ HTTPSAddrs: []net.Addr{
&net.TCPAddr{IP: net.ParseIP("198.18.0.2"), Port: 5678}, &net.TCPAddr{IP: net.ParseIP("198.18.0.2"), Port: 5678},
}, },
Datacenter: "dc-test", Datacenter: "dc-test",
CAFile: "/etc/consul/ca.crt", TLS: tlsutil.Config{
CAPath: "/etc/consul/ca.dir", HTTPS: tlsutil.ProtocolConfig{
CertFile: "/etc/consul/server.crt", CAFile: "/etc/consul/ca.crt",
KeyFile: "/etc/consul/ssl/server.key", CAPath: "/etc/consul/ca.dir",
VerifyOutgoing: false, CertFile: "/etc/consul/server.crt",
KeyFile: "/etc/consul/ssl/server.key",
VerifyOutgoing: false,
},
},
} }
cfg, err := rt.APIConfig(false) cfg, err := rt.APIConfig(false)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "198.18.0.2:5678", cfg.Address) require.Equal(t, "198.18.0.2:5678", cfg.Address)
require.Equal(t, "https", cfg.Scheme) require.Equal(t, "https", cfg.Scheme)
require.Equal(t, rt.CAFile, cfg.TLSConfig.CAFile) require.Equal(t, rt.TLS.HTTPS.CAFile, cfg.TLSConfig.CAFile)
require.Equal(t, rt.CAPath, cfg.TLSConfig.CAPath) require.Equal(t, rt.TLS.HTTPS.CAPath, cfg.TLSConfig.CAPath)
require.Equal(t, "", cfg.TLSConfig.CertFile) require.Equal(t, "", cfg.TLSConfig.CertFile)
require.Equal(t, "", cfg.TLSConfig.KeyFile) require.Equal(t, "", cfg.TLSConfig.KeyFile)
require.Equal(t, rt.Datacenter, cfg.Datacenter) require.Equal(t, rt.Datacenter, cfg.Datacenter)
require.Equal(t, true, cfg.TLSConfig.InsecureSkipVerify) require.Equal(t, true, cfg.TLSConfig.InsecureSkipVerify)
rt.VerifyOutgoing = true rt.TLS.HTTPS.VerifyOutgoing = true
cfg, err = rt.APIConfig(true) cfg, err = rt.APIConfig(true)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "198.18.0.2:5678", cfg.Address) require.Equal(t, "198.18.0.2:5678", cfg.Address)
require.Equal(t, "https", cfg.Scheme) require.Equal(t, "https", cfg.Scheme)
require.Equal(t, rt.CAFile, cfg.TLSConfig.CAFile) require.Equal(t, rt.TLS.HTTPS.CAFile, cfg.TLSConfig.CAFile)
require.Equal(t, rt.CAPath, cfg.TLSConfig.CAPath) require.Equal(t, rt.TLS.HTTPS.CAPath, cfg.TLSConfig.CAPath)
require.Equal(t, rt.CertFile, cfg.TLSConfig.CertFile) require.Equal(t, rt.TLS.HTTPS.CertFile, cfg.TLSConfig.CertFile)
require.Equal(t, rt.KeyFile, cfg.TLSConfig.KeyFile) require.Equal(t, rt.TLS.HTTPS.KeyFile, cfg.TLSConfig.KeyFile)
require.Equal(t, rt.Datacenter, cfg.Datacenter) require.Equal(t, rt.Datacenter, cfg.Datacenter)
require.Equal(t, false, cfg.TLSConfig.InsecureSkipVerify) require.Equal(t, false, cfg.TLSConfig.InsecureSkipVerify)
} }
@ -6515,86 +6897,6 @@ func TestRuntime_ClientAddressAnyV6(t *testing.T) {
require.Equal(t, "[::1]:5688", https) 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) { func Test_UIPathBuilder(t *testing.T) {
cases := []struct { cases := []struct {
name string name string

View File

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

View File

@ -647,6 +647,48 @@ telemetry {
statsite_address = "HpFwKB8R" statsite_address = "HpFwKB8R"
disable_compat_1.9 = true 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_cipher_suites = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
tls_min_version = "pAOWafkR" tls_min_version = "pAOWafkR"
tls_prefer_server_cipher_suites = true tls_prefer_server_cipher_suites = true

View File

@ -644,6 +644,47 @@
"statsite_address": "HpFwKB8R", "statsite_address": "HpFwKB8R",
"disable_compat_1.9": true "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_cipher_suites": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"tls_min_version": "pAOWafkR", "tls_min_version": "pAOWafkR",
"tls_prefer_server_cipher_suites": true, "tls_prefer_server_cipher_suites": true,

View File

@ -280,19 +280,8 @@ func (ac *AutoConfig) updateTLSSettingsInConfig(_ AutoConfigOptions, resp *pbaut
return nil 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 var err error
resp.Config.TLS.CipherSuites, err = tlsutil.CipherString(base.CipherSuites) resp.Config.TLS, err = ac.tlsConfigurator.AutoConfigTLSSettings()
return err return err
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -22,7 +22,6 @@ import (
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
"github.com/armon/go-metrics" "github.com/armon/go-metrics"
"github.com/hashicorp/consul-net-rpc/net/rpc"
connlimit "github.com/hashicorp/go-connlimit" connlimit "github.com/hashicorp/go-connlimit"
"github.com/hashicorp/go-hclog" "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-memdb" "github.com/hashicorp/go-memdb"
@ -33,6 +32,8 @@ import (
"golang.org/x/time/rate" "golang.org/x/time/rate"
"google.golang.org/grpc" "google.golang.org/grpc"
"github.com/hashicorp/consul-net-rpc/net/rpc"
"github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/consul/authmethod" "github.com/hashicorp/consul/agent/consul/authmethod"
"github.com/hashicorp/consul/agent/consul/authmethod/ssoauth" "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["nonvoter"] = "1"
conf.Tags["read_replica"] = "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" conf.Tags["use_tls"] = "1"
} }

View File

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

View File

@ -6,9 +6,10 @@ import (
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/require"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/consul-net-rpc/net/rpc" "github.com/hashicorp/consul-net-rpc/net/rpc"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/agent/pool"
"github.com/hashicorp/consul/agent/structs" "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 // TODO(rb): add tests for the wanfed/alpn variations
_, conf1 := testServerConfig(t) _, conf1 := testServerConfig(t)
conf1.TLSConfig.VerifyIncoming = true conf1.TLSConfig.InternalRPC.VerifyIncoming = true
conf1.TLSConfig.VerifyOutgoing = true conf1.TLSConfig.InternalRPC.VerifyOutgoing = true
conf1.RPCConfig.EnableStreaming = true conf1.RPCConfig.EnableStreaming = true
configureTLS(conf1) configureTLS(conf1)
server, err := newServer(t, 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. // Set up a server with initially bad certificates.
_, conf1 := testServerConfig(t) _, conf1 := testServerConfig(t)
conf1.TLSConfig.VerifyIncoming = true conf1.TLSConfig.InternalRPC.VerifyIncoming = true
conf1.TLSConfig.VerifyOutgoing = true conf1.TLSConfig.InternalRPC.VerifyOutgoing = true
conf1.TLSConfig.CAFile = "../../test/ca/root.cer" conf1.TLSConfig.InternalRPC.CAFile = "../../test/ca/root.cer"
conf1.TLSConfig.CertFile = "../../test/key/ssl-cert-snakeoil.pem" conf1.TLSConfig.InternalRPC.CertFile = "../../test/key/ssl-cert-snakeoil.pem"
conf1.TLSConfig.KeyFile = "../../test/key/ssl-cert-snakeoil.key" conf1.TLSConfig.InternalRPC.KeyFile = "../../test/key/ssl-cert-snakeoil.key"
conf1.RPCConfig.EnableStreaming = true conf1.RPCConfig.EnableStreaming = true
server, err := newServer(t, conf1) server, err := newServer(t, conf1)
@ -199,8 +199,8 @@ func TestSubscribeBackend_IntegrationWithServer_TLSReload(t *testing.T) {
// Reload the server with valid certs // Reload the server with valid certs
newConf := server.config.TLSConfig newConf := server.config.TLSConfig
newConf.CertFile = "../../test/key/ourdomain.cer" newConf.InternalRPC.CertFile = "../../test/key/ourdomain.cer"
newConf.KeyFile = "../../test/key/ourdomain.key" newConf.InternalRPC.KeyFile = "../../test/key/ourdomain.key"
server.tlsConfigurator.Update(newConf) server.tlsConfigurator.Update(newConf)
// Try the subscribe call again // Try the subscribe call again
@ -212,7 +212,7 @@ func TestSubscribeBackend_IntegrationWithServer_TLSReload(t *testing.T) {
} }
func clientConfigVerifyOutgoing(config *Config) { 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, // 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) registerWithGRPC(t, res)
tlsConf, err := tlsutil.NewConfigurator(tlsutil.Config{ tlsConf, err := tlsutil.NewConfigurator(tlsutil.Config{
VerifyIncoming: true, InternalRPC: tlsutil.ProtocolConfig{
VerifyOutgoing: true, VerifyIncoming: true,
CAFile: "../../test/hostname/CertAuth.crt", CAFile: "../../test/hostname/CertAuth.crt",
CertFile: "../../test/hostname/Alice.crt", CertFile: "../../test/hostname/Alice.crt",
KeyFile: "../../test/hostname/Alice.key", KeyFile: "../../test/hostname/Alice.key",
VerifyOutgoing: true,
},
}, hclog.New(nil)) }, hclog.New(nil))
require.NoError(t, err) require.NoError(t, err)
@ -188,14 +190,16 @@ func TestNewDialer_IntegrationWithTLSEnabledHandler_viaMeshGateway(t *testing.T)
registerWithGRPC(t, res) registerWithGRPC(t, res)
tlsConf, err := tlsutil.NewConfigurator(tlsutil.Config{ tlsConf, err := tlsutil.NewConfigurator(tlsutil.Config{
VerifyIncoming: true, InternalRPC: tlsutil.ProtocolConfig{
VerifyOutgoing: true, VerifyIncoming: true,
VerifyServerHostname: true, CAFile: "../../test/hostname/CertAuth.crt",
CAFile: "../../test/hostname/CertAuth.crt", CertFile: "../../test/hostname/Bob.crt",
CertFile: "../../test/hostname/Bob.crt", KeyFile: "../../test/hostname/Bob.key",
KeyFile: "../../test/hostname/Bob.key", VerifyOutgoing: true,
Domain: "consul", VerifyServerHostname: true,
NodeName: "bob", },
Domain: "consul",
NodeName: "bob",
}, hclog.New(nil)) }, hclog.New(nil))
require.NoError(t, err) require.NoError(t, err)
@ -216,14 +220,16 @@ func TestNewDialer_IntegrationWithTLSEnabledHandler_viaMeshGateway(t *testing.T)
t.Cleanup(srv.shutdown) t.Cleanup(srv.shutdown)
clientTLSConf, err := tlsutil.NewConfigurator(tlsutil.Config{ clientTLSConf, err := tlsutil.NewConfigurator(tlsutil.Config{
VerifyIncoming: true, InternalRPC: tlsutil.ProtocolConfig{
VerifyOutgoing: true, VerifyIncoming: true,
VerifyServerHostname: true, CAFile: "../../test/hostname/CertAuth.crt",
CAFile: "../../test/hostname/CertAuth.crt", CertFile: "../../test/hostname/Betty.crt",
CertFile: "../../test/hostname/Betty.crt", KeyFile: "../../test/hostname/Betty.key",
KeyFile: "../../test/hostname/Betty.key", VerifyOutgoing: true,
Domain: "consul", VerifyServerHostname: true,
NodeName: "betty", },
Domain: "consul",
NodeName: "betty",
}, hclog.New(nil)) }, hclog.New(nil))
require.NoError(t, err) require.NoError(t, err)

View File

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

View File

@ -11,9 +11,10 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/hashicorp/yamux"
msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc"
"github.com/hashicorp/consul-net-rpc/net/rpc" "github.com/hashicorp/consul-net-rpc/net/rpc"
"github.com/hashicorp/yamux"
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib" "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) 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 { if err != nil {
return d, err return d, err
} }

View File

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

View File

@ -32,7 +32,9 @@ message TLS {
bool VerifyServerHostname = 2; bool VerifyServerHostname = 2;
string CipherSuites = 3; string CipherSuites = 3;
string MinVersion = 4; 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 { message ACL {

View File

@ -18,6 +18,7 @@ import (
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
"github.com/hashicorp/consul/logging" "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 // 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, "tls13": tls.VersionTLS13,
} }
// Config used to create tls.Config // ProtocolConfig contains configuration for a given protocol.
type Config struct { type ProtocolConfig struct {
// VerifyIncoming is used to verify the authenticity of incoming // VerifyIncoming is used to verify the authenticity of incoming
// connections. This means that TCP requests are forbidden, only // connections. This means that TCP requests are forbidden, only
// allowing for TLS. TLS connections must match a provided certificate // allowing for TLS. TLS connections must match a provided certificate
// authority. This can be used to force client auth. // authority. This can be used to force client auth.
VerifyIncoming bool 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 // CAFile is a path to a certificate authority file. This is used with
// VerifyIncoming or VerifyOutgoing to verify the TLS connection. // VerifyIncoming or VerifyOutgoing to verify the TLS connection.
CAFile string CAFile string
@ -97,6 +70,62 @@ type Config struct {
// connections. Must be provided to serve TLS connections. // connections. Must be provided to serve TLS connections.
KeyFile string 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. // Node name is the name we use to advertise. Defaults to hostname.
NodeName string NodeName string
@ -107,16 +136,6 @@ type Config struct {
// Domain is the Consul TLD being used. Defaults to "consul." // Domain is the Consul TLD being used. Defaults to "consul."
Domain string 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 // EnableAgentTLSForChecks is used to apply the agent's TLS settings in
// order to configure the HTTP client used for health checks. Enabling // order to configure the HTTP client used for health checks. Enabling
// this allows HTTP checks to present a client certificate and verify // 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 // protocolConfig contains the loaded state (e.g. x509 certificates) for a given
// auto-config features. // ProtocolConfig.
type autoTLS struct { type protocolConfig struct {
extraCAPems []string // cert is the TLS certificate configured manually by the cert_file/key_file
connectCAPems []string // options in the configuration file.
cert *tls.Certificate cert *tls.Certificate
verifyServerHostname bool
}
// manual stores the TLS CA and cert received from Configurator.Update which // manualCAPEMs contains the PEM-encoded CA certificates provided manually by
// generally comes from the agent configuration. // the ca_file/ca_path options in the configuration file.
type manual struct { manualCAPEMs []string
caPems []string
cert *tls.Certificate // manualCAPool is a pool containing only manualCAPEM, for cases where it is
// caPool containing only the caPems. This CertPool should be used instead of // not appropriate to trust the Connect CA (e.g. when verifying server identity
// the Configurator.caPool when only the Agent TLS CA is allowed. // in AuthorizeServerConn).
caPool *x509.CertPool 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 // 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, // Configurator receives an initial TLS configuration from agent configuration,
// and receives updates from config reloads, auto-encrypt, and auto-config. // and receives updates from config reloads, auto-encrypt, and auto-config.
type Configurator struct { type Configurator struct {
@ -181,15 +203,25 @@ type Configurator struct {
version uint64 version uint64
// lock synchronizes access to all fields on this struct except for logger and version. // lock synchronizes access to all fields on this struct except for logger and version.
lock sync.RWMutex lock sync.RWMutex
base *Config base *Config
autoTLS autoTLS
manual manual
caPool *x509.CertPool
// peerDatacenterUseTLS is a map of DC name to a bool indicating if the DC // peerDatacenterUseTLS is a map of DC name to a bool indicating if the DC
// uses TLS for RPC requests. // uses TLS for RPC requests.
peerDatacenterUseTLS map[string]bool 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 // logger is not protected by a lock. It must never be changed after
// Configurator is created. // Configurator is created.
logger hclog.Logger logger hclog.Logger
@ -215,11 +247,12 @@ func NewConfigurator(config Config, logger hclog.Logger) (*Configurator, error)
return c, nil 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 { func (c *Configurator) ManualCAPems() []string {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() defer c.lock.RUnlock()
return c.manual.caPems return c.internalRPC.manualCAPEMs
} }
// Update updates the internal configuration which is used to generate // Update updates the internal configuration which is used to generate
@ -229,36 +262,92 @@ func (c *Configurator) Update(config Config) error {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
cert, err := loadKeyPair(config.CertFile, config.KeyFile) grpc, err := c.loadProtocolConfig(config, config.GRPC)
if err != nil { if err != nil {
return err return err
} }
pems, err := LoadCAs(config.CAFile, config.CAPath)
https, err := c.loadProtocolConfig(config, config.HTTPS)
if err != nil { if err != nil {
return err return err
} }
caPool, err := newX509CertPool(pems, c.autoTLS.extraCAPems, c.autoTLS.connectCAPems)
if err != nil { internalRPC, err := c.loadProtocolConfig(config, config.InternalRPC)
return err
}
if err = validateConfig(config, caPool, cert); err != nil {
return err
}
manualCAPool, err := newX509CertPool(pems)
if err != nil { if err != nil {
return err return err
} }
c.base = &config c.base = &config
c.manual.cert = cert c.grpc = *grpc
c.manual.caPems = pems c.https = *https
c.manual.caPool = manualCAPool c.internalRPC = *internalRPC
c.caPool = caPool
atomic.AddUint64(&c.version, 1) atomic.AddUint64(&c.version, 1)
c.log("Update") c.log("Update")
return nil 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 // 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 // from the server in order to be able to accept TLS connections with TLS
// certificates. // certificates.
@ -267,15 +356,30 @@ func (c *Configurator) UpdateAutoTLSCA(connectCAPems []string) error {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() 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 { if err != nil {
return err return err
} }
if err = validateConfig(*c.base, pool, c.manual.cert); err != nil { grpcPool, err := makePool(c.grpc)
if err != nil {
return err return err
} }
httpsPool, err := makePool(c.https)
if err != nil {
return err
}
c.autoTLS.connectCAPems = connectCAPems c.autoTLS.connectCAPems = connectCAPems
c.caPool = pool c.internalRPC.combinedCAPool = internalRPCPool
c.grpc.combinedCAPool = grpcPool
c.https.combinedCAPool = httpsPool
atomic.AddUint64(&c.version, 1) atomic.AddUint64(&c.version, 1)
c.log("UpdateAutoTLSCA") c.log("UpdateAutoTLSCA")
return nil return nil
@ -308,15 +412,33 @@ func (c *Configurator) UpdateAutoTLS(manualCAPems, connectCAPems []string, pub,
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() 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 { if err != nil {
return err 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.extraCAPems = manualCAPems
c.autoTLS.connectCAPems = connectCAPems c.autoTLS.connectCAPems = connectCAPems
c.autoTLS.cert = &cert c.autoTLS.cert = &cert
c.caPool = pool
c.autoTLS.verifyServerHostname = verifyServerHostname c.autoTLS.verifyServerHostname = verifyServerHostname
c.internalRPC.combinedCAPool = internalRPCPool
c.grpc.combinedCAPool = grpcPool
c.https.combinedCAPool = httpsPool
atomic.AddUint64(&c.version, 1) atomic.AddUint64(&c.version, 1)
c.log("UpdateAutoTLS") c.log("UpdateAutoTLS")
return nil return nil
@ -368,46 +490,6 @@ func newX509CertPool(groups ...[]string) (*x509.CertPool, error) {
return pool, nil 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) { func loadKeyPair(certFile, keyFile string) (*tls.Certificate, error) {
if certFile == "" || keyFile == "" { if certFile == "" || keyFile == "" {
return nil, nil return nil, nil
@ -465,33 +547,43 @@ func LoadCAs(caFile, caPath string) ([]string, error) {
return pems, nil 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 // commonTLSConfig generates a *tls.Config from the base configuration the
// Configurator has. It accepts an additional flag in case a config is needed // Configurator has. It accepts an additional flag in case a config is needed
// for incoming TLS connections. // for incoming TLS connections.
// This function acquires a read lock because it reads from the config. func (c *Configurator) commonTLSConfig(state protocolConfig, cfg ProtocolConfig, verifyIncoming bool) *tls.Config {
func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config { var tlsConfig 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,
}
// Set the cipher suites // Set the cipher suites
if len(c.base.CipherSuites) != 0 { if len(cfg.CipherSuites) != 0 {
tlsConfig.CipherSuites = c.base.CipherSuites tlsConfig.CipherSuites = cfg.CipherSuites
} }
tlsConfig.PreferServerCipherSuites = c.base.PreferServerCipherSuites
// GetCertificate is used when acting as a server and responding to // GetCertificate is used when acting as a server and responding to
// client requests. Default to the manually configured cert, but allow // client requests. Default to the manually configured cert, but allow
// autoEncrypt cert too so that a client can encrypt incoming // autoEncrypt cert too so that a client can encrypt incoming
// connections without having a manual cert configured. // connections without having a manual cert configured.
tlsConfig.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { 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 // 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) { tlsConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
cert := c.autoTLS.cert cert := c.autoTLS.cert
if cert == nil { if cert == nil {
cert = c.manual.cert cert = state.cert
} }
if cert == nil { if cert == nil {
@ -512,39 +604,53 @@ func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config {
return cert, nil return cert, nil
} }
tlsConfig.ClientCAs = c.caPool tlsConfig.ClientCAs = state.combinedCAPool
tlsConfig.RootCAs = c.caPool tlsConfig.RootCAs = state.combinedCAPool
// This is possible because tlsLookup also contains "" with golang's // This is possible because tlsLookup also contains "" with golang's
// default (tls10). And because the initial check makes sure the // default (tls10). And because the initial check makes sure the
// version correctly matches. // version correctly matches.
tlsConfig.MinVersion = tlsLookup[c.base.TLSMinVersion] tlsConfig.MinVersion = tlsLookup[cfg.TLSMinVersion]
// Set ClientAuth if necessary // Set ClientAuth if necessary
if verifyIncoming { if verifyIncoming {
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert 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. // This function acquires a read lock because it reads from the config.
func (c *Configurator) Cert() *tls.Certificate { func (c *Configurator) Cert() *tls.Certificate {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() defer c.lock.RUnlock()
cert := c.manual.cert cert := c.internalRPC.cert
if cert == nil { if cert == nil {
cert = c.autoTLS.cert cert = c.autoTLS.cert
} }
return cert return cert
} }
// VerifyIncomingRPC returns true if the configuration has enabled either // GRPCTLSConfigured returns whether there's a TLS certificate configured for
// VerifyIncoming, or VerifyIncomingRPC // 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 { func (c *Configurator) VerifyIncomingRPC() bool {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() 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. // 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() defer c.lock.RUnlock()
// use TLS if AutoEncrypt or VerifyOutgoing are enabled. // 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 // MutualTLSCapable returns true if Configurator has a CA and a local TL
// certificate configured. // certificate configured on the internal RPC protocol.
func (c *Configurator) MutualTLSCapable() bool { func (c *Configurator) MutualTLSCapable() bool {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() 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. // 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 // If AutoEncryptTLS is enabled and there is a CA, then verify
// outgoing. // outgoing.
if c.base.AutoTLS && c.caPool != nil { if c.base.AutoTLS && c.internalRPC.combinedCAPool != nil {
return true 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 { func (c *Configurator) ServerSNI(dc, nodeName string) string {
// Strip the trailing '.' from the domain if any // Strip the trailing '.' from the domain if any
domain := strings.TrimSuffix(c.domain(), ".") domain := strings.TrimSuffix(c.domain(), ".")
@ -610,19 +717,45 @@ func (c *Configurator) serverNameOrNodeName() string {
func (c *Configurator) VerifyServerHostname() bool { func (c *Configurator) VerifyServerHostname() bool {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() 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. // AutoConfigTLSSettings constructs the pbconfig.TLS that will be returned by
func (c *Configurator) IncomingGRPCConfig() *tls.Config { // servers in the auto-config endpoint.
c.log("IncomingGRPCConfig") 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 cfg := c.base.InternalRPC
// verification. This is because there is no verify_incoming_grpc
// configuration option. And using verify_incoming would be backwards cipherString, err := CipherString(cfg.CipherSuites)
// incompatible, because even if it was set before, it didn't have an if err != nil {
// effect on the grpc server. return nil, err
config := c.commonTLSConfig(false) }
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) { config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return c.IncomingGRPCConfig(), nil return c.IncomingGRPCConfig(), nil
} }
@ -632,7 +765,7 @@ func (c *Configurator) IncomingGRPCConfig() *tls.Config {
// IncomingRPCConfig generates a *tls.Config for incoming RPC connections. // IncomingRPCConfig generates a *tls.Config for incoming RPC connections.
func (c *Configurator) IncomingRPCConfig() *tls.Config { func (c *Configurator) IncomingRPCConfig() *tls.Config {
c.log("IncomingRPCConfig") c.log("IncomingRPCConfig")
config := c.commonTLSConfig(c.VerifyIncomingRPC()) config := c.internalRPCTLSConfig(c.base.InternalRPC.VerifyIncoming)
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return c.IncomingRPCConfig(), nil return c.IncomingRPCConfig(), nil
} }
@ -645,7 +778,7 @@ func (c *Configurator) IncomingALPNRPCConfig(alpnProtos []string) *tls.Config {
c.log("IncomingALPNRPCConfig") c.log("IncomingALPNRPCConfig")
// Since the ALPN-RPC variation is indirectly exposed to the internet via // Since the ALPN-RPC variation is indirectly exposed to the internet via
// mesh gateways we force mTLS and full server name verification. // mesh gateways we force mTLS and full server name verification.
config := c.commonTLSConfig(true) config := c.internalRPCTLSConfig(true)
config.InsecureSkipVerify = false config.InsecureSkipVerify = false
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
@ -662,7 +795,7 @@ func (c *Configurator) IncomingALPNRPCConfig(alpnProtos []string) *tls.Config {
// usecase ever. // usecase ever.
func (c *Configurator) IncomingInsecureRPCConfig() *tls.Config { func (c *Configurator) IncomingInsecureRPCConfig() *tls.Config {
c.log("IncomingInsecureRPCConfig") c.log("IncomingInsecureRPCConfig")
config := c.commonTLSConfig(false) config := c.internalRPCTLSConfig(false)
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return c.IncomingInsecureRPCConfig(), nil return c.IncomingInsecureRPCConfig(), nil
} }
@ -674,10 +807,13 @@ func (c *Configurator) IncomingHTTPSConfig() *tls.Config {
c.log("IncomingHTTPSConfig") c.log("IncomingHTTPSConfig")
c.lock.RLock() c.lock.RLock()
verifyIncoming := c.base.VerifyIncoming || c.base.VerifyIncomingHTTPS defer c.lock.RUnlock()
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.NextProtos = []string{"h2", "http/1.1"}
config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { config.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return c.IncomingHTTPSConfig(), nil return c.IncomingHTTPSConfig(), nil
@ -706,22 +842,22 @@ func (c *Configurator) OutgoingTLSConfigForCheck(skipVerify bool, serverName str
if serverName == "" { if serverName == "" {
serverName = c.serverNameOrNodeName() serverName = c.serverNameOrNodeName()
} }
config := c.commonTLSConfig(false) config := c.internalRPCTLSConfig(false)
config.InsecureSkipVerify = skipVerify config.InsecureSkipVerify = skipVerify
config.ServerName = serverName config.ServerName = serverName
return config return config
} }
// OutgoingRPCConfig generates a *tls.Config for outgoing RPC connections. If // OutgoingRPCConfig generates a *tls.Config for outgoing internal RPC
// there is a CA or VerifyOutgoing is set, a *tls.Config will be provided, // connections. If there is a CA or VerifyOutgoing is set, a *tls.Config
// otherwise we assume that no TLS should be used. // will be provided, otherwise we assume that no TLS should be used.
func (c *Configurator) OutgoingRPCConfig() *tls.Config { func (c *Configurator) OutgoingRPCConfig() *tls.Config {
c.log("OutgoingRPCConfig") c.log("OutgoingRPCConfig")
if !c.outgoingRPCTLSEnabled() { if !c.outgoingRPCTLSEnabled() {
return nil return nil
} }
return c.commonTLSConfig(false) return c.internalRPCTLSConfig(false)
} }
// outgoingALPNRPCConfig generates a *tls.Config for outgoing RPC connections // 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 // Since the ALPN-RPC variation is indirectly exposed to the internet via
// mesh gateways we force mTLS and full server name verification. // mesh gateways we force mTLS and full server name verification.
config := c.commonTLSConfig(true) config := c.internalRPCTLSConfig(true)
config.InsecureSkipVerify = false config.InsecureSkipVerify = false
return config return config
} }
@ -912,7 +1048,7 @@ func (c *Configurator) AuthorizeServerConn(dc string, conn TLSConn) error {
} }
c.lock.RLock() c.lock.RLock()
caPool := c.manual.caPool caPool := c.internalRPC.manualCAPool
c.lock.RUnlock() c.lock.RUnlock()
expected := c.ServerSNI(dc, "") 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 ```hcl
node_name = "consul-server" node_name = "consul-server"
server = true server = true
ui_config { ui_config {
enabled = true enabled = true
} }
@ -257,13 +257,21 @@ retry_join = [
"consul-server2", "consul-server2",
"consul-server3" "consul-server3"
] ]
encrypt = "aPuGh+5UDskRAbkLaXRzFoSOcSM+5vAK+NEYOWHJH7w=" encrypt = "aPuGh+5UDskRAbkLaXRzFoSOcSM+5vAK+NEYOWHJH7w="
verify_incoming = true
verify_outgoing = true tls {
verify_server_hostname = true defaults {
ca_file = "/consul/config/certs/consul-agent-ca.pem" verify_incoming = true
cert_file = "/consul/config/certs/dc1-server-consul-0.pem" verify_outgoing = true
key_file = "/consul/config/certs/dc1-server-consul-0-key.pem" 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"], "retry_join": ["consul-server1", "consul-server2"],
"encrypt": "aPuGh+5UDskRAbkLaXRzFoSOcSM+5vAK+NEYOWHJH7w=", "encrypt": "aPuGh+5UDskRAbkLaXRzFoSOcSM+5vAK+NEYOWHJH7w=",
"verify_incoming": true, "tls": {
"verify_outgoing": true, "defaults": {
"verify_server_hostname": true, "verify_incoming": true,
"ca_file": "/consul/config/certs/consul-agent-ca.pem", "verify_outgoing": true,
"cert_file": "/consul/config/certs/dc1-server-consul-0.pem", "ca_file": "/consul/config/certs/consul-agent-ca.pem",
"key_file": "/consul/config/certs/dc1-server-consul-0-key.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 ## TLS Configuration Reference
This section documents all of the configuration settings that apply to Agent TLS. Agent 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 TLS is used by the HTTP API, internal RPC, and gRPC/xDS interfaces. Some of these settings
applied automatically by [auto_config](#auto_config) or [auto_encrypt](#auto_encrypt). 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` ~> **Security Note:** The Certificate Authority (CA) configured on the internal RPC interface
should be a private CA, not a public one. We recommend using a dedicated CA (either explicitly by `tls.internal_rpc` or implicitly by `tls.defaults`) should be a private
which should not be used with any other systems. Any certificate signed by the CA, not a public one. We recommend using a dedicated CA which should not be used with any other
CA will be allowed to communicate with the cluster and a specially crafted certificate systems. Any certificate signed by the CA will be allowed to communicate with the cluster and a
signed by the CA can be used to gain full access to Consul. 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 - `tls` Added in Consul 1.12, for previous versions see
authority. The certificate authority is used to check the authenticity of client [Deprecated Options](#tls_deprecated_options).
and server connections with the appropriate [`verify_incoming`](#verify_incoming)
or [`verify_outgoing`](#verify_outgoing) flags.
- `ca_path` This provides a path to a directory of PEM-encoded - `defaults` ((#tls_defaults)) Provides default settings that will be applied
certificate authority files. These certificate authorities are used to check the to every interface unless explicitly overridden by `tls.grpc`, `tls.https`,
authenticity of client and server connections with the appropriate [`verify_incoming`](#verify_incoming) or [`verify_outgoing`](#verify_outgoing) flags. or `tls.internal_rpc`.
- `cert_file` This provides a file path to a PEM-encoded - `ca_file` ((#tls_defaults_ca_file)) This provides a file path to a
certificate. The certificate is provided to clients or servers to verify the agent's PEM-encoded certificate authority. The certificate authority is used to
authenticity. It must be provided along with [`key_file`](#key_file). 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 - `ca_path` ((#tls_defaults_ca_path)) This provides a path to a directory
private key. The key is used with the certificate to verify the agent's authenticity. of PEM-encoded certificate authority files. These certificate authorities
This must be provided along with [`cert_file`](#cert_file). 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) - `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 for the TLS certificate. It can be used to ensure that the certificate name matches
the hostname we declare. the hostname we declare.
- `tls_min_version` Added in Consul 0.7.4, this specifies ### Deprecated Options ((#tls_deprecated_options))
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` Added in Consul 0.8.2, this specifies the list of The following options were deprecated in Consul 1.12, please use the
supported ciphersuites as a comma-separated-list. Applicable to TLS 1.2 and below only. [`tls`](#tls) stanza instead.
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 - `ca_file` See: [`tls.defaults.ca_file`](#tls_defaults_ca_file).
[post](https://go.dev/blog/tls-cipher-suites) for details.
- `tls_prefer_server_cipher_suites` Added in Consul 0.8.2, this - `ca_path` See: [`tls.defaults.ca_path`](#tls_defaults_ca_path).
will cause Consul to prefer the server's ciphersuite over the client ciphersuites.
~> **Note:** This config will be deprecated in Consul 1.11. See this - `cert_file` See: [`tls.defaults.cert_file`](#tls_defaults_cert_file).
[post](https://go.dev/blog/tls-cipher-suites) for details.
- `verify_incoming` - If set to true, Consul - `key_file` See: [`tls.defaults.key_file`](#tls_defaults_key_file).
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.
- `verify_incoming_rpc` - When set to true, Consul - `tls_min_version` Added in Consul 0.7.4.
requires that all incoming RPC connections use TLS and that the client See: [`tls.defaults.tls_min_version`](#tls_defaults_tls_min_version).
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.
~> **Security Note:** `verify_incoming_rpc` _must_ be set to true to prevent anyone - `tls_cipher_suites` Added in Consul 0.8.2.
with access to the RPC port from gaining full access to the Consul cluster. See: [`tls.defaults.tls_cipher_suites`](#tls_defaults_tls_cipher_suites).
- `verify_incoming_https` - If set to true, - `tls_prefer_server_cipher_suites` Added in Consul 0.8.2. This setting will
Consul requires that all incoming HTTPS connections make use of TLS and that the be ignored (see [this post](https://go.dev/blog/tls-cipher-suites) for details).
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.
- `verify_outgoing` - If set to true, Consul requires - `verify_incoming` See: [`tls.defaults.verify_incoming`](#tls_defaults_verify_incoming).
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.
~> **Security Note:** Note that servers that specify `verify_outgoing = true` will always talk to other servers over TLS, but they still _accept_ - `verify_incoming_rpc` See: [`tls.internal_rpc.verify_incoming`](#tls_internal_rpc_verify_incoming).
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` - When set to true, Consul verifies the TLS certificate - `verify_incoming_https` See: [`tls.https.verify_incoming`](#tls_https_verify_incoming).
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.
~> **Security Note:** From versions 0.5.1 to 1.4.0, due to a bug, setting - `verify_outgoing` See: [`tls.defaults.verify_outgoing`](#tls_defaults_verify_outgoing).
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 - `verify_server_hostname` See: [`tls.internal_rpc.verify_server_hostname`](#tls_internal_rpc_verify_server_hostname).
[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.
### Example Configuration File, with TLS ### Example Configuration File, with TLS
~> **Security Note:** all three verify options should be set as `true` to enable secure mTLS communication, enabling both ~> **Security Note:** all three verify options should be set as `true` to enable
encryption and authentication. Failing to set [`verify_incoming`](#verify_incoming) or [`verify_outgoing`](#verify_outgoing) secure mTLS communication, enabling both encryption and authentication. Failing
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). 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. See, especially, the use of the `ports` setting highlighted below.
@ -2575,12 +2658,19 @@ ports {
https = 8501 https = 8501
} }
key_file = "/etc/pki/tls/private/my.key" tls {
cert_file = "/etc/pki/tls/certs/my.crt" defaults {
ca_file = "/etc/pki/tls/certs/ca-bundle.crt" key_file = "/etc/pki/tls/private/my.key"
verify_incoming = true cert_file = "/etc/pki/tls/certs/my.crt"
verify_outgoing = true ca_file = "/etc/pki/tls/certs/ca-bundle.crt"
verify_server_hostname = true verify_incoming = true
verify_outgoing = true
}
internal_rpc {
verify_server_hostname = true
}
}
``` ```
</CodeBlockConfig> </CodeBlockConfig>
@ -2600,12 +2690,18 @@ verify_server_hostname = true
"ports": { "ports": {
"https": 8501 "https": 8501
}, },
"key_file": "/etc/pki/tls/private/my.key", "tls": {
"cert_file": "/etc/pki/tls/certs/my.crt", "defaults": {
"ca_file": "/etc/pki/tls/certs/ca-bundle.crt", "key_file": "/etc/pki/tls/private/my.key",
"verify_incoming": true, "cert_file": "/etc/pki/tls/certs/my.crt",
"verify_outgoing": true, "ca_file": "/etc/pki/tls/certs/ca-bundle.crt",
"verify_server_hostname": true "verify_incoming": true,
"verify_outgoing": true
},
"internal_rpc": {
"verify_server_hostname": true
}
}
} }
``` ```
@ -2613,8 +2709,8 @@ verify_server_hostname = true
</CodeTabs> </CodeTabs>
Consul will not enable TLS for the HTTP API unless the `https` port has been Consul will not enable TLS for the HTTP or gRPC API unless the `https` port has
assigned a port number `> 0`. We recommend using `8501` for `https` as this been assigned a port number `> 0`. We recommend using `8501` for `https` as this
default will automatically work with some tooling. default will automatically work with some tooling.
## Ports Used ## Ports Used

View File

@ -46,7 +46,7 @@ configuration file include:
- [certificate authority settings](/docs/agent/options#connect) - [certificate authority settings](/docs/agent/options#connect)
- [token replication](/docs/agent/options#acl_tokens_replication) - [token replication](/docs/agent/options#acl_tokens_replication)
- [dev mode](/docs/agent/options#_dev) - [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 If you would like to use Envoy as your Connect proxy you will need to [enable
gRPC](/docs/agent/options#grpc_port). gRPC](/docs/agent/options#grpc_port).

View File

@ -157,8 +157,12 @@ auto_encrypt = {
tls = true tls = true
ip_san = ["$ECS_IPV4"] ip_san = ["$ECS_IPV4"]
} }
ca_file = "/tmp/consul-ca-cert.pem" tls {
verify_outgoing = true defaults {
ca_file = "/tmp/consul-ca-cert.pem"
verify_outgoing = true
}
}
# Configure ACLs # Configure ACLs
acl { acl {
@ -177,12 +181,12 @@ EOF
The following table describes the additional fields that must be included in the Consul client configuration file. The following table describes the additional fields that must be included in the Consul client configuration file.
| Field name | Type | Description | | Field name | Type | Description |
| --------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------ | | --------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------ |
| [`encrypt`](/docs/agent/options#_encrypt) | string | Specifies the gossip encryption key | | [`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. | | [`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) | boolen | Enable ACLs for this agent. | | [`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. | | [`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` ## 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 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. 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`, - `verify` ((#v-global-tls-verify)) (`boolean: true`) - If true, `tls.defaults.verify_outgoing`,
and `verify_incoming_rpc` will be set to `true` for Consul servers and clients. `tls.internal_rpc.verify_server_hostname`, and `tls.internal_rpc.verify_incoming` will be set
Set this to false to incrementally roll out TLS on an existing Consul cluster. to `true` for Consul servers and clients. Set this to false to incrementally roll out TLS
Please see https://consul.io/docs/k8s/operations/tls-on-existing-cluster on an existing Consul cluster.
for more details. 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 - `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. 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 -> **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 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), 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 that setting isn't strictly necessary to support Consul's threat model as it is recommended that
all requests contain a valid ACL token. 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"> <CodeBlockConfig filename="server.hcl">
```hcl ```hcl
cert_file = "vm-dc-server-consul-0.pem" tls {
key_file = "vm-dc-server-consul-0-key.pem" defaults {
ca_file = "consul-agent-ca.pem" cert_file = "vm-dc-server-consul-0.pem"
key_file = "vm-dc-server-consul-0-key.pem"
ca_file = "consul-agent-ca.pem"
}
}
``` ```
</CodeBlockConfig> </CodeBlockConfig>
@ -160,9 +164,19 @@ A final example server config file might look like:
```hcl ```hcl
# From above # From above
cert_file = "vm-dc-server-consul-0.pem" tls {
key_file = "vm-dc-server-consul-0-key.pem" defaults {
ca_file = "consul-agent-ca.pem" 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"] primary_gateways = ["1.2.3.4:443"]
acl { acl {
enabled = true enabled = true
@ -185,9 +199,6 @@ connect {
enabled = true enabled = true
enable_mesh_gateway_wan_federation = true enable_mesh_gateway_wan_federation = true
} }
verify_incoming_rpc = true
verify_outgoing = true
verify_server_hostname = true
ports { ports {
https = 8501 https = 8501
http = -1 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. ~> 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. 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), These modes are controlled by the [`verify_outgoing`](/docs/agent/options#tls_internal_rpc_verify_outgoing),
[`verify_server_hostname`](/docs/agent/options#verify_server_hostname), [`verify_server_hostname`](/docs/agent/options#tls_internal_rpc_verify_server_hostname),
and [`verify_incoming`](/docs/agent/options#verify_incoming) options, respectively. 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 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 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) [`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#cert_file) and [`key_file`](/docs/agent/options#key_file). 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 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 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 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 to true, and generate the proper certificates, but this is defaulted to false to avoid breaking
existing deployments. 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 authenticity of all incoming connections. All clients must have a valid key pair set using
[`cert_file`](/docs/agent/options#cert_file) and [`cert_file`](/docs/agent/options#tls_internal_rpc_cert_file) and
[`key_file`](/docs/agent/options#key_file). Servers will [`key_file`](/docs/agent/options#tls_internal_rpc_key_file). Servers will
also disallow any non-TLS connections. To force clients to use TLS, 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 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. 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 - **mTLS** - Mutual authentication of both the TLS server and client x509 certificates prevents internal abuse through
unauthorized access to Consul agents within the cluster. 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 - [`tls.defaults.verify_incoming`](/docs/agent/options#tls_defaults_verify_incoming) - By default this is false, and
to true to require TLS verification for incoming client connections. This applies to both server RPC and to the should almost always be set to true to require TLS verification for incoming client connections. This applies to the
HTTPS API. internal RPC, HTTPS and gRPC APIs.
- [`verify_incoming_https`](/docs/agent/options#verify_incoming_https) - By default this is false, and should be set - [`tls.https.verify_incoming`](/docs/agent/options#tls_https_verify_incoming) - By default this is false, and should
to true to require clients to provide a valid TLS certificate when the Consul HTTPS API is enabled. TLS for the API be set to true to require clients to provide a valid TLS certificate when the Consul HTTPS API is enabled. TLS for
may be not be necessary if it is exclusively served over a loopback interface such as `localhost`. 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 - [`tls.internal_rpc.verify_incoming`](/docs/agent/options#tls_internal_rpc_verify_incoming) - By default this is false,
always be set to true to require clients to provide a valid TLS certificate for Consul agent RPCs. 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 - [`tls.grpc.verify_incoming`](/docs/agent/options#tls_grpc_verify_incoming) - By default this is false, and should
require TLS for outgoing connections from server or client agents. Servers that specify `verify_outgoing = true` be set to true to require clients to provide a valid TLS certificate when the Consul gRPC API is enabled. TLS for
will always talk to other servers over TLS, but they still accept non-TLS connections to allow for a transition of the API may be not be necessary if it is exclusively served over a loopback interface such as `localhost`.
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.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 - [`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 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. added in Consul 1.0.1.
- [`verify_server_hostname`](/docs/agent/options#verify_server_hostname) - By default this is false, and should be - [`tls.internal_rpc.verify_server_hostname`](/docs/agent/options#tls_internal_rpc_verify_server_hostname) - By default
set to true to require that the TLS certificate presented by the servers matches 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 `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 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 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. in 1.4.1.
- [`auto_encrypt`](/docs/agent/options#auto_encrypt) - Enables automated TLS certificate distribution for client - [`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. 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 - [`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** **Example Server Agent TLS Configuration**
```hcl ```hcl
verify_incoming = true tls {
verify_outgoing = true defaults {
verify_server_hostname = true 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" internal_rpc {
cert_file = "dc1-server-consul-0.pem" verify_server_hostname = true
key_file = "dc1-server-consul-0-key.pem" }
}
auto_encrypt { auto_encrypt {
allow_tls = true allow_tls = true
} }
``` ```
**Example Client Agent TLS Configuration** **Example Client Agent TLS Configuration**
```hcl ```hcl
verify_incoming = false tls {
verify_outgoing = true defaults {
verify_server_hostname = true 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 { auto_encrypt {
tls = true tls = true
} }
``` ```
-> The client agent TLS configuration from above sets [`verify_incoming`](/docs/agent/options#verify_incoming) to -> The client agent TLS configuration from above sets [`verify_incoming`](/docs/agent/options#tls_defaults_verify_incoming)
false which assumes all incoming traffic is restricted to `localhost`. The primary benefit for this configuration 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 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 using the local Consul agent. In this case ACLs should be enabled to provide authorization and only ACL tokens would
need to be distributed. 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 - **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. 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. 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_cipher_suites`](/docs/agent/options#tls_defaults_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.
- **Customize HTTP Response Headers** - Additional security headers, such as - **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 [`X-XSS-Protection`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection), can be