mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-17 11:24:44 -07:00
Add a no_auth_user
This configuration allows to refer to a configured user to be used when the connection provides no credentials. Signed-off-by: Matthias Hanel <mh@synadia.com>
This commit is contained in:
@@ -16,6 +16,7 @@ package server
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -383,11 +384,19 @@ func (s *Server) processClientOrLeafAuthentication(c *client) bool {
|
||||
// Already checked that the client didn't send a user in connect
|
||||
// but we set it here to be able to identify it in the logs.
|
||||
c.opts.Username = euser
|
||||
} else if c.opts.Username != "" {
|
||||
user, ok = s.users[c.opts.Username]
|
||||
if !ok {
|
||||
s.mu.Unlock()
|
||||
return false
|
||||
} else {
|
||||
if c.kind == CLIENT && c.opts.Username == "" && s.opts.NoAuthUser != "" {
|
||||
if u, exists := s.users[s.opts.NoAuthUser]; exists {
|
||||
c.opts.Username = u.Username
|
||||
c.opts.Password = u.Password
|
||||
}
|
||||
}
|
||||
if c.opts.Username != "" {
|
||||
user, ok = s.users[c.opts.Username]
|
||||
if !ok {
|
||||
s.mu.Unlock()
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -693,3 +702,23 @@ func comparePasswords(serverPassword, clientPassword string) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func validateAuth(o *Options) error {
|
||||
if o.NoAuthUser == "" {
|
||||
return nil
|
||||
}
|
||||
if len(o.TrustedOperators) > 0 {
|
||||
return fmt.Errorf("no_auth_user not compatible with Trusted Operator")
|
||||
}
|
||||
if o.Users == nil {
|
||||
return fmt.Errorf(`no_auth_user: "%s" present, but users are not defined`, o.NoAuthUser)
|
||||
}
|
||||
for _, u := range o.Users {
|
||||
if u.Username == o.NoAuthUser {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf(
|
||||
`no_auth_user: "%s" not present as user in authorization block or account configuration`,
|
||||
o.NoAuthUser)
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@ type Options struct {
|
||||
Nkeys []*NkeyUser `json:"-"`
|
||||
Users []*User `json:"-"`
|
||||
Accounts []*Account `json:"-"`
|
||||
NoAuthUser string `json:"-"`
|
||||
SystemAccount string `json:"-"`
|
||||
AllowNewAccounts bool `json:"-"`
|
||||
Username string `json:"-"`
|
||||
@@ -783,6 +784,8 @@ func (o *Options) processConfigFileLine(k string, v interface{}, errors *[]error
|
||||
o.resolverPreloads[key] = jwtstr
|
||||
}
|
||||
}
|
||||
case "no_auth_user":
|
||||
o.NoAuthUser = v.(string)
|
||||
case "system_account", "system":
|
||||
// Already processed at the beginning so we just skip them
|
||||
// to not treat them as unknown values.
|
||||
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
func checkOptionsEqual(t *testing.T, golden, opts *Options) {
|
||||
@@ -2460,3 +2462,70 @@ func TestExpandPath(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoAuthUserCode(t *testing.T) {
|
||||
confFileName := createConfFile(t, []byte(`
|
||||
listen: "127.0.0.1:-1"
|
||||
no_auth_user: $NO_AUTH_USER
|
||||
|
||||
accounts {
|
||||
synadia {
|
||||
users [
|
||||
{user: "a", password: "a"},
|
||||
{nkey : UBAAQWTW6CG2G6ANGNKB5U2B7HRWHSGMZEZX3AQSAJOQDAUGJD46LD2E},
|
||||
]
|
||||
}
|
||||
acc {
|
||||
users [
|
||||
{user: "c", password: "c"}
|
||||
]
|
||||
}
|
||||
}
|
||||
# config for $G
|
||||
authorization {
|
||||
users [
|
||||
{user: "b", password: "b"}
|
||||
]
|
||||
}
|
||||
`))
|
||||
defer os.Remove(confFileName)
|
||||
defer os.Unsetenv("NO_AUTH_USER")
|
||||
|
||||
for _, user := range []string{"a", "b", "b"} {
|
||||
t.Run(user, func(t *testing.T) {
|
||||
os.Setenv("NO_AUTH_USER", user)
|
||||
opts, err := ProcessConfigFile(confFileName)
|
||||
if err != nil {
|
||||
t.Fatalf("Received unexpected error %s", err)
|
||||
} else {
|
||||
srv := RunServer(opts)
|
||||
nc, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", opts.Port))
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't connect %s", err)
|
||||
}
|
||||
nc.Close()
|
||||
srv.Shutdown()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for _, badUser := range []string{"notthere", "UBAAQWTW6CG2G6ANGNKB5U2B7HRWHSGMZEZX3AQSAJOQDAUGJD46LD2E"} {
|
||||
t.Run(badUser, func(t *testing.T) {
|
||||
os.Setenv("NO_AUTH_USER", badUser)
|
||||
opts, err := ProcessConfigFile(confFileName)
|
||||
if err != nil {
|
||||
t.Fatalf("Received unexpected error %s", err)
|
||||
}
|
||||
s, err := NewServer(opts)
|
||||
if err != nil {
|
||||
if !strings.HasPrefix(err.Error(), "no_auth_user") {
|
||||
t.Fatalf("Received unexpected error %s", err)
|
||||
}
|
||||
return // error looks as expected
|
||||
}
|
||||
s.Shutdown()
|
||||
t.Fatalf("Received no error, where no_auth_user error was expected")
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -410,8 +410,10 @@ func validateOptions(o *Options) error {
|
||||
if err := validateLeafNode(o); err != nil {
|
||||
return err
|
||||
}
|
||||
// Check that gateway is properly configured. Returns no error
|
||||
// if there is no gateway defined.
|
||||
// Check that authentication is properly configured.
|
||||
if err := validateAuth(o); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateGatewayOptions(o)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user