diff --git a/RECIPE.md b/RECIPE.md index 636e6fbe..f068a133 100644 --- a/RECIPE.md +++ b/RECIPE.md @@ -223,6 +223,8 @@ Create a new user. - *Fullname* (`string`): The full name (display name) of the new user. - *Groups* (`[string]`): A list of groups the new user belongs to (the new user is automatically part of its own group). - *Password* (optional `string`): The password for the user. If not provided, password login will be disabled. +- *UID* (optional `int`): The UID for the user. Will be determined automatically if not provided. +- *GID* (optional `int`): The GID for the user. Will be determined automatically if not provided. ### timezone diff --git a/core/recipe.go b/core/recipe.go index c3c492e7..5298346f 100644 --- a/core/recipe.go +++ b/core/recipe.go @@ -696,7 +696,9 @@ func runPostInstallOperation(chroot bool, operation string, args []interface{}) * - *Username* (`string`): The username of the new user. * - *Fullname* (`string`): The full name (display name) of the new user. * - *Groups* (`[string]`): A list of groups the new user belongs to (the new user is automatically part of its own group). - * - *Password* (optional `string`): The password for the user. If not provided, password login will be disabled. + * - *Password* (optional `string`): The password for the user. If not provided or empty, password login will be disabled. + * - *UID* (optional `int`): The UID for the user. Will be determined automatically if not provided. + * - *GID* (optional `int`): The GID for the user. Will be determined automatically if not provided. */ case "adduser": username := args[0].(string) @@ -706,13 +708,20 @@ func runPostInstallOperation(chroot bool, operation string, args []interface{}) groupStr := group.(string) groups = append(groups, groupStr) } - var err error - if len(args) == 4 { - password := args[3].(string) - err = system.AddUser(targetRoot, username, fullname, groups, password) - } else { - err = system.AddUser(targetRoot, username, fullname, groups) + password := "" + if len(args) >= 4 { + password = args[3].(string) } + uid := -1 + if len(args) >= 5 { + uid = int(args[4].(float64)) + } + gid := -1 + if len(args) >= 6 { + gid = int(args[5].(float64)) + } + + err := system.AddUser(targetRoot, username, fullname, groups, password, uid, gid) if err != nil { return operationError(operation, err) } diff --git a/core/system/post_install.go b/core/system/post_install.go index 189428b5..dae45730 100644 --- a/core/system/post_install.go +++ b/core/system/post_install.go @@ -30,25 +30,37 @@ func SetTimezone(targetRoot, tz string) error { return nil } -func AddUser(targetRoot, username, fullname string, groups []string, password ...string) error { - adduserCmd := "useradd --shell /bin/bash %s && usermod -c \"%s\" %s" +// AddUser creates a new user and adds it to the groups provided +// +// If password is left empty, password login will be disabled. +// If uid and/or gid are -1, they will be ignored. +func AddUser(targetRoot, username, fullname string, groups []string, password string, uid, gid int) error { + adduserCmd := "useradd --shell /bin/bash %s %s && usermod -c \"%s\" %s" + + extraArgs := "" + if uid != -1 { + extraArgs = " --uid " + fmt.Sprint(uid) + } + if gid != -1 { + extraArgs = " --gid " + fmt.Sprint(gid) + } var err error if targetRoot != "" { - err = util.RunInChroot(targetRoot, fmt.Sprintf(adduserCmd, username, fullname, username)) + err = util.RunInChroot(targetRoot, fmt.Sprintf(adduserCmd, extraArgs, username, fullname, username)) } else { - err = util.RunCommand(fmt.Sprintf(adduserCmd, username, fullname, username)) + err = util.RunCommand(fmt.Sprintf(adduserCmd, extraArgs, username, fullname, username)) } if err != nil { return fmt.Errorf("failed to create user: %s", err) } - if len(password) == 1 { + if password != "" { passwdCmd := "echo \"%s:%s\" | chpasswd" if targetRoot != "" { - err = util.RunInChroot(targetRoot, fmt.Sprintf(passwdCmd, username, password[0])) + err = util.RunInChroot(targetRoot, fmt.Sprintf(passwdCmd, username, password)) } else { - err = util.RunCommand(fmt.Sprintf(passwdCmd, username, password[0])) + err = util.RunCommand(fmt.Sprintf(passwdCmd, username, password)) } if err != nil { return fmt.Errorf("failed to set password: %s", err) diff --git a/utils/sample_recipe.json b/utils/sample_recipe.json index 60dca2bc..23c94c15 100644 --- a/utils/sample_recipe.json +++ b/utils/sample_recipe.json @@ -314,7 +314,7 @@ { "chroot": true, "operation": "adduser", - "params": ["vanilla", "vanilla", ["sudo", "lpadmin"], "vanilla"] + "params": ["vanilla", "vanilla", ["sudo", "lpadmin"], "vanilla", 1200] }, { "chroot": true,