Skip to content

Commit

Permalink
passwd: allow removing the existing users/groups
Browse files Browse the repository at this point in the history
Fixes coreos#738
Some users may want to add a custom user, and remove
the `core` user injected via the default configuration.
This PR will enable users to delete the existing
users/groups in a given distro.
  • Loading branch information
sohankunkerkar committed Jul 24, 2020
1 parent 0d6f3e5 commit e0d57f5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 17 deletions.
4 changes: 4 additions & 0 deletions internal/distro/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ var (

// Helper programs
groupaddCmd = "groupadd"
groupdelCmd = "groupdel"
mdadmCmd = "mdadm"
mountCmd = "mount"
sgdiskCmd = "sgdisk"
modprobeCmd = "modprobe"
udevadmCmd = "udevadm"
usermodCmd = "usermod"
useraddCmd = "useradd"
userdelCmd = "userdel"
setfilesCmd = "setfiles"
wipefsCmd = "wipefs"

Expand Down Expand Up @@ -81,13 +83,15 @@ 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 }
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 }

Expand Down
33 changes: 21 additions & 12 deletions internal/exec/stages/files/passwd.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ func (s *stage) expandGlobList(globs ...string) ([]string, error) {

// createPasswd creates the users and groups as described in config.Passwd.
func (s *stage) createPasswd(config types.Config) error {
if err := s.createGroups(config); err != nil {
return fmt.Errorf("failed to create groups: %v", err)
if err := s.ensureGroups(config); err != nil {
return fmt.Errorf("failed to configure groups: %v", err)
}

if err := s.createUsers(config); err != nil {
return fmt.Errorf("failed to create users: %v", err)
if err := s.ensureUsers(config); err != nil {
return fmt.Errorf("failed to configure users: %v", err)
}

// to be safe, just blanket mark all passwd-related files rather than
Expand All @@ -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.NoCreateHome != nil && *user.NoCreateHome {
continue
}
if user.ShouldExist != nil && !*user.ShouldExist {
continue
}
homedir, err := s.GetUserHomeDir(user)
Expand All @@ -94,18 +97,23 @@ func (s *stage) createPasswd(config types.Config) error {
return nil
}

// createUsers creates the users as described in config.Passwd.Users.
func (s stage) createUsers(config types.Config) error {
// ensureUsers ensures that users match the state described
// in config.Passwd.Users.
func (s stage) ensureUsers(config types.Config) error {
if len(config.Passwd.Users) == 0 {
return nil
}
s.Logger.PushPrefix("createUsers")
s.Logger.PushPrefix("ensureUsers")
defer s.Logger.PopPrefix()

for _, u := range config.Passwd.Users {
if err := s.EnsureUser(u); err != nil {
return fmt.Errorf("failed to create user %q: %v",
u.Name, err)
} else if err == nil {
if u.ShouldExist != nil && !*u.ShouldExist {
continue
}
}

if err := s.SetPasswordHash(u); err != nil {
Expand All @@ -122,16 +130,17 @@ func (s stage) createUsers(config types.Config) error {
return nil
}

// createGroups creates the users as described in config.Passwd.Groups.
func (s stage) createGroups(config types.Config) error {
// ensureGroups ensures that groups match the state described
// in config.Passwd.Groups.
func (s stage) ensureGroups(config types.Config) error {
if len(config.Passwd.Groups) == 0 {
return nil
}
s.Logger.PushPrefix("createGroups")
s.Logger.PushPrefix("ensureGroups")
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)
}
Expand Down
61 changes: 56 additions & 5 deletions internal/exec/util/passwd.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,30 @@ 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 the `shouldExist` field is set to false and the user already exists, then
// they will be deleted.
func (u Util) EnsureUser(c types.PasswdUser) error {
shouldExist := c.ShouldExist == nil || *c.ShouldExist
exists, err := u.CheckIfUserExists(c)
if err != nil {
return err
}
if !shouldExist && exists {
args := []string{"--remove", "--root", u.DestDir, 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
}

if !shouldExist && !exists {
return nil
}

args := []string{"--root", u.DestDir}

var cmd string
Expand Down Expand Up @@ -244,8 +261,30 @@ 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 the
// `shouldExist` field is set to false and the group already exists,
// then it will be deleted.
func (u Util) EnsureGroup(g types.PasswdGroup) error {
shouldExist := g.ShouldExist == nil || *g.ShouldExist
exists, err := u.CheckIfGroupExists(g)
if err != nil {
return err
}
if !shouldExist && exists {
args := []string{"--root", u.DestDir, 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
}

if !shouldExist && !exists {
return nil
}

args := []string{"--root", u.DestDir}

if g.Gid != nil {
Expand All @@ -263,7 +302,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
}

0 comments on commit e0d57f5

Please sign in to comment.