-
Notifications
You must be signed in to change notification settings - Fork 0
/
redis-acl.go
158 lines (130 loc) · 3.66 KB
/
redis-acl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"math/rand"
"os"
"text/template"
"time"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var rnd *rand.Rand
// Helper struct representing a redis user.
type User struct {
// Username
Name string
// Password
Password string
// True if password was generated, false if not.
Generated bool
// True if password should be hashed, false otherwise.
Hash bool
}
func NewUser(name, password string, pass_len uint) User {
if len(password) < 1 {
return User{
Name: name,
Password: randomString(pass_len),
Generated: true,
}
}
return User{Name: name, Password: password}
}
func (u *User) GetPassword() string {
if u.Hash {
return "#" + hash(u.Password)
}
return ">" + u.Password
}
func (u User) Print() {
fmt.Println(u.Name+":", u.Password)
}
func (u User) PrintIfGeneratedPW() {
if u.Generated {
u.Print()
}
}
func randomString(length uint) string {
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789"
out := ""
for i := 0; i < int(length); i++ {
idx := rnd.Intn(len(charset))
out += string(charset[idx])
}
return out
}
func hash(str string) string {
data := sha256.Sum256([]byte(str))
return hex.EncodeToString(data[:])
}
func writeTemplate(w io.Writer, defUser, serverUser, clientUser User, prefix string) error {
tmplStr := `# Created by thalos-tools on {{.timestamp}}
user default on {{.defaultpw}} ~* &* +@all
user {{.server}} on {{.serverpw}} resetchannels ~{{.prefix}}::* &{{.prefix}}::* -@all +ping +get +publish +set
user {{.client}} on {{.clientpw}} resetchannels &{{.prefix}}::* -@all +subscribe
`
tmpl, err := template.New("acl").Parse(tmplStr)
if err != nil {
return err
}
return tmpl.Execute(w, map[string]string{
"defaultpw": defUser.GetPassword(),
"client": clientUser.Name,
"clientpw": clientUser.GetPassword(),
"server": serverUser.Name,
"serverpw": serverUser.GetPassword(),
"prefix": prefix,
"timestamp": time.Now().Format(time.UnixDate),
})
}
var RedisACLCmd = &cobra.Command{
Use: "redis-acl",
Short: "create a users.acl file",
Run: func(cmd *cobra.Command, args []string) {
var err error
out := os.Stdout
rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
flagDefUserPw, _ := cmd.Flags().GetString("default-pw")
flagServer, _ := cmd.Flags().GetString("server")
flagServerPw, _ := cmd.Flags().GetString("server-pw")
flagClient, _ := cmd.Flags().GetString("client")
flagClientPw, _ := cmd.Flags().GetString("client-pw")
flagPrefix, _ := cmd.Flags().GetString("prefix")
flagPassLen, _ := cmd.Flags().GetUint("pass-len")
defaultUser := NewUser("default", flagDefUserPw, flagPassLen)
serverUser := NewUser(flagServer, flagServerPw, flagPassLen)
clientUser := NewUser(flagClient, flagClientPw, flagPassLen)
atleastOneGeneratedPw := defaultUser.Generated || serverUser.Generated || clientUser.Generated
cleartext, _ := cmd.Flags().GetBool("cleartext")
if !cleartext {
if atleastOneGeneratedPw {
println("Passwords")
}
defaultUser.PrintIfGeneratedPW()
serverUser.PrintIfGeneratedPW()
clientUser.PrintIfGeneratedPW()
defaultUser.Hash = true
serverUser.Hash = true
clientUser.Hash = true
}
filename, _ := cmd.Flags().GetString("file")
if len(filename) > 0 {
out, err = os.Create(filename)
if err != nil {
log.WithError(err).Fatal("Failed to create output file")
return
}
defer out.Close()
} else if !cleartext && atleastOneGeneratedPw {
fmt.Println()
}
err = writeTemplate(out, defaultUser, serverUser, clientUser, flagPrefix)
if err != nil {
log.WithError(err).Fatal("Failed to writte config")
return
}
},
}