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:
parent
27711fe5c7
commit
57f0f42733
|
@ -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
|
||||||
|
```
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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"`
|
||||||
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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": []
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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:])
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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`
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue