run: user LookupId
Signed-off-by: Yoan Blanc <yoan@dosimple.ch>
This commit is contained in:
parent
c553184416
commit
c7028c6d2f
|
|
@ -20,8 +20,16 @@ RUN touch $HOME/hello
|
||||||
# testuser1 with the default home created by useradd.
|
# testuser1 with the default home created by useradd.
|
||||||
|
|
||||||
RUN groupadd testgroup && \
|
RUN groupadd testgroup && \
|
||||||
useradd --create-home --gid testgroup alice
|
useradd --create-home --gid testgroup alice && \
|
||||||
|
useradd --create-home --uid 1111 --home-dir /home/john --gid testgroup bob
|
||||||
|
|
||||||
USER alice:testgroup
|
USER alice:testgroup
|
||||||
|
|
||||||
RUN touch $HOME/hello
|
RUN touch $HOME/hello
|
||||||
|
|
||||||
|
USER bob
|
||||||
|
RUN touch $HOME/hello
|
||||||
|
|
||||||
|
USER root
|
||||||
|
|
||||||
|
USER 1111
|
||||||
|
RUN touch $HOME/world
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ type RunCommand struct {
|
||||||
|
|
||||||
// for testing
|
// for testing
|
||||||
var (
|
var (
|
||||||
userLookup = user.Lookup
|
userLookup = user.Lookup
|
||||||
|
userLookupId = user.LookupId
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
|
||||||
|
|
@ -68,18 +69,29 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
|
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
var userStr string
|
|
||||||
|
u := config.User
|
||||||
|
userAndGroup := strings.Split(u, ":")
|
||||||
|
userStr, err := util.ResolveEnvironmentReplacement(userAndGroup[0], replacementEnvs, false)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "resolving user %s", userAndGroup[0])
|
||||||
|
}
|
||||||
|
|
||||||
// If specified, run the command as a specific user
|
// If specified, run the command as a specific user
|
||||||
if config.User != "" {
|
if userStr != "" {
|
||||||
userStr = config.User
|
uid, gid, err := util.GetUIDAndGIDFromString(userStr, true)
|
||||||
uid, gid, err := util.GetUIDAndGIDFromString(config.User, true)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}
|
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Env = addDefaultHOME(userStr, replacementEnvs)
|
env, err := addDefaultHOME(userStr, replacementEnvs)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "adding default HOME variable")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Env = env
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return errors.Wrap(err, "starting command")
|
return errors.Wrap(err, "starting command")
|
||||||
|
|
@ -102,32 +114,31 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
|
||||||
}
|
}
|
||||||
|
|
||||||
// addDefaultHOME adds the default value for HOME if it isn't already set
|
// addDefaultHOME adds the default value for HOME if it isn't already set
|
||||||
func addDefaultHOME(u string, envs []string) []string {
|
func addDefaultHOME(u string, envs []string) ([]string, error) {
|
||||||
for _, env := range envs {
|
for _, env := range envs {
|
||||||
split := strings.SplitN(env, "=", 2)
|
split := strings.SplitN(env, "=", 2)
|
||||||
if split[0] == constants.HOME {
|
if split[0] == constants.HOME {
|
||||||
return envs
|
return envs, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If user isn't set, set default value of HOME
|
// If user isn't set, set default value of HOME
|
||||||
if u == "" || u == constants.RootUser {
|
if u == "" || u == constants.RootUser {
|
||||||
return append(envs, fmt.Sprintf("%s=%s", constants.HOME, constants.DefaultHOMEValue))
|
return append(envs, fmt.Sprintf("%s=%s", constants.HOME, constants.DefaultHOMEValue)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If user is set to username, set value of HOME to /home/${user}
|
// If user is set to username, set value of HOME to /home/${user}
|
||||||
// Otherwise the user is set to uid and HOME is /
|
// Otherwise the user is set to uid and HOME is /
|
||||||
home := "/"
|
|
||||||
userObj, err := userLookup(u)
|
userObj, err := userLookup(u)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if userObj.HomeDir != "" {
|
if uo, e := userLookupId(u); e == nil {
|
||||||
home = userObj.HomeDir
|
userObj = uo
|
||||||
} else {
|
} else {
|
||||||
home = fmt.Sprintf("/home/%s", userObj.Username)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(envs, fmt.Sprintf("%s=%s", constants.HOME, home))
|
return append(envs, fmt.Sprintf("%s=%s", constants.HOME, userObj.HomeDir)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns some information about the command for the image config
|
// String returns some information about the command for the image config
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package commands
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
|
@ -33,11 +34,13 @@ import (
|
||||||
|
|
||||||
func Test_addDefaultHOME(t *testing.T) {
|
func Test_addDefaultHOME(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
user string
|
user string
|
||||||
mockUser *user.User
|
mockUser *user.User
|
||||||
initial []string
|
lookupError error
|
||||||
expected []string
|
mockUserId *user.User
|
||||||
|
initial []string
|
||||||
|
expected []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "HOME already set",
|
name: "HOME already set",
|
||||||
|
|
@ -78,31 +81,19 @@ func Test_addDefaultHOME(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "HOME not set and user set",
|
name: "USER is set using the UID",
|
||||||
user: "www-add",
|
user: "newuser",
|
||||||
mockUser: &user.User{
|
lookupError: errors.New("User not found"),
|
||||||
Username: "www-add",
|
mockUserId: &user.User{
|
||||||
|
Username: "user",
|
||||||
|
HomeDir: "/home/user",
|
||||||
},
|
},
|
||||||
initial: []string{
|
initial: []string{
|
||||||
"PATH=/something/else",
|
"PATH=/something/else",
|
||||||
},
|
},
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"PATH=/something/else",
|
"PATH=/something/else",
|
||||||
"HOME=/home/www-add",
|
"HOME=/home/user",
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "HOME not set and user is set",
|
|
||||||
user: "newuser",
|
|
||||||
mockUser: &user.User{
|
|
||||||
Username: "newuser",
|
|
||||||
},
|
|
||||||
initial: []string{
|
|
||||||
"PATH=/something/else",
|
|
||||||
},
|
|
||||||
expected: []string{
|
|
||||||
"PATH=/something/else",
|
|
||||||
"HOME=/home/newuser",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -122,10 +113,14 @@ func Test_addDefaultHOME(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
userLookup = func(username string) (*user.User, error) { return test.mockUser, nil }
|
userLookup = func(username string) (*user.User, error) { return test.mockUser, test.lookupError }
|
||||||
defer func() { userLookup = user.Lookup }()
|
userLookupId = func(username string) (*user.User, error) { return test.mockUserId, nil }
|
||||||
actual := addDefaultHOME(test.user, test.initial)
|
defer func() {
|
||||||
testutil.CheckErrorAndDeepEqual(t, false, nil, test.expected, actual)
|
userLookup = user.Lookup
|
||||||
|
userLookupId = user.LookupId
|
||||||
|
}()
|
||||||
|
actual, err := addDefaultHOME(test.user, test.initial)
|
||||||
|
testutil.CheckErrorAndDeepEqual(t, false, err, test.expected, actual)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue