From 39b577e6f5706eea5b158a2fc27a2c082d272853 Mon Sep 17 00:00:00 2001 From: Itxaka Date: Mon, 21 Oct 2024 10:15:34 +0200 Subject: [PATCH] Restore UID in user. Signed-off-by: Itxaka --- pkg/plugins/user.go | 47 ++++++++++++++++++++++----------------- pkg/plugins/user_test.go | 3 ++- pkg/schema/schema.go | 1 + pkg/schema/schema_test.go | 2 ++ 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/pkg/plugins/user.go b/pkg/plugins/user.go index 684587e5..ddcf295b 100644 --- a/pkg/plugins/user.go +++ b/pkg/plugins/user.go @@ -107,32 +107,39 @@ func createUser(fs vfs.FS, u schema.User, console Console) error { } uid := -1 - list := users.NewUserList() - list.SetPath(etcpasswd) - list.Load() - user := list.Get(u.Name) - - if user != nil { - uid, err = user.UID() - if err != nil { - return errors.Wrap(err, "could not get user id") - } + + // If UID is specified just put it there. No matter whats in the system or the collisions. Good luck. + if u.UID != "" { + uid, err = strconv.Atoi(u.UID) } else { - // Try to see if the user was created previously with a given UID by checking for an existing home dir - userDir, err := os.Stat(u.Homedir) - if err == nil { - if stat, ok := userDir.Sys().(*syscall.Stat_t); ok { - uid = int(stat.Uid) + // Try to get the existing UID in the system + list := users.NewUserList() + list.SetPath(etcpasswd) + list.Load() + user := list.Get(u.Name) + if user != nil { + uid, err = user.UID() + if err != nil { + return errors.Wrap(err, "could not get user id") } } else { - // Now generate one if we havent been able to pick the existing one - // https://systemd.io/UIDS-GIDS/#special-distribution-uid-ranges - uid, err = list.GenerateUIDInRange(entities.HumanIDMin, entities.HumanIDMax) - if err != nil { - return errors.Wrap(err, "no available uid") + // Try to see if the user was created previously with a given UID by checking for an existing home dir + userDir, err := os.Stat(u.Homedir) + if err == nil { + if stat, ok := userDir.Sys().(*syscall.Stat_t); ok { + uid = int(stat.Uid) + } + } else { + // Now generate one if we havent been able to pick the existing one + // https://systemd.io/UIDS-GIDS/#special-distribution-uid-ranges + uid, err = list.GenerateUIDInRange(entities.HumanIDMin, entities.HumanIDMax) + if err != nil { + return errors.Wrap(err, "no available uid") + } } } } + if uid == -1 { return errors.New("could not set uid for user") } diff --git a/pkg/plugins/user_test.go b/pkg/plugins/user_test.go index 34ee978b..2081fc15 100644 --- a/pkg/plugins/user_test.go +++ b/pkg/plugins/user_test.go @@ -183,6 +183,7 @@ last:x:999:999:Test user for uid:/:/usr/bin/nologin Users: map[string]schema.User{"foo": { PasswordHash: `$fkekofe`, LockPasswd: true, + UID: "5000", Homedir: "/run/foo", Shell: "/bin/bash", }}, @@ -212,7 +213,7 @@ last:x:999:999:Test user for uid:/:/usr/bin/nologin Expect(foo.HomeDir()).To(Equal("/run/foo")) Expect(foo.Shell()).To(Equal("/bin/bash")) Expect(foo.Password()).To(Equal("x")) - Expect(foo.UID()).To(Equal(1000)) + Expect(foo.UID()).To(Equal(5000)) }) diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index ef451eac..763b58da 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -98,6 +98,7 @@ type User struct { NoLogInit bool `yaml:"no_log_init,omitempty"` Shell string `yaml:"shell,omitempty"` LockPasswd bool `yaml:"lock_passwd,omitempty"` + UID string `yaml:"uid,omitempty"` } func (u User) Exists() bool { diff --git a/pkg/schema/schema_test.go b/pkg/schema/schema_test.go index 439e81d9..5d1ea0e2 100644 --- a/pkg/schema/schema_test.go +++ b/pkg/schema/schema_test.go @@ -94,6 +94,7 @@ stages: users: - name: "bar" passwd: "foo" + uid: "1002" lock_passwd: true groups: - sudo @@ -113,6 +114,7 @@ write_files: `) Expect(len(yipConfig.Stages)).To(Equal(3)) Expect(yipConfig.Stages["boot"][0].Users["bar"].PasswordHash).To(Equal("foo")) + Expect(yipConfig.Stages["boot"][0].Users["bar"].UID).To(Equal("1002")) Expect(yipConfig.Stages["boot"][0].SSHKeys).To(Equal(map[string][]string{"bar": {"faaapploo", "asdd"}})) Expect(yipConfig.Stages["boot"][0].Files[0].Path).To(Equal("/foo/bar")) Expect(yipConfig.Stages["boot"][0].Files[0].Permissions).To(Equal(uint32(0644)))