Skip to content

Commit

Permalink
feature: user configuration for cri manager
Browse files Browse the repository at this point in the history
Signed-off-by: YaoZengzeng <[email protected]>
  • Loading branch information
YaoZengzeng committed Feb 11, 2018
1 parent 4eb0189 commit 03d0a3b
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 22 deletions.
2 changes: 2 additions & 0 deletions cli/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type container struct {
env []string
entrypoint string
workdir string
user string
hostname string
cpushare int64
cpusetcpus string
Expand Down Expand Up @@ -120,6 +121,7 @@ func (c *container) config() (*types.ContainerCreateConfig, error) {
Env: c.env,
Entrypoint: strings.Fields(c.entrypoint),
WorkingDir: c.workdir,
User: c.user,
Hostname: strfmt.Hostname(c.hostname),
Labels: labels,
},
Expand Down
1 change: 1 addition & 0 deletions cli/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func (cc *CreateCommand) addFlags() {
flagSet.StringSliceVarP(&cc.labels, "label", "l", nil, "Set label for a container")
flagSet.StringVar(&cc.entrypoint, "entrypoint", "", "Overwrite the default entrypoint")
flagSet.StringVarP(&cc.workdir, "workdir", "w", "", "Set the working directory in a container")
flagSet.StringVarP(&cc.user, "user", "u", "", "UID")
flagSet.StringVar(&cc.hostname, "hostname", "", "Set container's hostname")
flagSet.Int64Var(&cc.cpushare, "cpu-share", 0, "CPU shares")
flagSet.StringVar(&cc.cpusetcpus, "cpuset-cpus", "", "CPUs in cpuset")
Expand Down
1 change: 1 addition & 0 deletions cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (rc *RunCommand) addFlags() {
flagSet.StringSliceVarP(&rc.labels, "label", "l", nil, "Set label for a container")
flagSet.StringVar(&rc.entrypoint, "entrypoint", "", "Overwrite the default entrypoint")
flagSet.StringVarP(&rc.workdir, "workdir", "w", "", "Set the working directory in a container")
flagSet.StringVarP(&rc.user, "user", "u", "", "UID")
flagSet.BoolVarP(&rc.detach, "detach", "d", false, "Run container in background and print container ID")
flagSet.StringVar(&rc.hostname, "hostname", "", "Set container's hostname")
flagSet.Int64Var(&rc.cpushare, "cpu-share", 0, "CPU shares")
Expand Down
3 changes: 3 additions & 0 deletions daemon/mgr/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ func (mgr *ContainerManager) StartExec(ctx context.Context, execid string, confi
Cwd: "/",
Env: c.Config().Env,
}
if len(execConfig.User) == 0 {
setupProcessUser(ctx, c.meta, &SpecWrapper{s: &specs.Spec{Process: process}})
}

return mgr.Client.ExecContainer(ctx, &ctrd.Process{
ContainerID: execConfig.ContainerID,
Expand Down
15 changes: 15 additions & 0 deletions daemon/mgr/cri_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,23 @@ func modifyHostConfig(sc *runtime.LinuxContainerSecurityContext, hostConfig *api
return nil
}

// modifyContainerConfig applies container security context config to pouch's Config.
func modifyContainerConfig(sc *runtime.LinuxContainerSecurityContext, config *apitypes.ContainerConfig) {
if sc == nil {
return
}
if sc.RunAsUser != nil {
config.User = strconv.FormatInt(sc.GetRunAsUser().Value, 10)
}
if sc.RunAsUsername != "" {
config.User = sc.RunAsUsername
}
}

// applyContainerSecurityContext updates pouch container options according to security context.
func applyContainerSecurityContext(lc *runtime.LinuxContainerConfig, podSandboxID string, config *apitypes.ContainerConfig, hc *apitypes.HostConfig) error {
modifyContainerConfig(lc.SecurityContext, config)

err := modifyHostConfig(lc.SecurityContext, hc)
if err != nil {
return err
Expand Down
34 changes: 14 additions & 20 deletions daemon/mgr/spec_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package mgr

import (
"context"
"fmt"
"strconv"
"strings"

Expand Down Expand Up @@ -59,27 +58,22 @@ func setupProcessTTY(ctx context.Context, c *ContainerMeta, spec *SpecWrapper) e
}

func setupProcessUser(ctx context.Context, c *ContainerMeta, spec *SpecWrapper) (err error) {
if c.Config.User != "" {
fields := strings.SplitN(c.Config.User, ":", 2)
var u, g string
u = fields[0]
if len(fields) == 2 {
g = fields[1]
}
user := &specs.User{}
if uid, err := strconv.Atoi(u); err == nil {
user.UID = uint32(uid)
} else {
user.Username = u
}
gid, err := strconv.Atoi(g)
if err != nil || gid <= 0 {
return fmt.Errorf("invalid gid: %d", gid)
}
user.GID = uint32(gid)
// The user option is complicated, now we only handle case "uid".
// TODO: handle other cases like "user", "uid:gid", etc.
if c.Config.User == "" {
return nil
}

//TODO security config (including both seccomp and selinux)
fields := strings.Split(c.Config.User, ":")
var u string
u = fields[0]
user := specs.User{}
if uid, err := strconv.Atoi(u); err == nil {
user.UID = uint32(uid)
} else {
user.Username = u
}
spec.s.Process.User = user

return nil
}
4 changes: 2 additions & 2 deletions hack/cri-test/test-cri.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ POUCH_SOCK="/var/run/pouchcri.sock"

# CRI_FOCUS focuses the test to run.
# With the CRI manager completes its function, we may need to expand this field.
CRI_FOCUS=${CRI_FOCUS:-"PodSandbox|AppArmor|Privileged is true|basic operations on container|Runtime info|mount propagation|volume and device"}
CRI_FOCUS=${CRI_FOCUS:-"PodSandbox|AppArmor|Privileged is true|basic operations on container|Runtime info|mount propagation|volume and device|RunAsUser"}

# CRI_SKIP skips the test to skip.
CRI_SKIP=${CRI_SKIP:-""}
CRI_SKIP=${CRI_SKIP:-"RunAsUserName"}
# REPORT_DIR is the the directory to store test logs.
REPORT_DIR=${REPORT_DIR:-"/tmp/test-cri"}

Expand Down
17 changes: 17 additions & 0 deletions test/cli_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,20 @@ func (suite *PouchCreateSuite) TestCreateWithWorkDir(c *check.C) {

// TODO: check the work directory has been created.
}

// TestCreateWithUser tests creating container with user works.
func (suite *PouchCreateSuite) TestCreateWithUser(c *check.C) {
name := "TestCreateWithUser"
user := "1001"

res := command.PouchRun("create", "--name", name, "--user", user, busyboxImage)
res.Assert(c, icmd.Success)

output := command.PouchRun("inspect", name).Stdout()

result := &types.ContainerJSON{}
if err := json.Unmarshal([]byte(output), result); err != nil {
c.Errorf("failed to decode inspect output: %v", err)
}
c.Assert(result.Config.User, check.Equals, user)
}
15 changes: 15 additions & 0 deletions test/cli_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,21 @@ func (suite *PouchRunSuite) TestRunWithSysctls(c *check.C) {
command.PouchRun("rm", "-f", name).Assert(c, icmd.Success)
}

// TestRunWithUser is to verify run container with user.
func (suite *PouchRunSuite) TestRunWithUser(c *check.C) {
user := "1001"
name := "run-user"

res := command.PouchRun("run", "--name", name, "--user", user, busyboxImage)
res.Assert(c, icmd.Success)

output := command.PouchRun("exec", name, "id", "-u").Stdout()
if !strings.Contains(output, user) {
c.Fatalf("failed to run a container with user: %s", output)
}
command.PouchRun("rm", "-f", name).Assert(c, icmd.Success)
}

// TestRunWithAppArmor is to verify run container with security option AppArmor.
func (suite *PouchRunSuite) TestRunWithAppArmor(c *check.C) {
appArmor := "apparmor=unconfined"
Expand Down
12 changes: 12 additions & 0 deletions test/cli_start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,18 @@ func (suite *PouchStartSuite) TestStartWithWorkDir(c *check.C) {
}
}

// TestStartWithUser starts a container with user.
func (suite *PouchStartSuite) TestStartWithUser(c *check.C) {
name := "start-user"
user := "1001"

command.PouchRun("create", "--name", name, "--user", user, busyboxImage, "id", "-u")
output := command.PouchRun("start", "-a", name).Stdout()
if !strings.Contains(output, user) {
c.Errorf("failed to start a container with user: %s", output)
}
}

// TestStartWithHostname starts a container with hostname.
func (suite *PouchStartSuite) TestStartWithHostname(c *check.C) {
name := "start-hostname"
Expand Down

0 comments on commit 03d0a3b

Please sign in to comment.