Skip to content

Commit

Permalink
falling back to root as home directory for keep users when expected h…
Browse files Browse the repository at this point in the history
…ome directory already exists
  • Loading branch information
eriktate committed Oct 10, 2024
1 parent 432b6ae commit badc90c
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 24 deletions.
20 changes: 20 additions & 0 deletions integration/hostuser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,26 @@ func TestRootHostUsers(t *testing.T) {
})
})

t.Run("test create permanent user with pre-existing home dir", func(t *testing.T) {
users := srv.NewHostUsers(context.Background(), presence, "host_uuid")
expectedHome := filepath.Join("/home", testuser)
require.NoDirExists(t, expectedHome)

require.NoError(t, os.Mkdir(expectedHome, 0700))
t.Cleanup(func() {
os.RemoveAll(expectedHome)
})
closer, err := users.UpsertUser(testuser, services.HostUsersInfo{Mode: services.HostUserModeKeep})
require.NoError(t, err)
require.Nil(t, closer)
t.Cleanup(func() { cleanupUsersAndGroups([]string{testuser}, []string{types.TeleportKeepGroup}) })

u, err := user.Lookup(testuser)
require.NoError(t, err)
require.Equal(t, string(os.PathSeparator), u.HomeDir)
require.DirExists(t, expectedHome)
})

t.Run("test create sudoers enabled users", func(t *testing.T) {
if _, err := exec.LookPath("visudo"); err != nil {
t.Skip("Visudo not found on path")
Expand Down
62 changes: 38 additions & 24 deletions lib/srv/usermgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ type HostUsersBackend interface {
DeleteUser(name string) error
// CreateHomeDirectory creates the users home directory and copies in /etc/skel
CreateHomeDirectory(userHome string, uid, gid string) error
// SetHomeDirectory sets a given user's home directory.
SetHomeDirectory(username, home string) error
// GetDefaultHomeDirectory returns the default home directory path for the given user
GetDefaultHomeDirectory(user string) (string, error)
}
Expand Down Expand Up @@ -246,14 +248,6 @@ var unmanagedUserErr = errors.New("user not managed by teleport")
var staticConversionErr = errors.New("managed host users can not be converted to or from a static host user")

func (u *HostUserManagement) updateUser(hostUser HostUser, ui services.HostUsersInfo) error {
ctx := u.ctx
log := u.log.With(
"host_username", hostUser.Name,
"mode", ui.Mode,
"uid", hostUser.UID,
"gid", hostUser.GID,
)

if ui.Mode == services.HostUserModeKeep {
_, hasKeepGroup := hostUser.Groups[types.TeleportKeepGroup]
if !hasKeepGroup {
Expand All @@ -262,9 +256,8 @@ func (u *HostUserManagement) updateUser(hostUser HostUser, ui services.HostUsers
return trace.Wrap(err)
}

log.DebugContext(ctx, "Creating home directory", "home_path", home)
err = u.backend.CreateHomeDirectory(home, hostUser.UID, hostUser.GID)
if err != nil && !os.IsExist(err) {
hostUser.Home = home
if err := u.setupHomeDirectory(hostUser); err != nil {
return trace.Wrap(err)
}
}
Expand Down Expand Up @@ -349,19 +342,7 @@ func (u *HostUserManagement) createUser(name string, ui services.HostUsersInfo)
return trace.Wrap(err)
}

if userOpts.Home != "" {
log.InfoContext(u.ctx, "Attempting to create home directory", "home", userOpts.Home, "gid", userOpts.GID)
if err := u.backend.CreateHomeDirectory(userOpts.Home, user.Uid, user.Gid); err != nil {
if !os.IsExist(err) {
return trace.Wrap(err)
}
log.InfoContext(u.ctx, "Home directory already exists", "home", userOpts.Home, "gid", userOpts.GID)
} else {
log.InfoContext(u.ctx, "Created home directory", "home", userOpts.Home, "gid", userOpts.GID)
}
}

return nil
return trace.Wrap(u.setupHomeDirectory(HostUser{Name: user.Username, Home: userOpts.Home, UID: user.Uid, GID: user.Gid}))
})

return trace.Wrap(err)
Expand Down Expand Up @@ -739,3 +720,36 @@ func ResolveGroups(logger *slog.Logger, hostUser *HostUser, ui services.HostUser
log.InfoContext(context.Background(), "Resolved user groups", "before", currentGroups, "after", groupSlice)
return groupSlice, nil
}

// setupHomeDirectory tries to create a home directory for the given HostUser. If the directory cannot be created, the user's home directory
// is reset to the root directory
func (u *HostUserManagement) setupHomeDirectory(hostUser HostUser) error {
log := u.log.With(
"host_username", hostUser.Name,
"uid", hostUser.UID,
"gid", hostUser.GID,
"home", hostUser.Home,
)

if hostUser.Home == "" {
return nil
}

log.InfoContext(u.ctx, "Attempting to create home directory")
if err := u.backend.CreateHomeDirectory(hostUser.Home, hostUser.UID, hostUser.GID); err != nil {
if os.IsExist(err) {
log.InfoContext(u.ctx, "Home directory already exists")
} else {
log.WarnContext(u.ctx, "Could not create home directory", "error", err)
}

if err := u.backend.SetHomeDirectory(hostUser.Name, "/"); err != nil {
log.WarnContext(u.ctx, "Could not unset user home after failing to create directory, host may be inaccessible as this user")
return trace.WrapWithMessage(err, "resetting user home after failing to create directory")
}

return nil
}

return nil
}
10 changes: 10 additions & 0 deletions lib/srv/usermgmt_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,13 @@ func (u *HostUsersProvisioningBackend) CreateHomeDirectory(userHome, uidS, gidS

return nil
}

// SetHomeDirectory sets the home directory path for an existing user.
func (u *HostUsersProvisioningBackend) SetHomeDirectory(username, home string) error {
if home == "" {
home = string(os.PathSeparator)
}

_, err := host.SetUserHome(username, home)
return trace.Wrap(err)
}
4 changes: 4 additions & 0 deletions lib/srv/usermgmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ func (tm *testHostUserBackend) CreateHomeDirectory(user, uid, gid string) error
return nil
}

func (tm *testHostUserBackend) SetHomeDirectory(username, home string) error {
return nil
}

func (tm *testHostUserBackend) GetDefaultHomeDirectory(user string) (string, error) {
return "", nil
}
Expand Down
13 changes: 13 additions & 0 deletions lib/utils/host/hostusers.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,16 @@ func CheckSudoers(contents []byte) error {
}
return trace.Wrap(err)
}

func SetUserHome(username, home string) (exitCode int, err error) {
usermodBin, err := exec.LookPath("usermod")
if err != nil {
return -1, trace.Wrap(err, "cant find usermod binary")
}

// usermod -G (replace groups) (username)
cmd := exec.Command(usermodBin, "--home", home, username)
output, err := cmd.CombinedOutput()
log.Debugf("%s output: %s", cmd.Path, string(output))
return cmd.ProcessState.ExitCode(), trace.Wrap(err)
}

0 comments on commit badc90c

Please sign in to comment.