Implement galenectl initial-setup.

This commit is contained in:
Juliusz Chroboczek
2025-08-11 17:58:09 +02:00
parent bcd4b09a17
commit f5cd385530
2 changed files with 121 additions and 11 deletions
+114 -4
View File
@@ -31,13 +31,14 @@ import (
type configuration struct {
Server string `json:"server"`
AdminUsername string `json:"admin-username"`
AdminPassword string `json:"admin-password"`
AdminToken string `json:"admin-token"`
AdminUsername string `json:"admin-username,omitempty"`
AdminPassword string `json:"admin-password,omitempty"`
AdminToken string `json:"admin-token,omitempty"`
}
var insecure bool
var serverURL, adminUsername, adminPassword, adminToken string
var configFile string
var client http.Client
@@ -51,6 +52,10 @@ var commands = map[string]command{
command: hashPasswordCmd,
description: "generate a hashed password",
},
"initial-setup": {
command: initialSetupCmd,
description: "initial setup of Galene and galenectl",
},
"set-password": {
command: setPasswordCmd,
description: "set a user's password",
@@ -114,7 +119,7 @@ func main() {
if err != nil {
log.Fatalf("UserConfigDir: %v", err)
}
configFile := filepath.Join(
configFile = filepath.Join(
filepath.Join(configdir, "galene"),
"galenectl.json",
)
@@ -321,6 +326,111 @@ func hashPasswordCmd(cmdname string, args []string) {
}
}
func initialSetupCmd(cmdname string, args []string) {
var galeneConfigFn string
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname,
"%v [option...] %v [option...]\n",
os.Args[0], cmdname,
)
cmd.StringVar(&galeneConfigFn, "config", "config.json",
"Galene configuration `file`")
cmd.Parse(args)
if cmd.NArg() != 0 {
cmd.Usage()
os.Exit(1)
}
if adminUsername == "" {
fmt.Fprintf(cmd.Output(),
"Option \"-admin-username\" is required.\n",
)
os.Exit(1)
}
if adminPassword == "" && adminToken == "" {
fmt.Fprint(os.Stdin, "Administrator password: ")
pw, err := term.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
log.Fatalf("ReadPassword: %v", err)
}
adminPassword = string(pw)
fmt.Fprint(os.Stdin, "\n")
}
galeneConfig, err := os.OpenFile(galeneConfigFn,
os.O_WRONLY|os.O_CREATE|os.O_CREATE|os.O_EXCL,
0600)
if err != nil {
log.Fatalf("Create %v: %v", galeneConfigFn, err)
}
galenectlConfig, err := os.OpenFile(configFile,
os.O_WRONLY|os.O_CREATE|os.O_CREATE|os.O_EXCL,
0600)
if err != nil {
galeneConfig.Close()
os.Remove(galeneConfigFn)
log.Fatalf("Create %v: %v", galeneConfigFn, err)
}
defer galeneConfig.Close()
defer galenectlConfig.Close()
var users map[string]group.UserDescription
if adminPassword != "" {
pw, err := makePassword(adminPassword, "bcrypt", 0, 0, 0, 12)
if err != nil {
log.Fatalf("makePassword: %v", err)
}
perms, err := group.NewPermissions("admin")
if err != nil {
log.Fatalf("NewPermissions: %v", err)
}
users = map[string]group.UserDescription{
adminUsername: {
Password: pw,
Permissions: perms,
},
}
}
config := group.Configuration{
WritableGroups: true,
Users: users,
}
encoder := json.NewEncoder(galeneConfig)
encoder.SetIndent("", " ")
err = encoder.Encode(&config)
if err != nil {
log.Fatalf("Encode %v: %v", galeneConfigFn, err)
}
ctlConfig := configuration{
Server: serverURL,
AdminUsername: adminUsername,
AdminPassword: adminPassword,
AdminToken: adminToken,
}
ctlEncoder := json.NewEncoder(galenectlConfig)
ctlEncoder.SetIndent("", " ")
err = ctlEncoder.Encode(&ctlConfig)
if err != nil {
log.Fatalf("Encode %v: %v", configFile, err)
}
fmt.Printf("The file %v has been created. ", galeneConfigFn)
fmt.Printf("Please copy it into your server's\n\"data/\" directory.\n")
fmt.Printf("The file %v has been created. ", configFile)
fmt.Printf("It contains the administrator's\npassword in cleartext, ")
fmt.Printf("please keep it secure.\n")
}
func setAuthorization(req *http.Request) {
if adminToken != "" {
req.Header.Set("Authorization", "Bearer "+adminToken)
+7 -7
View File
@@ -917,15 +917,15 @@ type Configuration struct {
modTime time.Time `json:"-"`
fileSize int64 `json:"-"`
CanonicalHost string `json:"canonicalHost"`
AllowOrigin []string `json:"allowOrigin"`
AllowAdminOrigin []string `json:"allowAdminOrigin"`
ProxyURL string `json:"proxyURL"`
WritableGroups bool `json:"writableGroups"`
Users map[string]UserDescription
CanonicalHost string `json:"canonicalHost,omitempty"`
AllowOrigin []string `json:"allowOrigin,omitempty"`
AllowAdminOrigin []string `json:"allowAdminOrigin,omitempty"`
ProxyURL string `json:"proxyURL,omitempty"`
WritableGroups bool `json:"writableGroups,omitempty"`
Users map[string]UserDescription `json:"users,omitempty"`
// obsolete fields
Admin []ClientPattern `json:"admin"`
Admin []ClientPattern `json:"admin,omitempty"`
}
func (conf Configuration) Zero() bool {