Merge pull request #924 from nats-io/ignore_custom_auth_in_relaod

[FIXED] Allow use of custom auth with config reload
This commit is contained in:
Ivan Kozlovic
2019-03-21 10:46:01 -06:00
committed by GitHub
5 changed files with 56 additions and 38 deletions

View File

@@ -379,9 +379,6 @@ func (s *Server) gatewayAcceptLoop(ch chan struct{}) {
// Write resolved port back to options.
opts.Gateway.Port = l.Addr().(*net.TCPAddr).Port
}
// Keep track of actual listen port. This will be needed in case of
// config reload.
s.gatewayActualPort = opts.Gateway.Port
// Possibly override Host/Port based on Gateway.Advertise
if err := s.setGatewayInfoHostPort(info, opts); err != nil {
s.Fatalf("Error setting gateway INFO with Gateway.Advertise value of %s, err=%v", opts.Gateway.Advertise, err)

View File

@@ -28,6 +28,10 @@ import (
// startup. This should not be modified once the server has started.
var FlagSnapshot *Options
type reloadContext struct {
oldClusterPerms *RoutePermissions
}
// option is a hot-swappable configuration setting.
type option interface {
// Apply the server option.
@@ -511,14 +515,17 @@ func (s *Server) Reload() error {
return err
}
curOpts := s.getOpts()
// Wipe trusted keys if needed when we have an operator.
if len(s.opts.TrustedOperators) > 0 && len(s.opts.TrustedKeys) > 0 {
s.opts.TrustedKeys = nil
if len(curOpts.TrustedOperators) > 0 && len(curOpts.TrustedKeys) > 0 {
curOpts.TrustedKeys = nil
}
clientOrgPort := s.clientActualPort
clusterOrgPort := s.clusterActualPort
gatewayOrgPort := s.gatewayActualPort
clientOrgPort := curOpts.Port
clusterOrgPort := curOpts.Cluster.Port
gatewayOrgPort := curOpts.Gateway.Port
s.mu.Unlock()
// Apply flags over config file settings.
@@ -531,7 +538,7 @@ func (s *Server) Reload() error {
setBaselineOptions(newOpts)
// processOptions sets Port to 0 if set to -1 (RANDOM port)
// setBaselineOptions sets Port to 0 if set to -1 (RANDOM port)
// If that's the case, set it to the saved value when the accept loop was
// created.
if newOpts.Port == 0 {
@@ -545,7 +552,7 @@ func (s *Server) Reload() error {
newOpts.Gateway.Port = gatewayOrgPort
}
if err := s.reloadOptions(newOpts); err != nil {
if err := s.reloadOptions(curOpts, newOpts); err != nil {
return err
}
s.mu.Lock()
@@ -581,17 +588,22 @@ func applyBoolFlags(newOpts, flagOpts *Options) {
// reloadOptions reloads the server config with the provided options. If an
// option that doesn't support hot-swapping is changed, this returns an error.
func (s *Server) reloadOptions(newOpts *Options) error {
func (s *Server) reloadOptions(curOpts, newOpts *Options) error {
// Apply to the new options some of the options that may have been set
// that can't be configured in the config file (this can happen in
// applications starting NATS Server programmatically).
newOpts.CustomClientAuthentication = curOpts.CustomClientAuthentication
newOpts.CustomRouterAuthentication = curOpts.CustomRouterAuthentication
changed, err := s.diffOptions(newOpts)
if err != nil {
return err
}
s.mu.Lock()
// Need to save off previous cluster permissions
s.oldClusterPerms = s.opts.Cluster.Permissions
s.mu.Unlock()
// Create a context that is used to pass special info that we may need
// while applying the new options.
ctx := reloadContext{oldClusterPerms: curOpts.Cluster.Permissions}
s.setOpts(newOpts)
s.applyOptions(changed)
s.applyOptions(&ctx, changed)
return nil
}
@@ -730,7 +742,7 @@ func (s *Server) diffOptions(newOpts *Options) ([]option, error) {
return diffOpts, nil
}
func (s *Server) applyOptions(opts []option) {
func (s *Server) applyOptions(ctx *reloadContext, opts []option) {
var (
reloadLogging = false
reloadAuth = false
@@ -756,7 +768,7 @@ func (s *Server) applyOptions(opts []option) {
s.reloadAuthorization()
}
if reloadClusterPerms {
s.reloadClusterPermissions()
s.reloadClusterPermissions(ctx.oldClusterPerms)
}
s.Noticef("Reloaded server configuration")
@@ -889,17 +901,14 @@ func (s *Server) clientHasMovedToDifferentAccount(c *client) bool {
// update INFO protocol so that remote can resend their local
// subs if needed, and sending local subs matching cluster's
// import subjects.
func (s *Server) reloadClusterPermissions() {
func (s *Server) reloadClusterPermissions(oldPerms *RoutePermissions) {
s.mu.Lock()
var (
infoJSON []byte
oldPerms = s.oldClusterPerms
newPerms = s.opts.Cluster.Permissions
routes = make(map[uint64]*client, len(s.routes))
withNewProto int
)
// We can clear this now that we have captured it with oldPerms.
s.oldClusterPerms = nil
// Get all connected routes
for i, route := range s.routes {
// Count the number of routes that can understand receiving INFO updates.

View File

@@ -3203,6 +3203,8 @@ func TestConfigReloadNotPreventedByGateways(t *testing.T) {
}
func TestConfigReloadBoolFlags(t *testing.T) {
defer func() { FlagSnapshot = nil }()
logfile := "logtime.log"
defer os.Remove(logfile)
template := `
@@ -3638,3 +3640,29 @@ func TestConfigReloadMaxControlLineWithClients(t *testing.T) {
mcl, opts.MaxControlLine)
}
}
type testCustomAuth struct{}
func (ca *testCustomAuth) Check(c ClientAuthentication) bool { return true }
func TestConfigReloadIgnoreCustomAuth(t *testing.T) {
conf := createConfFile(t, []byte(`
port: -1
`))
opts := LoadConfig(conf)
ca := &testCustomAuth{}
opts.CustomClientAuthentication = ca
opts.CustomRouterAuthentication = ca
s := RunServer(opts)
defer s.Shutdown()
if err := s.Reload(); err != nil {
t.Fatalf("Error during reload: %v", err)
}
if s.getOpts().CustomClientAuthentication != ca || s.getOpts().CustomRouterAuthentication != ca {
t.Fatalf("Custom auth missing")
}
}

View File

@@ -1418,9 +1418,6 @@ func (s *Server) routeAcceptLoop(ch chan struct{}) {
// Write resolved port back to options.
opts.Cluster.Port = l.Addr().(*net.TCPAddr).Port
}
// Keep track of actual listen port. This will be needed in case of
// config reload.
s.clusterActualPort = opts.Cluster.Port
// Check for Auth items
if opts.Cluster.Username != "" {
info.AuthRequired = true

View File

@@ -143,16 +143,6 @@ type Server struct {
gatewayListener net.Listener // Accept listener
gateway *srvGateway
// These store the real client/cluster listen ports. They are
// required during config reload to reset the Options (after
// reload) to the actual listen port values.
clientActualPort int
clusterActualPort int
gatewayActualPort int
// Use during reload
oldClusterPerms *RoutePermissions
// Used by tests to check that http.Servers do
// not set any timeout.
monitoringServer *http.Server
@@ -1090,9 +1080,6 @@ func (s *Server) AcceptLoop(clr chan struct{}) {
// Write resolved port back to options.
opts.Port = l.Addr().(*net.TCPAddr).Port
}
// Keep track of actual listen port. This will be needed in case of
// config reload.
s.clientActualPort = opts.Port
// Now that port has been set (if it was set to RANDOM), set the
// server's info Host/Port with either values from Options or