diff --git a/go.mod b/go.mod index 6159ef70..d7b9cb4f 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,9 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/itchyny/gojq v0.12.15 github.com/joho/godotenv v1.5.1 - github.com/mauromorales/xpasswd v0.3.1 + github.com/mauromorales/xpasswd v0.4.0 github.com/moby/moby v24.0.9+incompatible - github.com/mudler/entities v0.0.0-20240611135956-f8f11ba52c2f + github.com/mudler/entities v0.0.0-20240625130751-3d7f84082f3a github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.33.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 7455a260..93ee445b 100644 --- a/go.sum +++ b/go.sum @@ -138,8 +138,8 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mauromorales/xpasswd v0.3.1 h1:mVPGISfzN/WaCUjYRFiDgIREb2NMfwgPSj3LS6QMm0Q= -github.com/mauromorales/xpasswd v0.3.1/go.mod h1:Z3+aY19mhNfcGi3st0+RAVSz2vC+pyoju2S/FPN8kEg= +github.com/mauromorales/xpasswd v0.4.0 h1:Jf6mfA8lwQsYzwgfQADPDGV7l/liAvRrnG+nQTPy0j8= +github.com/mauromorales/xpasswd v0.4.0/go.mod h1:Z3+aY19mhNfcGi3st0+RAVSz2vC+pyoju2S/FPN8kEg= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -149,8 +149,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/moby v24.0.9+incompatible h1:Z/hFbZJqC5Fmuf6jesMLdHU71CMAgdiSJ1ZYey+bFmg= github.com/moby/moby v24.0.9+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= -github.com/mudler/entities v0.0.0-20240611135956-f8f11ba52c2f h1:5x1OeWl4gSW3L9KzntvWphjrcHASXq3gI351BgBbXjs= -github.com/mudler/entities v0.0.0-20240611135956-f8f11ba52c2f/go.mod h1:TXMcB82+CBF3fEQhIch/gFSuWVcItz4BdTfomYGW1jg= +github.com/mudler/entities v0.0.0-20240625130751-3d7f84082f3a h1:IeKeUwMeqfGYblesrk7Gu72z1xsJrceiIDDES4Rj3+U= +github.com/mudler/entities v0.0.0-20240625130751-3d7f84082f3a/go.mod h1:7bNIR64mpm7ld4bnDQ+LjHBPhUDAqoBQuv4aK53UGSs= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= diff --git a/pkg/plugins/user.go b/pkg/plugins/user.go index 76a74a3d..555db44e 100644 --- a/pkg/plugins/user.go +++ b/pkg/plugins/user.go @@ -18,7 +18,7 @@ import ( "github.com/twpayne/go-vfs/v4" ) -func createUser(fs vfs.FS, u schema.User, console Console) error { +func createUser(l logger.Interface, fs vfs.FS, u schema.User, console Console) error { pass := u.PasswordHash if u.LockPasswd { pass = "!" @@ -69,8 +69,11 @@ func createUser(fs vfs.FS, u schema.User, console Console) error { } primaryGroup := u.Name - gid := 1000 + l.Debugf("dimitris - primaryGroup: %v\n", primaryGroup) + l.Debugf("dimitris - u.PrimaryGroup: %v\n", u.PrimaryGroup) + + gid := -1 // Automatic by default (-1 instruct entities to find the next free id and assign it) if u.PrimaryGroup != "" { gr, err := osuser.LookupGroup(u.PrimaryGroup) if err != nil { @@ -78,32 +81,36 @@ func createUser(fs vfs.FS, u schema.User, console Console) error { } gid, _ = strconv.Atoi(gr.Gid) primaryGroup = u.PrimaryGroup - } else { - // Create a new group after the user name - all, _ := entities.ParseGroup(etcgroup) - if len(all) != 0 { - usedGids := []int{} - for _, entry := range all { - usedGids = append(usedGids, *entry.Gid) - } - sort.Ints(usedGids) - if len(usedGids) == 0 { - return errors.New("no new guid found") - } - gid = usedGids[len(usedGids)-1] - gid++ - } } + l.Debugf("dimitris - gid outside: %v", gid) + updateGroup := entities.Group{ Name: primaryGroup, Password: "x", Gid: &gid, Users: u.Name, } - updateGroup.Apply(etcgroup, false) + err = updateGroup.Apply(etcgroup, false) + if err != nil { + return errors.Wrap(err, "creating the user's group") + } + + // reload the group to get the generated GID + groups, _ := entities.ParseGroup(etcgroup) + for name, group := range groups { + l.Debugf("dimitris - checking group: %v , against: %v", name, updateGroup.Name) + if name == updateGroup.Name { + updateGroup = group + gid = *group.Gid + l.Debugf("dimitris - found group: %v , with gid: %v", name, *group.Gid) + break + } + } + + l.Debugf("dimitris - gid after apply: %v", *updateGroup.Gid) - uid := 1000 + uid := -1 if u.UID != "" { // User defined-uid uid, err = strconv.Atoi(u.UID) @@ -123,9 +130,16 @@ func createUser(fs vfs.FS, u schema.User, console Console) error { return errors.Wrap(err, "could not get user id") } } else { - uid = list.GenerateUID() + // https://systemd.io/UIDS-GIDS/#special-distribution-uid-ranges + uid, err = list.GenerateUIDInRange(1000, 65533) + if err != nil { + return errors.Wrap(err, "no available uid in the range 1000…65533") + } } } + if uid == -1 { + return errors.New("could not set uid for user") + } if u.Homedir == "" { u.Homedir = fmt.Sprintf("%s/%s", usrDefaults["HOME"], u.Name) @@ -135,6 +149,7 @@ func createUser(fs vfs.FS, u schema.User, console Console) error { u.Shell = usrDefaults["SHELL"] } + l.Debugf("uid = %+v\n", uid) userInfo := &entities.UserPasswd{ Username: u.Name, Password: "x", @@ -144,6 +159,7 @@ func createUser(fs vfs.FS, u schema.User, console Console) error { Shell: u.Shell, Uid: uid, } + l.Debugf("dimitris - user gid: %v\n", gid) if err := userInfo.Apply(etcpasswd, false); err != nil { return err @@ -162,7 +178,7 @@ func createUser(fs vfs.FS, u schema.User, console Console) error { os.Chown(homedir, uid, gid) } - groups, _ := entities.ParseGroup(etcgroup) + groups, _ = entities.ParseGroup(etcgroup) for name, group := range groups { for _, w := range u.Groups { if w == name { @@ -192,6 +208,7 @@ func setUserPass(fs vfs.FS, username, password string) error { } func User(l logger.Interface, s schema.Stage, fs vfs.FS, console Console) error { + l.Debugf("dimitris - running the user plugin\n") var errs error // Order users so they get the same UID on each run @@ -206,10 +223,12 @@ func User(l logger.Interface, s schema.Stage, fs vfs.FS, console Console) error r := s.Users[k] r.Name = k if !r.Exists() { - if err := createUser(fs, r, console); err != nil { + l.Debugf("dimitris - about to create user: %v\n", r.Name) + if err := createUser(l, fs, r, console); err != nil { errs = multierror.Append(errs, err) } } else if r.PasswordHash != "" { + l.Debugf("dimitris - user existed, setting pass\n") if err := setUserPass(fs, r.Name, r.PasswordHash); err != nil { return err } diff --git a/pkg/schema/loader_cloudinit.go b/pkg/schema/loader_cloudinit.go index a129bca2..0e16c881 100644 --- a/pkg/schema/loader_cloudinit.go +++ b/pkg/schema/loader_cloudinit.go @@ -40,6 +40,7 @@ func (cloudInit) Load(s []byte, fs vfs.FS) (*YipConfig, error) { users := make(map[string]User) userstoKey := []string{} + fmt.Printf("cc.Users = %+v\n", cc.Users) for _, u := range cc.Users { userstoKey = append(userstoKey, u.Name) users[u.Name] = User{ @@ -104,6 +105,8 @@ func (cloudInit) Load(s []byte, fs vfs.FS) (*YipConfig, error) { stages = append(stages, Stage{Layout: *layout}) } + fmt.Printf("stages = %+v\n", stages) + fmt.Printf("users = %+v\n", users) result := &YipConfig{ Stages: map[string][]Stage{ "boot": stages, diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index d38854d2..539e5318 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -103,6 +103,7 @@ type User struct { func (u User) Exists() bool { _, err := user.Lookup(u.Name) + fmt.Printf("Exists() err = %+v\n", err) return err == nil }