mirror of
https://github.com/eosswedenorg/thalos
synced 2026-06-16 04:24:56 +02:00
171 lines
4.6 KiB
Go
171 lines
4.6 KiB
Go
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),
|
|
})
|
|
}
|
|
|
|
func CreateRedisACLCmd() *cobra.Command {
|
|
cmd := &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
|
|
}
|
|
},
|
|
}
|
|
|
|
cmd.Flags().String("default-pw", "", "Password to use for the default account, if not provided a random one will be generated")
|
|
cmd.Flags().String("client", "thalos-client", "Thalos client account name")
|
|
cmd.Flags().String("client-pw", "", "Password to use for the thalos client account, if not provided a random one will be generated")
|
|
cmd.Flags().String("server", "thalos", "Thalos account name")
|
|
cmd.Flags().String("server-pw", "", "Password to use for the thalos server account, if not provided a random one will be generated")
|
|
cmd.Flags().String("prefix", "ship", "Redis key prefix")
|
|
cmd.Flags().Bool("cleartext", false, "If passwords should be hashed or left in cleartext.")
|
|
cmd.Flags().String("file", "", "Where the config should be written to (default: standard out)")
|
|
cmd.Flags().Uint("pass-len", 32, "The length of generated passwords")
|
|
|
|
return cmd
|
|
}
|