mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
[FIXED] Clients disconnected on reload when only $SYS account configured
This was introduced by PR#1900 by detecting that a single system account was configured. A "fake" user name was created and added to the list of users and set as a no_auth_user. However, on config reload, a new fake user was created, which would cause existing connected clients to be disconnected. Resolves #2282 Signed-off-by: Ivan Kozlovic <ivan@synadia.com>
This commit is contained in:
@@ -4522,3 +4522,39 @@ func TestConfigReloadAccountMappings(t *testing.T) {
|
||||
checkPending(fsub, 1)
|
||||
checkPending(sub, 0)
|
||||
}
|
||||
|
||||
func TestConfigReloadWithSysAccountOnly(t *testing.T) {
|
||||
conf := createConfFile(t, []byte(`
|
||||
listen: "127.0.0.1:-1"
|
||||
accounts {
|
||||
$SYS {
|
||||
users = [{user: "system",pass: "password"}, {user: "system2",pass: "password2"}]
|
||||
}
|
||||
}
|
||||
`))
|
||||
defer os.Remove(conf)
|
||||
s, _ := RunServerWithConfig(conf)
|
||||
defer s.Shutdown()
|
||||
|
||||
dch := make(chan struct{}, 1)
|
||||
nc := natsConnect(t,
|
||||
s.ClientURL(),
|
||||
nats.DisconnectErrHandler(func(_ *nats.Conn, _ error) {
|
||||
dch <- struct{}{}
|
||||
}),
|
||||
nats.NoCallbacksAfterClientClose())
|
||||
defer nc.Close()
|
||||
|
||||
// Just reload...
|
||||
if err := s.Reload(); err != nil {
|
||||
t.Fatalf("Error on reload: %v", err)
|
||||
}
|
||||
|
||||
// Make sure we did not get disconnected
|
||||
select {
|
||||
case <-dch:
|
||||
t.Fatal("Got disconnected!")
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,6 +256,11 @@ type Server struct {
|
||||
// For out of resources to not log errors too fast.
|
||||
rerrMu sync.Mutex
|
||||
rerrLast time.Time
|
||||
|
||||
// If there is a system account configured, to still support the $G account,
|
||||
// the server will create a fake user and add it to the list of users.
|
||||
// Keep track of what that user name is for config reload purposes.
|
||||
sysAccOnlyNoAuthUser string
|
||||
}
|
||||
|
||||
type nodeInfo struct {
|
||||
@@ -756,15 +761,21 @@ func (s *Server) configureAccounts() error {
|
||||
// We would do this to add user/pass to the system account. If this is the case add in
|
||||
// no-auth-user for $G.
|
||||
if numAccounts == 2 && s.opts.NoAuthUser == _EMPTY_ {
|
||||
// Create a unique name so we do not collide.
|
||||
var b [8]byte
|
||||
rn := rand.Int63()
|
||||
for i, l := 0, rn; i < len(b); i++ {
|
||||
b[i] = digits[l%base]
|
||||
l /= base
|
||||
// If we come here from config reload, let's not recreate the fake user name otherwise
|
||||
// it will cause currently clients to be disconnected.
|
||||
uname := s.sysAccOnlyNoAuthUser
|
||||
if uname == _EMPTY_ {
|
||||
// Create a unique name so we do not collide.
|
||||
var b [8]byte
|
||||
rn := rand.Int63()
|
||||
for i, l := 0, rn; i < len(b); i++ {
|
||||
b[i] = digits[l%base]
|
||||
l /= base
|
||||
}
|
||||
uname = fmt.Sprintf("nats-%s", b[:])
|
||||
s.sysAccOnlyNoAuthUser = uname
|
||||
}
|
||||
uname := fmt.Sprintf("nats-%s", b[:])
|
||||
s.opts.Users = append(s.opts.Users, &User{Username: uname, Password: string(b[:]), Account: s.gacc})
|
||||
s.opts.Users = append(s.opts.Users, &User{Username: uname, Password: uname[6:], Account: s.gacc})
|
||||
s.opts.NoAuthUser = uname
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user