SuperUser CLI flags, fix #20

Also adds some Murmur CLI flags, see #25
Since the only way right now to set the SuperUser pw is through
the CLI on start, this commit also drops the config updates through
the freezelog (probably a remnant of RPC), which the SetSuperUserPassword
function was the last user of.
This commit is contained in:
rubenseyer 2018-02-14 15:29:16 +01:00
parent 40ef449f6e
commit 693dd6f4e8
3 changed files with 67 additions and 12 deletions

View file

@ -21,7 +21,7 @@ var usageTmpl = `usage: grumble [options]
grumble {{.Version}} ({{.BuildDate}}) grumble {{.Version}} ({{.BuildDate}})
target: {{.OS}}, {{.Arch}} target: {{.OS}}, {{.Arch}}
--help --help, --version
Shows this help listing. Shows this help listing.
--datadir <data-dir> (default: {{.DefaultDataDir}}) --datadir <data-dir> (default: {{.DefaultDataDir}})
@ -33,6 +33,17 @@ var usageTmpl = `usage: grumble [options]
--ini <config-path> (default: $DATADIR/grumble.ini) --ini <config-path> (default: $DATADIR/grumble.ini)
Config file path. Config file path.
--supw <password> [server-id]
Set password for SuperUser account. Optionally takes
the virtual server to modify as the first positional argument.
--readsupw [server-id]
Like --supw, but reads from stdin instead.
--disablesu [server-id]
Disables the SuperUser account. Optionally takes
the virtual server to modify as the first positional argument.
--regen-keys --regen-keys
Force grumble to regenerate its global RSA Force grumble to regenerate its global RSA
keypair (and certificate). keypair (and certificate).
@ -49,13 +60,17 @@ var usageTmpl = `usage: grumble [options]
` `
type args struct { type args struct {
ShowHelp bool ShowHelp bool
DataDir string DataDir string
LogPath string LogPath string
ConfigPath string ConfigPath string
RegenKeys bool SuperUserPW string
SQLiteDB string ReadPass bool
CleanUp bool DisablePass bool
RegenKeys bool
ServerId int64
SQLiteDB string
CleanUp bool
} }
func defaultDataDir() string { func defaultDataDir() string {
@ -90,11 +105,17 @@ var Args args
func init() { func init() {
flag.Usage = Usage flag.Usage = Usage
flag.BoolVar(&Args.ShowHelp, "version", false, "")
flag.BoolVar(&Args.ShowHelp, "help", false, "") flag.BoolVar(&Args.ShowHelp, "help", false, "")
flag.StringVar(&Args.DataDir, "datadir", defaultDataDir(), "") flag.StringVar(&Args.DataDir, "datadir", defaultDataDir(), "")
flag.StringVar(&Args.LogPath, "log", "", "") flag.StringVar(&Args.LogPath, "log", "", "")
flag.StringVar(&Args.ConfigPath, "ini", "", "") flag.StringVar(&Args.ConfigPath, "ini", "", "")
flag.StringVar(&Args.SuperUserPW, "supw", "", "")
flag.BoolVar(&Args.ReadPass, "readsupw", false, "")
flag.BoolVar(&Args.DisablePass, "disablesu", false, "")
flag.BoolVar(&Args.RegenKeys, "regen-keys", false, "") flag.BoolVar(&Args.RegenKeys, "regen-keys", false, "")
flag.StringVar(&Args.SQLiteDB, "import-murmurdb", "", "") flag.StringVar(&Args.SQLiteDB, "import-murmurdb", "", "")

View file

@ -7,10 +7,12 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv"
"mumble.info/grumble/pkg/blobstore" "mumble.info/grumble/pkg/blobstore"
"mumble.info/grumble/pkg/logtarget" "mumble.info/grumble/pkg/logtarget"
@ -29,6 +31,20 @@ func main() {
Usage() Usage()
return return
} }
if Args.ReadPass {
data, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("Failed to read password from stdin: %v", err)
}
Args.SuperUserPW = string(data)
}
if flag.NArg() > 0 && (Args.SuperUserPW != "" || Args.DisablePass) {
Args.ServerId, err = strconv.ParseInt(flag.Arg(0), 10, 64)
if err != nil {
log.Fatalf("Failed to parse server id %v: %v", flag.Arg(0), err)
return
}
}
// Open the data dir to check whether it exists. // Open the data dir to check whether it exists.
dataDir, err := os.Open(Args.DataDir) dataDir, err := os.Open(Args.DataDir)
@ -114,9 +130,7 @@ func main() {
// Check whether we should regenerate the default global keypair // Check whether we should regenerate the default global keypair
// and corresponding certificate. // and corresponding certificate.
// These are used as the default certificate of all virtual servers // These are used as the default certificate of all virtual servers.
// and the SSH admin console, but can be overridden using the "key"
// and "cert" arguments to Grumble. todo(rubenseyer) implement override by cli
certFn := config.PathValue("CertPath", Args.DataDir) certFn := config.PathValue("CertPath", Args.DataDir)
keyFn := config.PathValue("KeyPath", Args.DataDir) keyFn := config.PathValue("KeyPath", Args.DataDir)
shouldRegen := false shouldRegen := false
@ -232,6 +246,18 @@ func main() {
if err != nil { if err != nil {
log.Fatalf("Unable to load server: %v", err.Error()) log.Fatalf("Unable to load server: %v", err.Error())
} }
// Check if SuperUser password should be updated.
if Args.ServerId == 0 || Args.ServerId == s.Id {
if Args.DisablePass {
s.cfg.Reset("SuperUserPassword")
log.Printf("Disabled SuperUser for server %v", name)
} else if Args.SuperUserPW != "" {
s.SetSuperUserPassword(Args.SuperUserPW)
log.Printf("Set SuperUser password for server %v", name)
}
}
err = s.FreezeToFile() err = s.FreezeToFile()
if err != nil { if err != nil {
log.Fatalf("Unable to freeze server to disk: %v", err.Error()) log.Fatalf("Unable to freeze server to disk: %v", err.Error())
@ -240,6 +266,14 @@ func main() {
} }
} }
// If SuperUser password flags were passed, the servers should not start.
if Args.SuperUserPW != "" || Args.DisablePass {
if len(servers) == 0 {
log.Fatalf("No servers found to set password for")
}
return
}
// If no servers were found, create the default virtual server. // If no servers were found, create the default virtual server.
if len(servers) == 0 { if len(servers) == 0 {
s, err := NewServer(1, configFile.ServerConfig(1, nil)) s, err := NewServer(1, configFile.ServerConfig(1, nil))

View file

@ -74,8 +74,8 @@ type Server struct {
incoming chan *Message incoming chan *Message
voicebroadcast chan *VoiceBroadcast voicebroadcast chan *VoiceBroadcast
cfgUpdate chan *KeyValuePair
tempRemove chan *Channel tempRemove chan *Channel
//cfgUpdate chan *KeyValuePair
// Signals to the server that a client has been successfully // Signals to the server that a client has been successfully
// authenticated. // authenticated.