Skip to content

Commit

Permalink
specify the user and group to be executed for the exec of kwokctl
Browse files Browse the repository at this point in the history
  • Loading branch information
lianghao208 committed Jun 25, 2023
1 parent 876ac0f commit e97540f
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 0 deletions.
10 changes: 10 additions & 0 deletions pkg/apis/internalversion/exec_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type ExecTargetLocal struct {
WorkDir string
// Envs is a list of environment variables to exec with.
Envs []EnvVar
// User is the user to exec.
User User
}

// EnvVar represents an environment variable present in a Container.
Expand All @@ -59,3 +61,11 @@ type EnvVar struct {
// Value of the environment variable.
Value string
}

// User is the username and group name in a Container.
type User struct {
// Name of the user.
Name string
// Group of the user.
Group string
}
38 changes: 38 additions & 0 deletions pkg/apis/internalversion/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions pkg/apis/internalversion/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions pkg/apis/v1alpha1/exec_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ type ExecTargetLocal struct {
WorkDir string `json:"workDir,omitempty"`
// Envs is a list of environment variables to exec with.
Envs []EnvVar `json:"envs,omitempty"`
// User is the user to exec.
User User `json:"user,omitempty"`
}

// EnvVar represents an environment variable present in a Container.
Expand All @@ -68,3 +70,11 @@ type EnvVar struct {
// Value of the environment variable.
Value string `json:"value,omitempty"`
}

// User is the username and group name in a Container.
type User struct {
// Name of the user.
Name string `json:"name,omitempty"`
// Group of the user.
Group string `json:"group,omitempty"`
}
17 changes: 17 additions & 0 deletions pkg/apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions pkg/kwok/server/debugging_exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ import (
"sigs.k8s.io/kwok/pkg/utils/slices"
)

const (
defaultUsername = "guest"
defaultGroupName = "guest"
)

// ExecInContainer executes a command in a container.
func (s *Server) ExecInContainer(ctx context.Context, podName, podNamespace string, uid types.UID, container string, cmd []string, in io.Reader, out, errOut io.WriteCloser, tty bool, resize <-chan clientremotecommand.TerminalSize) error {
execTarget, err := s.getExecTarget(podName, podNamespace, container)
Expand All @@ -53,6 +58,16 @@ func (s *Server) ExecInContainer(ctx context.Context, podName, podNamespace stri
ctx = exec.WithEnv(ctx, envs)
}

// Set the user.
username, groupName := defaultUsername, defaultGroupName
if execTarget.Local.User.Name != "" {
username = execTarget.Local.User.Name
}
if execTarget.Local.User.Group != "" {
groupName = execTarget.Local.User.Group
}
ctx = exec.WithUser(ctx, username, groupName)

// Set the working directory.
if execTarget.Local.WorkDir != "" {
ctx = exec.WithDir(ctx, execTarget.Local.WorkDir)
Expand Down
47 changes: 47 additions & 0 deletions pkg/utils/exec/cmd_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import (
"context"
"os"
"os/exec"
"os/user"
"strconv"
"syscall"

"sigs.k8s.io/kwok/pkg/log"
)

func startProcess(ctx context.Context, name string, arg ...string) *exec.Cmd {
Expand All @@ -47,3 +51,46 @@ func isRunning(pid int) bool {
err = process.Signal(syscall.Signal(0))
return err == nil
}

func createAndSetUser(ctx context.Context, username, groupName string, cmd *exec.Cmd) {
logger := log.FromContext(ctx)

_, err := exec.Command("groupadd", groupName).Output()
if err != nil {
logger.Warn("failed to add group", "error", err.Error())
}

_, err = exec.Command("useradd", "-g", username, groupName).Output()
if err != nil {
logger.Warn("failed to add user", "error", err.Error())
}

u, err := user.Lookup(username)
if err != nil {
logger.Warn("failed to lookup user", "error", err.Error())
return
}
g, err := user.LookupGroup(groupName)
if err != nil {
logger.Warn("failed to lookup group", "error", err.Error())
return
}

uid, err := strconv.Atoi(u.Uid)
if err != nil {
logger.Warn("failed to convert uid to integers", "error", err.Error())
return
}
gid, err := strconv.Atoi(g.Gid)
if err != nil {
logger.Warn("failed to convert gid to integers", "error", err.Error())
return
}
logger.Info("username", username, "group name", groupName)
cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uint32(uid),
Gid: uint32(gid),
},
}
}
8 changes: 8 additions & 0 deletions pkg/utils/exec/cmd_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"syscall"

"golang.org/x/sys/windows"

"sigs.k8s.io/kwok/pkg/log"
)

func startProcess(ctx context.Context, name string, arg ...string) *exec.Cmd {
Expand All @@ -47,3 +49,9 @@ func isRunning(pid int) bool {
_, err := os.FindProcess(pid)
return err == nil
}

func createAndSetUser(ctx context.Context, username, groupName string, cmd *exec.Cmd) {
logger := log.FromContext(ctx)
err := "user and group are not supported in windows, ignoring the custom user and group"
logger.Warn(err)
}
15 changes: 15 additions & 0 deletions pkg/utils/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ type execOptions struct {
Dir string
// Env is the environment variables of the command.
Env []string
// Username is the username of the command
Username string
// GroupName is the group name of the command
GroupName string
// IOStreams contains the standard streams.
IOStreams
// PipeStdin is true if the command's stdin should be piped.
Expand All @@ -65,6 +69,14 @@ func WithEnv(ctx context.Context, env []string) context.Context {
return ctx
}

// WithUser returns a context with the given username and group name.
func WithUser(ctx context.Context, username, groupName string) context.Context {
ctx, opt := withExecOptions(ctx)
opt.Username = username
opt.GroupName = groupName
return ctx
}

// WithDir returns a context with the given working directory.
func WithDir(ctx context.Context, dir string) context.Context {
ctx, opt := withExecOptions(ctx)
Expand Down Expand Up @@ -141,6 +153,9 @@ func Exec(ctx context.Context, name string, arg ...string) error {
cmd.Env = opt.Env
cmd.Env = append(os.Environ(), cmd.Env...)
}
if opt.Username != "" && opt.GroupName != "" {
createAndSetUser(ctx, opt.Username, opt.GroupName, cmd)
}
cmd.Dir = opt.Dir
if opt.In != nil {
if opt.PipeStdin {
Expand Down
56 changes: 56 additions & 0 deletions site/content/en/docs/generated/apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -3219,6 +3219,19 @@ string
<p>Envs is a list of environment variables to exec with.</p>
</td>
</tr>
<tr>
<td>
<code>user</code>
<em>
<a href="#kwok.x-k8s.io/v1alpha1.User">
User
</a>
</em>
</td>
<td>
<p>User is the user to exec.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="kwok.x-k8s.io/v1alpha1.ExpressionFromSource">
Expand Down Expand Up @@ -4355,3 +4368,46 @@ bool
</tr>
</tbody>
</table>
<h3 id="kwok.x-k8s.io/v1alpha1.User">
User
<a href="#kwok.x-k8s.io%2fv1alpha1.User"> #</a>
</h3>
<p>
<em>Appears on: </em>
<a href="#kwok.x-k8s.io/v1alpha1.ExecTargetLocal">ExecTargetLocal</a>
</p>
<p>
<p>User is the username and group name in a Container.</p>
</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>name</code>
<em>
string
</em>
</td>
<td>
<p>Name of the user.</p>
</td>
</tr>
<tr>
<td>
<code>group</code>
<em>
string
</em>
</td>
<td>
<p>Group of the user.</p>
</td>
</tr>
</tbody>
</table>
3 changes: 3 additions & 0 deletions test/kwokctl/exec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ spec:
envs:
- name: TEST_ENV
value: test
user:
name: test
group: test
2 changes: 2 additions & 0 deletions test/kwokctl/kwokctl_exec_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ function main() {
test_apply_node_and_pod "${name}" || failed+=("apply_node_and_pod")
test_exec "${name}" other pod/fake-pod "pwd" "/tmp" || failed+=("${name}_target_exec")
test_exec "${name}" default deploy/fake-pod "env" "TEST_ENV=test" || failed+=("${name}_cluster_default_exec")
test_exec "${name}" default deploy/fake-pod "echo $USER" "test" || failed+=("${name}_cluster_default_exec")
test_exec "${name}" default deploy/fake-pod "getent group $GROUPS | cut -d: -f1" "test" || failed+=("${name}_cluster_default_exec")
delete_cluster "${name}"
done

Expand Down

0 comments on commit e97540f

Please sign in to comment.