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 Jul 6, 2023
1 parent ef999cc commit 9f57d24
Show file tree
Hide file tree
Showing 29 changed files with 601 additions and 56 deletions.
Empty file modified hack/boilerplate/boilerplate.go.txt
100644 → 100755
Empty file.
4 changes: 3 additions & 1 deletion images/kwok/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ ARG BASE_IMAGE=docker.io/library/alpine:3.18
FROM --platform=$TARGETPLATFORM $BASE_IMAGE AS cache
ARG TARGETPLATFORM
COPY --chmod=0755 bin/$TARGETPLATFORM/kwok /usr/local/bin/
COPY --chmod=0755 images/kwok/entrypoint.sh /entrypoint.sh
COPY --chmod=0755 images/kwok/setuser.sh /setuser.sh

ENTRYPOINT ["/usr/local/bin/kwok"]
ENTRYPOINT ["/entrypoint.sh"]
20 changes: 20 additions & 0 deletions images/kwok/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh
# Copyright 2023 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

if [ -n "${USER_NAME}" ] && [ -n "${USER_UID}" ] && [ -n "${USER_GROUP_NAME}" ] && [ -n "${USER_GID}" ] && [ -n "${USER_HOME}" ] && [ -n "${USER_SHELL}" ]; then
/setuser.sh --username="${USER_NAME}" --uid="${USER_UID}" --groupname="${USER_GROUP_NAME}" --gid="${USER_GID}" --home="${USER_HOME}" --shell="${USER_SHELL}"
fi

/usr/local/bin/kwok "$@"
174 changes: 174 additions & 0 deletions images/kwok/setuser.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
#!/bin/sh
# Copyright 2023 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# command_exist checks if a command exists.
command_exist() {
type "${1}" >/dev/null 2>&1
}

# add_group adds a group to the system. It tries to use addgroup or groupadd if they exist,
# otherwise it writes directly to /etc/group.
add_group() {
gid="$1"
groupname="$2"
if command_exist addgroup; then # use addgroup if it exists
addgroup --gid "${gid}" "${groupname}"
elif command_exist groupadd; then # use groupadd if it exists
groupadd --gid "${gid}" "${groupname}"
else # write /etc/group directly
echo "${groupname}:x:${gid}:" >>/etc/group
fi
}

# add_user adds a user to the system. It tries to use adduser or useradd if they exist,
# otherwise it writes directly to /etc/passwd.
add_user() {
uid="$1"
username="$2"
gid="$3"
home="$4"
shell="$5"
if command_exist adduser; then # use adduser if it exists
adduser -u "${uid}" -G "${groupname}" -h "${home}" -s "${shell}" "${username}" -D
elif command_exist useradd; then # use useradd if it exists
useradd -u "${uid}" -G "${groupname}" -h "${home}" -s "${shell}" "${username}" -D
else # write /etc/passwd directly
echo "${username}:x:${uid}:${gid}::${home}:${shell}" >>/etc/passwd
fi
}

# get_ent gets an entry from a file. It tries to use getent if it exists,
get_ent() {
name="$1"
id="$2"
if command_exist getent; then
getent "${name}" "${id}"
else
case "${name}" in
group)
grep ":${id}:" /etc/group
;;
passwd)
grep ":${id}:${id}:" /etc/passwd
;;
*)
log "get_ent: unknown name ${name}"
exit 1
;;
esac
fi
}

# log prints a log message.
log() {
echo "$*" >&2
}

# usage prints the usage of this script.
usage() {
cat <<EOF >&2
Usage: $(basename "$0") [options]
--username: the name of the user to create
--uid: the uid of the user to create
--groupname: the name of the group to create (defaults to username)
--gid: the gid of the user to create (defaults to uid)
--home: the home directory of the user to create (defaults to /home/<username>)
--shell: the shell of the user to create (defaults to /bin/sh)
--help: print this help message
EOF
}

USER_NAME=""
USER_UID=""
USER_GROUP_NAME=""
USER_GID=""
USER_HOME=""
USER_SHELL=""
args() {
while [ $# -gt 0 ]; do
arg="$1"
case "${arg}" in
--username | --username=*)
[ "${arg#*=}" != "${arg}" ] && USER_NAME="${arg#*=}" || { USER_NAME="${2}" && shift; } || : shift
;;
--uid | --uid=*)
[ "${arg#*=}" != "${arg}" ] && USER_UID="${arg#*=}" || { USER_UID="${2}" && shift; } || : shift
;;
--groupname | --groupname=*)
[ "${arg#*=}" != "${arg}" ] && USER_GROUP_NAME="${arg#*=}" || { USER_GROUP_NAME="${2}" && shift; } || : shift
;;
--gid | --gid=*)
[ "${arg#*=}" != "${arg}" ] && USER_GID="${arg#*=}" || { USER_GID="${2}" && shift; } || : shift
;;
--home | --home=*)
[ "${arg#*=}" != "${arg}" ] && USER_HOME="${arg#*=}" || { USER_HOME="${2}" && shift; } || : shift
;;
--shell | --shell=*)
[ "${arg#*=}" != "${arg}" ] && USER_SHELL="${arg#*=}" || { USER_SHELL="${2}" && shift; } || : shift
;;
--help | -h)
usage
exit 0
;;
*)
log "Unknown option: $1"
usage
exit 1
;;
esac
shift
done
}

main() {
args "$@"
USER_GROUP_NAME="${USER_GROUP_NAME:-${USER_NAME}}"
USER_GID="${USER_GID:-${USER_UID}}"
USER_HOME="${USER_HOME:-/home/${USER_NAME}}"
USER_SHELL="${USER_SHELL:-/bin/sh}"
if [ -z "${USER_NAME}" ] && [ -z "${USER_GROUP_NAME}" ]; then
log "username or groupname is required"
usage
return 1
fi
if [ -n "${USER_GROUP_NAME}" ] && [ -z "${USER_GID}" ]; then
log "groupname requires gid"
usage
return 1
fi
if [ -n "${USER_NAME}" ] && [ -z "${USER_UID}" ]; then
log "username requires uid"
usage
return 1
fi
if [ -n "${USER_GROUP_NAME}" ] && [ -n "${USER_GID}" ]; then
if ! get_ent group "${USER_GID}"; then
log "Group ${USER_GROUP_NAME} (${USER_GID}) does not exist, creating."
add_group "${USER_GID}" "${USER_GROUP_NAME}"
else
log "Group ${USER_GROUP_NAME} (${USER_GID}) already exists, not creating."
fi
fi
if [ -n "${USER_NAME}" ] && [ -n "${USER_UID}" ]; then
if ! get_ent passwd "${USER_UID}"; then
log "User ${USER_NAME} (${USER_UID}) does not exist, creating."
add_user "${USER_UID}" "${USER_NAME}" "${USER_GID}" "${USER_HOME}" "${USER_SHELL}"
else
log "User ${USER_NAME} (${USER_UID}) already exists, not creating."
fi
fi
}

main "$@"
14 changes: 14 additions & 0 deletions kustomize/crd/bases/kwok.x-k8s.io_clusterexecs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ spec:
- name
type: object
type: array
securityContext:
description: SecurityContext is the user context to exec.
properties:
runAsGroup:
description: RunAsGroup is the existing gid to run exec
command in container process.
format: int64
type: integer
runAsUser:
description: RunAsUser is the existing uid to run exec
command in container process.
format: int64
type: integer
type: object
workDir:
description: WorkDir is the working directory to exec with.
type: string
Expand Down
14 changes: 14 additions & 0 deletions kustomize/crd/bases/kwok.x-k8s.io_execs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ spec:
- name
type: object
type: array
securityContext:
description: SecurityContext is the user context to exec.
properties:
runAsGroup:
description: RunAsGroup is the existing gid to run exec
command in container process.
format: int64
type: integer
runAsUser:
description: RunAsUser is the existing uid to run exec
command in container process.
format: int64
type: integer
type: object
workDir:
description: WorkDir is the working directory to exec with.
type: string
Expand Down
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
// SecurityContext is the user context to exec.
SecurityContext *SecurityContext
}

// 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
}

// SecurityContext specifies the existing uid and gid to run exec command in container process.
type SecurityContext struct {
// RunAsUser is the existing uid to run exec command in container process.
RunAsUser *int64
// RunAsGroup is the existing gid to run exec command in container process.
RunAsGroup *int64
}
34 changes: 34 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.

31 changes: 31 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 @@ -75,6 +75,8 @@ type ExecTargetLocal struct {
WorkDir string `json:"workDir,omitempty"`
// Envs is a list of environment variables to exec with.
Envs []EnvVar `json:"envs,omitempty"`
// SecurityContext is the user context to exec.
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
}

// EnvVar represents an environment variable present in a Container.
Expand All @@ -87,6 +89,14 @@ type EnvVar struct {
Value string `json:"value,omitempty"`
}

// SecurityContext specifies the existing uid and gid to run exec command in container process.
type SecurityContext struct {
// RunAsUser is the existing uid to run exec command in container process.
RunAsUser *int64 `json:"runAsUser,omitempty"`
// RunAsGroup is the existing gid to run exec command in container process.
RunAsGroup *int64 `json:"runAsGroup,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true

Expand Down
Loading

0 comments on commit 9f57d24

Please sign in to comment.