forked from mirror/redis
Add AuthACL
This commit is contained in:
parent
64bb0b7f3a
commit
cf6cf7f450
|
@ -57,6 +57,7 @@ type ClusterOptions struct {
|
|||
|
||||
OnConnect func(*Conn) error
|
||||
|
||||
Username string
|
||||
Password string
|
||||
|
||||
MaxRetries int
|
||||
|
@ -130,6 +131,7 @@ func (opt *ClusterOptions) clientOptions() *Options {
|
|||
MaxRetries: opt.MaxRetries,
|
||||
MinRetryBackoff: opt.MinRetryBackoff,
|
||||
MaxRetryBackoff: opt.MaxRetryBackoff,
|
||||
Username: opt.Username,
|
||||
Password: opt.Password,
|
||||
readOnly: opt.ReadOnly,
|
||||
|
||||
|
|
10
commands.go
10
commands.go
|
@ -302,6 +302,7 @@ type Cmdable interface {
|
|||
type StatefulCmdable interface {
|
||||
Cmdable
|
||||
Auth(password string) *StatusCmd
|
||||
AuthACL(username, password string) *StatusCmd
|
||||
Select(index int) *StatusCmd
|
||||
SwapDB(index1, index2 int) *StatusCmd
|
||||
ClientSetName(name string) *BoolCmd
|
||||
|
@ -324,6 +325,15 @@ func (c statefulCmdable) Auth(password string) *StatusCmd {
|
|||
return cmd
|
||||
}
|
||||
|
||||
// Perform an AUTH command, using the given user and pass.
|
||||
// Should be used to authenticate the current connection with one of the connections defined in the ACL list
|
||||
// when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
|
||||
func (c statefulCmdable) AuthACL(username, password string) *StatusCmd {
|
||||
cmd := NewStatusCmd("auth", username, password)
|
||||
_ = c(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c cmdable) Echo(message interface{}) *StringCmd {
|
||||
cmd := NewStringCmd("echo", message)
|
||||
_ = c(cmd)
|
||||
|
|
|
@ -40,8 +40,13 @@ type Options struct {
|
|||
// Hook that is called when new connection is established.
|
||||
OnConnect func(*Conn) error
|
||||
|
||||
// Use the specified Username to authenticate the current connection with one of the connections defined in the ACL
|
||||
// list when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
|
||||
Username string
|
||||
|
||||
// Optional password. Must match the password specified in the
|
||||
// requirepass server configuration option.
|
||||
// requirepass server configuration option (if connecting to a Redis 5.0 instance, or lower),
|
||||
// or the User Password when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
|
||||
Password string
|
||||
// Database to be selected after connecting to the server.
|
||||
DB int
|
||||
|
@ -187,6 +192,7 @@ func ParseURL(redisURL string) (*Options, error) {
|
|||
}
|
||||
|
||||
if u.User != nil {
|
||||
o.Username = u.User.Username()
|
||||
if p, ok := u.User.Password(); ok {
|
||||
o.Password = p
|
||||
}
|
||||
|
|
|
@ -15,56 +15,86 @@ func TestParseURL(t *testing.T) {
|
|||
db int
|
||||
tls bool
|
||||
err error
|
||||
user string
|
||||
pass string
|
||||
}{
|
||||
{
|
||||
"redis://localhost:123/1",
|
||||
"localhost:123",
|
||||
1, false, nil,
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"redis://localhost:123",
|
||||
"localhost:123",
|
||||
0, false, nil,
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"redis://localhost/1",
|
||||
"localhost:6379",
|
||||
1, false, nil,
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"redis://12345",
|
||||
"12345:6379",
|
||||
0, false, nil,
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"rediss://localhost:123",
|
||||
"localhost:123",
|
||||
0, true, nil,
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"redis://:bar@localhost:123",
|
||||
"localhost:123",
|
||||
0, false, nil,
|
||||
"", "bar",
|
||||
},
|
||||
{
|
||||
"redis://foo@localhost:123",
|
||||
"localhost:123",
|
||||
0, false, nil,
|
||||
"foo", "",
|
||||
},
|
||||
{
|
||||
"redis://foo:bar@localhost:123",
|
||||
"localhost:123",
|
||||
0, false, nil,
|
||||
"foo", "bar",
|
||||
},
|
||||
{
|
||||
"redis://localhost/?abc=123",
|
||||
"",
|
||||
0, false, errors.New("no options supported"),
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"http://google.com",
|
||||
"",
|
||||
0, false, errors.New("invalid redis URL scheme: http"),
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"redis://localhost/1/2/3/4",
|
||||
"",
|
||||
0, false, errors.New("invalid redis URL path: /1/2/3/4"),
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"12345",
|
||||
"",
|
||||
0, false, errors.New("invalid redis URL scheme: "),
|
||||
"", "",
|
||||
},
|
||||
{
|
||||
"redis://localhost/iamadatabase",
|
||||
"",
|
||||
0, false, errors.New(`invalid redis database number: "iamadatabase"`),
|
||||
"", "",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -90,6 +120,12 @@ func TestParseURL(t *testing.T) {
|
|||
if c.tls && o.TLSConfig == nil {
|
||||
t.Errorf("got nil TLSConfig, expected a TLSConfig")
|
||||
}
|
||||
if o.Username != c.user {
|
||||
t.Errorf("got %q, expected %q", o.Username, c.user)
|
||||
}
|
||||
if o.Password != c.pass {
|
||||
t.Errorf("got %q, expected %q", o.Password, c.pass)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
6
redis.go
6
redis.go
|
@ -241,7 +241,11 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
|
|||
|
||||
_, err := conn.Pipelined(func(pipe Pipeliner) error {
|
||||
if c.opt.Password != "" {
|
||||
pipe.Auth(c.opt.Password)
|
||||
if c.opt.Username != "" {
|
||||
pipe.AuthACL(c.opt.Username, c.opt.Password)
|
||||
} else {
|
||||
pipe.Auth(c.opt.Password)
|
||||
}
|
||||
}
|
||||
|
||||
if c.opt.DB > 0 {
|
||||
|
|
|
@ -22,6 +22,7 @@ type FailoverOptions struct {
|
|||
MasterName string
|
||||
// A seed list of host:port addresses of sentinel nodes.
|
||||
SentinelAddrs []string
|
||||
SentinelUsername string
|
||||
SentinelPassword string
|
||||
|
||||
// Following options are copied from Options struct.
|
||||
|
@ -29,6 +30,7 @@ type FailoverOptions struct {
|
|||
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
OnConnect func(*Conn) error
|
||||
|
||||
Username string
|
||||
Password string
|
||||
DB int
|
||||
|
||||
|
@ -57,6 +59,7 @@ func (opt *FailoverOptions) options() *Options {
|
|||
OnConnect: opt.OnConnect,
|
||||
|
||||
DB: opt.DB,
|
||||
Username: opt.Username,
|
||||
Password: opt.Password,
|
||||
|
||||
MaxRetries: opt.MaxRetries,
|
||||
|
@ -88,6 +91,7 @@ func NewFailoverClient(failoverOpt *FailoverOptions) *Client {
|
|||
failover := &sentinelFailover{
|
||||
masterName: failoverOpt.MasterName,
|
||||
sentinelAddrs: failoverOpt.SentinelAddrs,
|
||||
username: failoverOpt.SentinelUsername,
|
||||
password: failoverOpt.SentinelPassword,
|
||||
|
||||
opt: opt,
|
||||
|
@ -281,6 +285,7 @@ type sentinelFailover struct {
|
|||
sentinelAddrs []string
|
||||
|
||||
opt *Options
|
||||
username string
|
||||
password string
|
||||
|
||||
pool *pool.ConnPool
|
||||
|
@ -372,6 +377,7 @@ func (c *sentinelFailover) masterAddr() (string, error) {
|
|||
Addr: sentinelAddr,
|
||||
Dialer: c.opt.Dialer,
|
||||
|
||||
Username: c.username,
|
||||
Password: c.password,
|
||||
|
||||
MaxRetries: c.opt.MaxRetries,
|
||||
|
|
|
@ -22,6 +22,7 @@ type UniversalOptions struct {
|
|||
|
||||
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
OnConnect func(*Conn) error
|
||||
Username string
|
||||
Password string
|
||||
MaxRetries int
|
||||
MinRetryBackoff time.Duration
|
||||
|
@ -60,6 +61,7 @@ func (o *UniversalOptions) Cluster() *ClusterOptions {
|
|||
Dialer: o.Dialer,
|
||||
OnConnect: o.OnConnect,
|
||||
|
||||
Username: o.Username,
|
||||
Password: o.Password,
|
||||
|
||||
MaxRedirects: o.MaxRedirects,
|
||||
|
@ -99,6 +101,7 @@ func (o *UniversalOptions) Failover() *FailoverOptions {
|
|||
OnConnect: o.OnConnect,
|
||||
|
||||
DB: o.DB,
|
||||
Username: o.Username,
|
||||
Password: o.Password,
|
||||
|
||||
MaxRetries: o.MaxRetries,
|
||||
|
@ -133,6 +136,7 @@ func (o *UniversalOptions) Simple() *Options {
|
|||
OnConnect: o.OnConnect,
|
||||
|
||||
DB: o.DB,
|
||||
Username: o.Username,
|
||||
Password: o.Password,
|
||||
|
||||
MaxRetries: o.MaxRetries,
|
||||
|
|
Loading…
Reference in New Issue