Skip to content

Commit f66582f

Browse files
committed
feat: add acl auth support for sentinels
1 parent 7c92957 commit f66582f

File tree

3 files changed

+114
-2
lines changed

3 files changed

+114
-2
lines changed

main_test.go

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,27 @@ const (
4040
sentinelPort3 = "9128"
4141
)
4242

43+
const (
44+
aclSentinelUsername = "sentinel-user"
45+
aclSentinelPassword = "sentinel-pass"
46+
aclSentinelName = "my_server"
47+
aclServerPort = "10001"
48+
aclSentinelPort1 = "10002"
49+
aclSentinelPort2 = "10003"
50+
aclSentinelPort3 = "10004"
51+
)
52+
4353
var (
4454
sentinelAddrs = []string{":" + sentinelPort1, ":" + sentinelPort2, ":" + sentinelPort3}
55+
aclSentinelAddrs = []string {":" + aclSentinelPort1, ":" + aclSentinelPort2, ":" + aclSentinelPort3}
4556

4657
processes map[string]*redisProcess
4758

48-
redisMain *redisProcess
59+
redisMain, aclServer *redisProcess
4960
ringShard1, ringShard2, ringShard3 *redisProcess
5061
sentinelMaster, sentinelSlave1, sentinelSlave2 *redisProcess
5162
sentinel1, sentinel2, sentinel3 *redisProcess
63+
aclSentinel1, aclSentinel2, aclSentinel3 *redisProcess
5264
)
5365

5466
var cluster = &clusterScenario{
@@ -101,6 +113,18 @@ var _ = BeforeSuite(func() {
101113
Expect(err).NotTo(HaveOccurred())
102114

103115
Expect(startCluster(ctx, cluster)).NotTo(HaveOccurred())
116+
117+
aclServer, err = startRedis(aclServerPort)
118+
Expect(err).NotTo(HaveOccurred())
119+
120+
aclSentinel1, err = startSentinelWithAcl(aclSentinelPort1, aclSentinelName, aclServerPort)
121+
Expect(err).NotTo(HaveOccurred())
122+
123+
aclSentinel2, err = startSentinelWithAcl(aclSentinelPort2, aclSentinelName, aclServerPort)
124+
Expect(err).NotTo(HaveOccurred())
125+
126+
aclSentinel3, err = startSentinelWithAcl(aclSentinelPort3, aclSentinelName, aclServerPort)
127+
Expect(err).NotTo(HaveOccurred())
104128
})
105129

106130
var _ = AfterSuite(func() {
@@ -364,6 +388,28 @@ func startSentinel(port, masterName, masterPort string) (*redisProcess, error) {
364388
return p, nil
365389
}
366390

391+
func startSentinelWithAcl(port, masterName, masterPort string) (*redisProcess, error) {
392+
process, err := startSentinel(port, masterName, masterPort)
393+
if err != nil {
394+
return nil, err
395+
}
396+
397+
for _, cmd := range []*redis.StatusCmd{
398+
redis.NewStatusCmd(ctx, "ACL", "SETUSER", aclSentinelUsername, "ON", ">" + aclSentinelPassword, "-@all",
399+
"+auth", "+client|getname", "+client|id", "+client|setname", "+command", "+hello", "+ping", "+role",
400+
"+sentinel|get-master-addr-by-name", "+sentinel|master", "+sentinel|myid", "+sentinel|replicas",
401+
"+sentinel|sentinels"),
402+
} {
403+
process.Client.Process(ctx, cmd)
404+
if err := cmd.Err(); err != nil {
405+
process.Kill()
406+
return nil, err
407+
}
408+
}
409+
410+
return process, nil
411+
}
412+
367413
//------------------------------------------------------------------------------
368414

369415
type badConnError string

sentinel.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ type FailoverOptions struct {
2323
MasterName string
2424
// A seed list of host:port addresses of sentinel nodes.
2525
SentinelAddrs []string
26-
// Sentinel password from "requirepass <password>" (if enabled) in Sentinel configuration
26+
27+
// If specified with SentinelPassword, enables ACL-based authentication (via
28+
// AUTH <user> <pass>).
29+
SentinelUsername string
30+
// Sentinel password from "requirepass <password>" (if enabled) in Sentinel
31+
// configuration, or, if SentinelUsername is also supplied, used for ACL-based
32+
// authentication.
2733
SentinelPassword string
2834

2935
// Allows routing read-only commands to the closest master or slave node.
@@ -109,6 +115,7 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options {
109115
OnConnect: opt.OnConnect,
110116

111117
DB: 0,
118+
Username: opt.SentinelUsername,
112119
Password: opt.SentinelPassword,
113120

114121
MaxRetries: opt.MaxRetries,

sentinel_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,62 @@ var _ = Describe("NewFailoverClusterClient", func() {
212212
Expect(err).NotTo(HaveOccurred())
213213
})
214214
})
215+
216+
var _ = Describe("SentinelAclAuth", func() {
217+
var client *redis.Client
218+
var server *redis.Client
219+
var sentinel *redis.SentinelClient
220+
221+
BeforeEach(func() {
222+
client = redis.NewFailoverClient(&redis.FailoverOptions{
223+
MasterName: aclSentinelName,
224+
SentinelAddrs: aclSentinelAddrs,
225+
MaxRetries: -1,
226+
SentinelUsername: aclSentinelUsername,
227+
SentinelPassword: aclSentinelPassword,
228+
})
229+
230+
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
231+
232+
sentinel = redis.NewSentinelClient(&redis.Options{
233+
Addr: aclSentinelAddrs[0],
234+
MaxRetries: -1,
235+
Username: aclSentinelUsername,
236+
Password: aclSentinelPassword,
237+
})
238+
239+
addr, err := sentinel.GetMasterAddrByName(ctx, aclSentinelName).Result()
240+
Expect(err).NotTo(HaveOccurred())
241+
242+
server = redis.NewClient(&redis.Options{
243+
Addr: net.JoinHostPort(addr[0], addr[1]),
244+
MaxRetries: -1,
245+
})
246+
247+
// Wait until sentinels are picked up by each other.
248+
Eventually(func() string {
249+
return aclSentinel1.Info(ctx).Val()
250+
}, "15s", "100ms").Should(ContainSubstring("sentinels=3"))
251+
Eventually(func() string {
252+
return aclSentinel2.Info(ctx).Val()
253+
}, "15s", "100ms").Should(ContainSubstring("sentinels=3"))
254+
Eventually(func() string {
255+
return aclSentinel3.Info(ctx).Val()
256+
}, "15s", "100ms").Should(ContainSubstring("sentinels=3"))
257+
})
258+
259+
AfterEach(func() {
260+
_ = client.Close()
261+
_ = server.Close()
262+
_ = sentinel.Close()
263+
})
264+
265+
It("should still facilitate operations", func() {
266+
err := client.Set(ctx, "wow", "acl-auth", 0).Err()
267+
Expect(err).NotTo(HaveOccurred())
268+
269+
val, err := client.Get(ctx, "wow").Result()
270+
Expect(err).NotTo(HaveOccurred())
271+
Expect(val).To(Equal("acl-auth"))
272+
})
273+
})

0 commit comments

Comments
 (0)