Implement galenectl initial-setup.
This commit is contained in:
+114
-4
@@ -31,13 +31,14 @@ import (
|
|||||||
|
|
||||||
type configuration struct {
|
type configuration struct {
|
||||||
Server string `json:"server"`
|
Server string `json:"server"`
|
||||||
AdminUsername string `json:"admin-username"`
|
AdminUsername string `json:"admin-username,omitempty"`
|
||||||
AdminPassword string `json:"admin-password"`
|
AdminPassword string `json:"admin-password,omitempty"`
|
||||||
AdminToken string `json:"admin-token"`
|
AdminToken string `json:"admin-token,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var insecure bool
|
var insecure bool
|
||||||
var serverURL, adminUsername, adminPassword, adminToken string
|
var serverURL, adminUsername, adminPassword, adminToken string
|
||||||
|
var configFile string
|
||||||
|
|
||||||
var client http.Client
|
var client http.Client
|
||||||
|
|
||||||
@@ -51,6 +52,10 @@ var commands = map[string]command{
|
|||||||
command: hashPasswordCmd,
|
command: hashPasswordCmd,
|
||||||
description: "generate a hashed password",
|
description: "generate a hashed password",
|
||||||
},
|
},
|
||||||
|
"initial-setup": {
|
||||||
|
command: initialSetupCmd,
|
||||||
|
description: "initial setup of Galene and galenectl",
|
||||||
|
},
|
||||||
"set-password": {
|
"set-password": {
|
||||||
command: setPasswordCmd,
|
command: setPasswordCmd,
|
||||||
description: "set a user's password",
|
description: "set a user's password",
|
||||||
@@ -114,7 +119,7 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("UserConfigDir: %v", err)
|
log.Fatalf("UserConfigDir: %v", err)
|
||||||
}
|
}
|
||||||
configFile := filepath.Join(
|
configFile = filepath.Join(
|
||||||
filepath.Join(configdir, "galene"),
|
filepath.Join(configdir, "galene"),
|
||||||
"galenectl.json",
|
"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) {
|
func setAuthorization(req *http.Request) {
|
||||||
if adminToken != "" {
|
if adminToken != "" {
|
||||||
req.Header.Set("Authorization", "Bearer "+adminToken)
|
req.Header.Set("Authorization", "Bearer "+adminToken)
|
||||||
|
|||||||
+7
-7
@@ -917,15 +917,15 @@ type Configuration struct {
|
|||||||
modTime time.Time `json:"-"`
|
modTime time.Time `json:"-"`
|
||||||
fileSize int64 `json:"-"`
|
fileSize int64 `json:"-"`
|
||||||
|
|
||||||
CanonicalHost string `json:"canonicalHost"`
|
CanonicalHost string `json:"canonicalHost,omitempty"`
|
||||||
AllowOrigin []string `json:"allowOrigin"`
|
AllowOrigin []string `json:"allowOrigin,omitempty"`
|
||||||
AllowAdminOrigin []string `json:"allowAdminOrigin"`
|
AllowAdminOrigin []string `json:"allowAdminOrigin,omitempty"`
|
||||||
ProxyURL string `json:"proxyURL"`
|
ProxyURL string `json:"proxyURL,omitempty"`
|
||||||
WritableGroups bool `json:"writableGroups"`
|
WritableGroups bool `json:"writableGroups,omitempty"`
|
||||||
Users map[string]UserDescription
|
Users map[string]UserDescription `json:"users,omitempty"`
|
||||||
|
|
||||||
// obsolete fields
|
// obsolete fields
|
||||||
Admin []ClientPattern `json:"admin"`
|
Admin []ClientPattern `json:"admin,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf Configuration) Zero() bool {
|
func (conf Configuration) Zero() bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user