forked from mirror/redis
Merge pull request #1896 from jsievenpiper/main
feat: add acl auth support for sentinels
This commit is contained in:
commit
fddf086cbe
|
@ -23,7 +23,13 @@ type FailoverOptions struct {
|
||||||
MasterName string
|
MasterName string
|
||||||
// A seed list of host:port addresses of sentinel nodes.
|
// A seed list of host:port addresses of sentinel nodes.
|
||||||
SentinelAddrs []string
|
SentinelAddrs []string
|
||||||
// Sentinel password from "requirepass <password>" (if enabled) in Sentinel configuration
|
|
||||||
|
// If specified with SentinelPassword, enables ACL-based authentication (via
|
||||||
|
// AUTH <user> <pass>).
|
||||||
|
SentinelUsername string
|
||||||
|
// Sentinel password from "requirepass <password>" (if enabled) in Sentinel
|
||||||
|
// configuration, or, if SentinelUsername is also supplied, used for ACL-based
|
||||||
|
// authentication.
|
||||||
SentinelPassword string
|
SentinelPassword string
|
||||||
|
|
||||||
// Allows routing read-only commands to the closest master or slave node.
|
// Allows routing read-only commands to the closest master or slave node.
|
||||||
|
@ -109,6 +115,7 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options {
|
||||||
OnConnect: opt.OnConnect,
|
OnConnect: opt.OnConnect,
|
||||||
|
|
||||||
DB: 0,
|
DB: 0,
|
||||||
|
Username: opt.SentinelUsername,
|
||||||
Password: opt.SentinelPassword,
|
Password: opt.SentinelPassword,
|
||||||
|
|
||||||
MaxRetries: opt.MaxRetries,
|
MaxRetries: opt.MaxRetries,
|
||||||
|
|
|
@ -212,3 +212,76 @@ var _ = Describe("NewFailoverClusterClient", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var _ = Describe("SentinelAclAuth", func() {
|
||||||
|
const (
|
||||||
|
aclSentinelUsername = "sentinel-user"
|
||||||
|
aclSentinelPassword = "sentinel-pass"
|
||||||
|
)
|
||||||
|
|
||||||
|
var client *redis.Client
|
||||||
|
var sentinel *redis.SentinelClient
|
||||||
|
var sentinels = func() []*redisProcess {
|
||||||
|
return []*redisProcess{ sentinel1, sentinel2, sentinel3 }
|
||||||
|
}
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
authCmd := redis.NewStatusCmd(ctx, "ACL", "SETUSER", aclSentinelUsername, "ON",
|
||||||
|
">" + aclSentinelPassword, "-@all", "+auth", "+client|getname", "+client|id", "+client|setname",
|
||||||
|
"+command", "+hello", "+ping", "+role", "+sentinel|get-master-addr-by-name", "+sentinel|master",
|
||||||
|
"+sentinel|myid", "+sentinel|replicas", "+sentinel|sentinels")
|
||||||
|
|
||||||
|
for _, process := range sentinels() {
|
||||||
|
err := process.Client.Process(ctx, authCmd)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
client = redis.NewFailoverClient(&redis.FailoverOptions{
|
||||||
|
MasterName: sentinelName,
|
||||||
|
SentinelAddrs: sentinelAddrs,
|
||||||
|
MaxRetries: -1,
|
||||||
|
SentinelUsername: aclSentinelUsername,
|
||||||
|
SentinelPassword: aclSentinelPassword,
|
||||||
|
})
|
||||||
|
|
||||||
|
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
sentinel = redis.NewSentinelClient(&redis.Options{
|
||||||
|
Addr: sentinelAddrs[0],
|
||||||
|
MaxRetries: -1,
|
||||||
|
Username: aclSentinelUsername,
|
||||||
|
Password: aclSentinelPassword,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err := sentinel.GetMasterAddrByName(ctx, sentinelName).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Wait until sentinels are picked up by each other.
|
||||||
|
for _, process := range sentinels() {
|
||||||
|
Eventually(func() string {
|
||||||
|
return process.Info(ctx).Val()
|
||||||
|
}, "15s", "100ms").Should(ContainSubstring("sentinels=3"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
unauthCommand := redis.NewStatusCmd(ctx, "ACL", "DELUSER", aclSentinelUsername)
|
||||||
|
|
||||||
|
for _, process := range sentinels() {
|
||||||
|
err := process.Client.Process(ctx, unauthCommand)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = client.Close()
|
||||||
|
_ = sentinel.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should still facilitate operations", func() {
|
||||||
|
err := client.Set(ctx, "wow", "acl-auth", 0).Err()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
val, err := client.Get(ctx, "wow").Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(val).To(Equal("acl-auth"))
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue