-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow TLS configurations for HTTP and RPC connections to be reloaded … #4025
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -777,14 +777,34 @@ func (a *Agent) Stats() map[string]map[string]string { | |
|
||
// ShouldReload determines if we should reload the configuration and agent | ||
// connections. If the TLS Configuration has not changed, we shouldn't reload. | ||
func (a *Agent) ShouldReload(newConfig *Config) (bool, bool) { | ||
func (a *Agent) ShouldReload(newConfig *Config) (bool, bool, bool) { | ||
var shouldReloadAgent, shouldReloadHTTP, shouldReloadRPC bool | ||
|
||
a.configLock.Lock() | ||
defer a.configLock.Unlock() | ||
if a.config.TLSConfig.Equals(newConfig.TLSConfig) { | ||
return false, false | ||
|
||
var tlsInfoChanged bool | ||
if !a.config.TLSConfig.CertificateInfoIsEqual(newConfig.TLSConfig) { | ||
tlsInfoChanged = true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be easier to |
||
} | ||
|
||
// Allow the ability to only reload HTTP connections | ||
if a.config.TLSConfig.EnableHTTP != newConfig.TLSConfig.EnableHTTP || tlsInfoChanged { | ||
shouldReloadHTTP = true | ||
} | ||
|
||
// Allow the ability to only reload HTTP connections | ||
if a.config.TLSConfig.EnableRPC != newConfig.TLSConfig.EnableRPC || tlsInfoChanged { | ||
shouldReloadRPC = true | ||
} | ||
|
||
// Always reload the agent if either HTTP or RPC connections need to reload, | ||
// or if the TLS configuration itself has changed | ||
if shouldReloadHTTP || shouldReloadRPC || tlsInfoChanged { | ||
shouldReloadAgent = true | ||
} | ||
|
||
return true, true // requires a reload of both agent and http server | ||
return shouldReloadAgent, shouldReloadHTTP, shouldReloadRPC | ||
} | ||
|
||
// Reload handles configuration changes for the agent. Provides a method that | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -771,9 +771,104 @@ func TestServer_ShouldReload_ReturnFalseForNoChanges(t *testing.T) { | |
config: agentConfig, | ||
} | ||
|
||
shouldReloadAgent, shouldReloadHTTPServer := agent.ShouldReload(sameAgentConfig) | ||
shouldReloadAgent, shouldReloadHTTP, shouldReloadRPC := agent.ShouldReload(sameAgentConfig) | ||
assert.False(shouldReloadAgent) | ||
assert.False(shouldReloadHTTPServer) | ||
assert.False(shouldReloadHTTP) | ||
assert.False(shouldReloadRPC) | ||
} | ||
|
||
func TestServer_ShouldReload_ReturnTrueForOnlyHTTPChanges(t *testing.T) { | ||
t.Parallel() | ||
assert := assert.New(t) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use require |
||
|
||
const ( | ||
cafile = "../../helper/tlsutil/testdata/ca.pem" | ||
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" | ||
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" | ||
) | ||
dir := tmpDir(t) | ||
defer os.RemoveAll(dir) | ||
|
||
logger := log.New(ioutil.Discard, "", 0) | ||
|
||
agentConfig := &Config{ | ||
TLSConfig: &sconfig.TLSConfig{ | ||
EnableHTTP: false, | ||
EnableRPC: true, | ||
VerifyServerHostname: true, | ||
CAFile: cafile, | ||
CertFile: foocert, | ||
KeyFile: fookey, | ||
}, | ||
} | ||
|
||
sameAgentConfig := &Config{ | ||
TLSConfig: &sconfig.TLSConfig{ | ||
EnableHTTP: true, | ||
EnableRPC: true, | ||
VerifyServerHostname: true, | ||
CAFile: cafile, | ||
CertFile: foocert, | ||
KeyFile: fookey, | ||
}, | ||
} | ||
|
||
agent := &Agent{ | ||
logger: logger, | ||
config: agentConfig, | ||
} | ||
|
||
shouldReloadAgent, shouldReloadHTTP, shouldReloadRPC := agent.ShouldReload(sameAgentConfig) | ||
assert.True(shouldReloadAgent) | ||
assert.True(shouldReloadHTTP) | ||
assert.False(shouldReloadRPC) | ||
} | ||
|
||
func TestServer_ShouldReload_ReturnTrueForOnlyRPCChanges(t *testing.T) { | ||
t.Parallel() | ||
assert := assert.New(t) | ||
|
||
const ( | ||
cafile = "../../helper/tlsutil/testdata/ca.pem" | ||
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" | ||
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" | ||
) | ||
dir := tmpDir(t) | ||
defer os.RemoveAll(dir) | ||
|
||
logger := log.New(ioutil.Discard, "", 0) | ||
|
||
agentConfig := &Config{ | ||
TLSConfig: &sconfig.TLSConfig{ | ||
EnableHTTP: true, | ||
EnableRPC: false, | ||
VerifyServerHostname: true, | ||
CAFile: cafile, | ||
CertFile: foocert, | ||
KeyFile: fookey, | ||
}, | ||
} | ||
|
||
sameAgentConfig := &Config{ | ||
TLSConfig: &sconfig.TLSConfig{ | ||
EnableHTTP: true, | ||
EnableRPC: true, | ||
VerifyServerHostname: true, | ||
CAFile: cafile, | ||
CertFile: foocert, | ||
KeyFile: fookey, | ||
}, | ||
} | ||
|
||
agent := &Agent{ | ||
logger: logger, | ||
config: agentConfig, | ||
} | ||
|
||
shouldReloadAgent, shouldReloadHTTP, shouldReloadRPC := agent.ShouldReload(sameAgentConfig) | ||
assert.True(shouldReloadAgent) | ||
assert.False(shouldReloadHTTP) | ||
assert.True(shouldReloadRPC) | ||
} | ||
|
||
func TestServer_ShouldReload_ReturnTrueForConfigChanges(t *testing.T) { | ||
|
@@ -819,7 +914,8 @@ func TestServer_ShouldReload_ReturnTrueForConfigChanges(t *testing.T) { | |
config: agentConfig, | ||
} | ||
|
||
shouldReloadAgent, shouldReloadHTTPServer := agent.ShouldReload(newConfig) | ||
shouldReloadAgent, shouldReloadHTTP, shouldReloadRPC := agent.ShouldReload(newConfig) | ||
assert.True(shouldReloadAgent) | ||
assert.True(shouldReloadHTTPServer) | ||
assert.True(shouldReloadHTTP) | ||
assert.True(shouldReloadRPC) | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -271,7 +271,7 @@ func TestServer_Reload_TLSConnections_PlaintextToTLS(t *testing.T) { | |||||||||||||||||||||
|
||||||||||||||||||||||
err := s1.reloadTLSConnections(newTLSConfig) | ||||||||||||||||||||||
assert.Nil(err) | ||||||||||||||||||||||
assert.True(s1.config.TLSConfig.Equals(newTLSConfig)) | ||||||||||||||||||||||
assert.True(s1.config.TLSConfig.CertificateInfoIsEqual(newTLSConfig)) | ||||||||||||||||||||||
|
||||||||||||||||||||||
codec := rpcClient(t, s1) | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
@@ -319,7 +319,61 @@ func TestServer_Reload_TLSConnections_TLSToPlaintext_RPC(t *testing.T) { | |||||||||||||||||||||
|
||||||||||||||||||||||
err := s1.reloadTLSConnections(newTLSConfig) | ||||||||||||||||||||||
assert.Nil(err) | ||||||||||||||||||||||
assert.True(s1.config.TLSConfig.Equals(newTLSConfig)) | ||||||||||||||||||||||
assert.True(s1.config.TLSConfig.CertificateInfoIsEqual(newTLSConfig)) | ||||||||||||||||||||||
|
||||||||||||||||||||||
codec := rpcClient(t, s1) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This won't actually use TLS: Lines 27 to 36 in 40db0af
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You may want to add a new helper that takes a tls config and then returns a client codec. You would have to write the TLS mode first:
You can remove the new code and put a TODO for yourself, and create a follow up PR |
||||||||||||||||||||||
|
||||||||||||||||||||||
node := mock.Node() | ||||||||||||||||||||||
req := &structs.NodeRegisterRequest{ | ||||||||||||||||||||||
Node: node, | ||||||||||||||||||||||
WriteRequest: structs.WriteRequest{Region: "global"}, | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
var resp structs.GenericResponse | ||||||||||||||||||||||
err = msgpackrpc.CallWithCodec(codec, "Node.Register", req, &resp) | ||||||||||||||||||||||
assert.Nil(err) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Tests that the server will successfully reload its network connections, | ||||||||||||||||||||||
// downgrading only RPC connections | ||||||||||||||||||||||
func TestServer_Reload_TLSConnections_TLSToPlaintext_OnlyRPC(t *testing.T) { | ||||||||||||||||||||||
t.Parallel() | ||||||||||||||||||||||
assert := assert.New(t) | ||||||||||||||||||||||
|
||||||||||||||||||||||
const ( | ||||||||||||||||||||||
cafile = "../helper/tlsutil/testdata/ca.pem" | ||||||||||||||||||||||
foocert = "../helper/tlsutil/testdata/nomad-foo.pem" | ||||||||||||||||||||||
fookey = "../helper/tlsutil/testdata/nomad-foo-key.pem" | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
dir := tmpDir(t) | ||||||||||||||||||||||
defer os.RemoveAll(dir) | ||||||||||||||||||||||
|
||||||||||||||||||||||
s1 := TestServer(t, func(c *Config) { | ||||||||||||||||||||||
c.DataDir = path.Join(dir, "nodeB") | ||||||||||||||||||||||
c.TLSConfig = &config.TLSConfig{ | ||||||||||||||||||||||
EnableHTTP: true, | ||||||||||||||||||||||
EnableRPC: true, | ||||||||||||||||||||||
VerifyServerHostname: true, | ||||||||||||||||||||||
CAFile: cafile, | ||||||||||||||||||||||
CertFile: foocert, | ||||||||||||||||||||||
KeyFile: fookey, | ||||||||||||||||||||||
} | ||||||||||||||||||||||
}) | ||||||||||||||||||||||
defer s1.Shutdown() | ||||||||||||||||||||||
|
||||||||||||||||||||||
newTLSConfig := &config.TLSConfig{ | ||||||||||||||||||||||
EnableHTTP: true, | ||||||||||||||||||||||
EnableRPC: false, | ||||||||||||||||||||||
VerifyServerHostname: true, | ||||||||||||||||||||||
CAFile: cafile, | ||||||||||||||||||||||
CertFile: foocert, | ||||||||||||||||||||||
KeyFile: fookey, | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
err := s1.reloadTLSConnections(newTLSConfig) | ||||||||||||||||||||||
assert.Nil(err) | ||||||||||||||||||||||
assert.True(s1.config.TLSConfig.CertificateInfoIsEqual(newTLSConfig)) | ||||||||||||||||||||||
|
||||||||||||||||||||||
codec := rpcClient(t, s1) | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add named returns? Will help readability: