Skip to content

Commit 9e89ec3

Browse files
[FIXED] Gateway: TLS configuration reload now applies to implicit remotes (#6886)
When a config reload is issued and a server has implicit remote gateways (that is, gateways that were gossiped and not explicitly configured), the TLS changes were applied only to explicit remotes. With this change, the changes to the main `tls{}` block will be applied to implicit remotes. Credit to @song0071000 for the proposed changes in the code. Resolves #6875 Signed-off-by: Ivan Kozlovic <ivan@synadia.com>
2 parents 7941ee6 + 4aa328f commit 9e89ec3

File tree

2 files changed

+95
-26
lines changed

2 files changed

+95
-26
lines changed

server/gateway.go

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -424,38 +424,48 @@ func (s *Server) newGateway(opts *Options) error {
424424
func (g *srvGateway) updateRemotesTLSConfig(opts *Options) {
425425
g.Lock()
426426
defer g.Unlock()
427-
428-
for _, ro := range opts.Gateway.Gateways {
429-
if ro.Name == g.name {
427+
// Instead of going over opts.Gateway.Gateways, which would include only
428+
// explicit remotes, we are going to go through g.remotes.
429+
for name, cfg := range g.remotes {
430+
if name == g.name {
430431
continue
431432
}
432-
if cfg, ok := g.remotes[ro.Name]; ok {
433-
cfg.Lock()
434-
// If TLS config is in remote, use that one, otherwise,
435-
// use the TLS config from the main block.
436-
if ro.TLSConfig != nil {
437-
cfg.TLSConfig = ro.TLSConfig.Clone()
438-
} else if opts.Gateway.TLSConfig != nil {
439-
cfg.TLSConfig = opts.Gateway.TLSConfig.Clone()
433+
var ro *RemoteGatewayOpts
434+
// We now need to go back and find the RemoteGatewayOpts but only if
435+
// this remote is explicit (otherwise it won't be found).
436+
if !cfg.isImplicit() {
437+
for _, r := range opts.Gateway.Gateways {
438+
if r.Name == name {
439+
ro = r
440+
break
441+
}
440442
}
441-
442-
// Ensure that OCSP callbacks are always setup after a reload if needed.
443-
mustStaple := opts.OCSPConfig != nil && opts.OCSPConfig.Mode == OCSPModeAlways
444-
if mustStaple && opts.Gateway.TLSConfig != nil {
445-
clientCB := opts.Gateway.TLSConfig.GetClientCertificate
446-
verifyCB := opts.Gateway.TLSConfig.VerifyConnection
447-
if mustStaple && cfg.TLSConfig != nil {
448-
if clientCB != nil && cfg.TLSConfig.GetClientCertificate == nil {
449-
cfg.TLSConfig.GetClientCertificate = clientCB
450-
}
451-
if verifyCB != nil && cfg.TLSConfig.VerifyConnection == nil {
452-
cfg.TLSConfig.VerifyConnection = verifyCB
453-
}
443+
}
444+
cfg.Lock()
445+
// If we have an `ro` (that means an explicitly defined remote gateway)
446+
// and it has an explicit TLS config, use that one, otherwise (no explicit
447+
// TLS config in the remote, or implicit remote), use the TLS config from
448+
// the main block.
449+
if ro != nil && ro.TLSConfig != nil {
450+
cfg.TLSConfig = ro.TLSConfig.Clone()
451+
} else if opts.Gateway.TLSConfig != nil {
452+
cfg.TLSConfig = opts.Gateway.TLSConfig.Clone()
453+
}
454+
// Ensure that OCSP callbacks are always setup after a reload if needed.
455+
mustStaple := opts.OCSPConfig != nil && opts.OCSPConfig.Mode == OCSPModeAlways
456+
if mustStaple && opts.Gateway.TLSConfig != nil {
457+
clientCB := opts.Gateway.TLSConfig.GetClientCertificate
458+
verifyCB := opts.Gateway.TLSConfig.VerifyConnection
459+
if mustStaple && cfg.TLSConfig != nil {
460+
if clientCB != nil && cfg.TLSConfig.GetClientCertificate == nil {
461+
cfg.TLSConfig.GetClientCertificate = clientCB
462+
}
463+
if verifyCB != nil && cfg.TLSConfig.VerifyConnection == nil {
464+
cfg.TLSConfig.VerifyConnection = verifyCB
454465
}
455466
}
456-
457-
cfg.Unlock()
458467
}
468+
cfg.Unlock()
459469
}
460470
}
461471

server/gateway_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6458,6 +6458,65 @@ func TestGatewayTLSConfigReloadForRemote(t *testing.T) {
64586458
waitForOutboundGateways(t, srvB, 1, time.Second)
64596459
}
64606460

6461+
func TestGatewayTLSConfigReloadForImplicitRemote(t *testing.T) {
6462+
SetGatewaysSolicitDelay(5 * time.Millisecond)
6463+
defer ResetGatewaysSolicitDelay()
6464+
6465+
template := `
6466+
listen: 127.0.0.1:-1
6467+
gateway {
6468+
name: "A"
6469+
listen: "127.0.0.1:-1"
6470+
tls {
6471+
cert_file: "../test/configs/certs/srva-cert.pem"
6472+
key_file: "../test/configs/certs/srva-key.pem"
6473+
%s
6474+
verify: true
6475+
}
6476+
}
6477+
`
6478+
confA := createConfFile(t, fmt.Appendf(nil, template, `ca_file: "../test/configs/certs/ca.pem"`))
6479+
srvA, optsA := RunServerWithConfig(confA)
6480+
defer srvA.Shutdown()
6481+
6482+
optsB := testGatewayOptionsFromToWithTLS(t, "B", "A", []string{fmt.Sprintf("nats://127.0.0.1:%d", optsA.Gateway.Port)})
6483+
srvB := runGatewayServer(optsB)
6484+
defer srvB.Shutdown()
6485+
6486+
waitForInboundGateways(t, srvA, 1, time.Second)
6487+
waitForOutboundGateways(t, srvA, 1, time.Second)
6488+
waitForInboundGateways(t, srvB, 1, time.Second)
6489+
waitForOutboundGateways(t, srvB, 1, time.Second)
6490+
6491+
// We will verify that the config reload of the tls{} block is applied to
6492+
// the implicit remote (from A to B) by removing the ca_file.
6493+
reloadUpdateConfig(t, srvA, confA, fmt.Sprintf(template, ""))
6494+
6495+
// Get the remote from A to B
6496+
cfg := srvA.getRemoteGateway("B")
6497+
require_NotNil(t, cfg)
6498+
cfg.Lock()
6499+
tc := cfg.TLSConfig
6500+
cfg.Unlock()
6501+
require_NotNil(t, tc)
6502+
// The CA should have been removed.
6503+
require_True(t, tc.ClientCAs == nil)
6504+
6505+
// Reset the connection attempts, since we are going to close the connection
6506+
// from A to B and make sure that connection keeps failing.
6507+
cfg.resetConnAttempts()
6508+
6509+
// Get the outbound connection and close it.
6510+
c := srvA.getOutboundGatewayConnection("B")
6511+
require_NotNil(t, c)
6512+
c.mu.Lock()
6513+
c.nc.Close()
6514+
c.mu.Unlock()
6515+
6516+
// Verify that we fail to connect from A to B now.
6517+
waitForGatewayFailedConnect(t, srvA, "B", true, time.Second)
6518+
}
6519+
64616520
func TestGatewayAuthDiscovered(t *testing.T) {
64626521
SetGatewaysSolicitDelay(5 * time.Millisecond)
64636522
defer ResetGatewaysSolicitDelay()

0 commit comments

Comments
 (0)