diff --git a/internal/distro/distro.go b/internal/distro/distro.go index 3364715757..a8b3ddbfab 100644 --- a/internal/distro/distro.go +++ b/internal/distro/distro.go @@ -34,6 +34,7 @@ var ( // Helper programs groupaddCmd = "groupadd" + groupdelCmd = "groupdel" mdadmCmd = "mdadm" mountCmd = "mount" sgdiskCmd = "sgdisk" @@ -41,6 +42,7 @@ var ( udevadmCmd = "udevadm" usermodCmd = "usermod" useraddCmd = "useradd" + userdelCmd = "userdel" setfilesCmd = "setfiles" wipefsCmd = "wipefs" @@ -81,6 +83,7 @@ func KernelCmdlinePath() string { return kernelCmdlinePath } func SystemConfigDir() string { return fromEnv("SYSTEM_CONFIG_DIR", systemConfigDir) } func GroupaddCmd() string { return groupaddCmd } +func GroupdelCmd() string { return groupdelCmd } func MdadmCmd() string { return mdadmCmd } func MountCmd() string { return mountCmd } func SgdiskCmd() string { return sgdiskCmd } @@ -88,6 +91,7 @@ func ModprobeCmd() string { return modprobeCmd } func UdevadmCmd() string { return udevadmCmd } func UsermodCmd() string { return usermodCmd } func UseraddCmd() string { return useraddCmd } +func UserdelCmd() string { return userdelCmd } func SetfilesCmd() string { return setfilesCmd } func WipefsCmd() string { return wipefsCmd } diff --git a/internal/exec/stages/files/passwd.go b/internal/exec/stages/files/passwd.go index 7e4263faa4..b740d012a2 100644 --- a/internal/exec/stages/files/passwd.go +++ b/internal/exec/stages/files/passwd.go @@ -68,7 +68,10 @@ func (s *stage) createPasswd(config types.Config) error { s.relabel(deglobbed...) s.relabel("/etc/.pwd.lock") for _, user := range config.Passwd.Users { - if user.NoCreateHome != nil && *user.NoCreateHome == true { + if user.ShouldExist == nil || *user.ShouldExist { + continue + } + if user.NoCreateHome != nil && *user.NoCreateHome { continue } homedir, err := s.GetUserHomeDir(user) @@ -106,6 +109,8 @@ func (s stage) createUsers(config types.Config) error { if err := s.EnsureUser(u); err != nil { return fmt.Errorf("failed to create user %q: %v", u.Name, err) + } else if !(u.ShouldExist == nil || *u.ShouldExist) && err == nil { + continue } if err := s.SetPasswordHash(u); err != nil { @@ -131,7 +136,7 @@ func (s stage) createGroups(config types.Config) error { defer s.Logger.PopPrefix() for _, g := range config.Passwd.Groups { - if err := s.CreateGroup(g); err != nil { + if err := s.EnsureGroup(g); err != nil { return fmt.Errorf("failed to create group %q: %v", g.Name, err) } diff --git a/internal/exec/util/passwd.go b/internal/exec/util/passwd.go index 30b03ac4bd..fb0afbb67e 100644 --- a/internal/exec/util/passwd.go +++ b/internal/exec/util/passwd.go @@ -50,13 +50,25 @@ func appendIfStringSet(args []string, arg string, str *string) []string { } // EnsureUser ensures that the user exists as described. If the user does not -// yet exist, they will be created, otherwise the existing user will be -// modified. +// yet exist, they will be created, otherwise the existing user will be modified. +// If shouldExist variable is set to false and the user already exists, then they +// will be deleted. func (u Util) EnsureUser(c types.PasswdUser) error { exists, err := u.CheckIfUserExists(c) if err != nil { return err } + if !(c.ShouldExist == nil || *c.ShouldExist) && exists { + args := []string{"--remove", "--force", "--root", u.DestDir} + args = append(args, c.Name) + _, err := u.LogCmd(exec.Command(distro.UserdelCmd(), args...), + "deleting user %q", c.Name) + if err != nil { + return fmt.Errorf("failed to delete user %q: %v", + c.Name, err) + } + return nil + } args := []string{"--root", u.DestDir} var cmd string @@ -244,8 +256,25 @@ func (u Util) SetPasswordHash(c types.PasswdUser) error { return err } -// CreateGroup creates the group as described. -func (u Util) CreateGroup(g types.PasswdGroup) error { +// EnsureGroup ensures that the group exists as described. If shouldExist +// variable is set to false and the group already exists, then it will be +// deleted. +func (u Util) EnsureGroup(g types.PasswdGroup) error { + exists, err := u.CheckIfGroupExists(g) + if err != nil { + return err + } + if !(g.ShouldExist == nil || *g.ShouldExist) && exists { + args := []string{"--force", "--root", u.DestDir} + args = append(args, g.Name) + _, err := u.LogCmd(exec.Command(distro.GroupdelCmd(), args...), + "deleting group %q", g.Name) + if err != nil { + return fmt.Errorf("failed to delete group %q: %v", + g.Name, err) + } + return nil + } args := []string{"--root", u.DestDir} if g.Gid != nil { @@ -263,7 +292,19 @@ func (u Util) CreateGroup(g types.PasswdGroup) error { args = append(args, g.Name) - _, err := u.LogCmd(exec.Command(distro.GroupaddCmd(), args...), + _, err = u.LogCmd(exec.Command(distro.GroupaddCmd(), args...), "adding group %q", g.Name) return err } + +// CheckIfGroupExists will return Info log when group is empty +func (u Util) CheckIfGroupExists(g types.PasswdGroup) (bool, error) { + _, err := u.groupLookup(g.Name) + if _, ok := err.(user.UnknownGroupError); ok { + return false, nil + } + if err != nil { + return false, err + } + return true, nil +}