Skip to content

Commit

Permalink
feat: restricted security context
Browse files Browse the repository at this point in the history
  • Loading branch information
yetone committed Jan 9, 2023
1 parent 4dc695c commit 21d1625
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,13 @@ RUN curl https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud
&& tar -xf google-cloud-cli-410.tar.gz \
&& ./google-cloud-sdk/install.sh \
&& rm google-cloud-cli-410.tar.gz

ARG USERNAME=yetone
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Create the user
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME

USER $USER_UID:$USER_GID
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
IMAGE := quay.io/bentoml/bento-downloader:0.0.1
IMAGE := quay.io/bentoml/bento-downloader:0.0.3

build:
docker build -t ${IMAGE} .
Expand Down
12 changes: 12 additions & 0 deletions container_images/buildah/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM quay.io/buildah/stable:v1.23.1

RUN touch /etc/subgid /etc/subuid \
&& chmod g=u /etc/subgid /etc/subuid /etc/passwd \
&& echo build:10000:65536 > /etc/subuid \
&& echo build:10000:65536 > /etc/subgid

ENV BUILDAH_ISOLATION=chroot

USER build
WORKDIR /home/build

5 changes: 5 additions & 0 deletions container_images/buildah/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
IMAGE := quay.io/bentoml/bentoml-buildah:0.0.1

build:
docker build -t ${IMAGE} .
docker push ${IMAGE}
79 changes: 68 additions & 11 deletions controllers/resources/bentorequest_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,12 +625,18 @@ const (
BentoImageBuildEngineKaniko BentoImageBuildEngine = "kaniko"
BentoImageBuildEngineBuildkit BentoImageBuildEngine = "buildkit"
BentoImageBuildEngineBuildkitRootless BentoImageBuildEngine = "buildkit-rootless"
BentoImageBuildEngineBuildah BentoImageBuildEngine = "buildah"
)

const (
EnvBentoImageBuildEngine = "BENTO_IMAGE_BUILD_ENGINE"
EnvRunInOpenshift = "RUN_IN_OPENSHIFT"
)

func checkIfRunInOpenshift() bool {
return os.Getenv(EnvRunInOpenshift) == commonconsts.KubeLabelValueTrue
}

func getBentoImageBuildEngine() BentoImageBuildEngine {
engine := os.Getenv(EnvBentoImageBuildEngine)
if engine == "" {
Expand Down Expand Up @@ -1119,8 +1125,10 @@ func (r *BentoRequestReconciler) generateImageBuilderPod(ctx context.Context, op
logrus.Infof("Image builder is using the images %v", *internalImages)

buildEngine := getBentoImageBuildEngine()
isRunInOpenshift := checkIfRunInOpenshift()

privileged := buildEngine != BentoImageBuildEngineBuildkitRootless
privileged := buildEngine != BentoImageBuildEngineBuildkitRootless || isRunInOpenshift
unprivilegedUID := int64(1034)

bentoDownloadCommandTemplate, err := template.New("downloadCommand").Parse(`
set -e
Expand All @@ -1141,7 +1149,7 @@ echo "Removing bento tar file..."
rm /tmp/downloaded.tar
{{if not .Privileged}}
echo "Changing directory permission..."
chown -R 1000:1000 /workspace
chown -R {{ .UnprivilegedUID }}:{{ .UnprivilegedUID }} /workspace
{{end}}
echo "Done"
`)
Expand All @@ -1159,6 +1167,7 @@ echo "Done"
"BentoRepositoryName": bentoRepositoryName,
"BentoVersion": bentoVersion,
"Privileged": privileged,
"UnprivilegedUID": unprivilegedUID,
})
if err != nil {
err = errors.Wrap(err, "failed to execute download command template")
Expand Down Expand Up @@ -1200,6 +1209,17 @@ echo "Done"
})
}

restrictedSecurityContext := &corev1.SecurityContext{
AllowPrivilegeEscalation: pointer.BoolPtr(false),
RunAsNonRoot: pointer.BoolPtr(true),
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{"ALL"},
},
}

initContainers := []corev1.Container{
{
Name: "bento-downloader",
Expand All @@ -1209,9 +1229,10 @@ echo "Done"
"-c",
bentoDownloadCommand,
},
VolumeMounts: volumeMounts,
Resources: downloaderContainerResources,
EnvFrom: downloaderContainerEnvFrom,
VolumeMounts: volumeMounts,
Resources: downloaderContainerResources,
EnvFrom: downloaderContainerEnvFrom,
SecurityContext: restrictedSecurityContext,
},
}

Expand Down Expand Up @@ -1304,7 +1325,7 @@ echo "Removing model tar file..."
rm /tmp/downloaded.tar
{{if not .Privileged}}
echo "Changing directory permission..."
chown -R 1000:1000 /workspace
chown -R {{ .UnprivilegedUID }}:{{ .UnprivilegedUID }} /workspace
{{end}}
echo "Done"
`)).Execute(&modelDownloadCommandOutput, map[string]interface{}{
Expand All @@ -1315,6 +1336,7 @@ echo "Done"
"ModelRepositoryName": modelRepositoryName,
"ModelVersion": modelVersion,
"Privileged": privileged,
"UnprivilegedUID": unprivilegedUID,
})
if err != nil {
err = errors.Wrap(err, "failed to generate download command")
Expand All @@ -1329,9 +1351,10 @@ echo "Done"
"-c",
modelDownloadCommand,
},
VolumeMounts: volumeMounts,
Resources: downloaderContainerResources,
EnvFrom: downloaderContainerEnvFrom,
VolumeMounts: volumeMounts,
Resources: downloaderContainerResources,
EnvFrom: downloaderContainerEnvFrom,
SecurityContext: restrictedSecurityContext,
})
}

Expand Down Expand Up @@ -1459,6 +1482,19 @@ echo "Done"
builderImage = internalImages.Buildkit
case BentoImageBuildEngineBuildkitRootless:
builderImage = internalImages.BuildkitRootless
case BentoImageBuildEngineBuildah:
builderImage = internalImages.Buildah
command = []string{"bash", "-c"}
args = []string{
fmt.Sprintf(
"buildah bud --format=docker --tls-verify=%v -f %s -t %s /workspace/buildcontext && buildah push --tls-verify=%v %s",
!dockerRegistryInsecure,
dockerFilePath,
inClusterImageName,
!dockerRegistryInsecure,
inClusterImageName,
),
}
default:
err = errors.Errorf("unknown bento image build engine %s", buildEngine)
return
Expand All @@ -1483,18 +1519,33 @@ echo "Done"

var builderContainerSecurityContext *corev1.SecurityContext

//nolint: gocritic
if buildEngine == BentoImageBuildEngineBuildkit {
builderContainerSecurityContext = &corev1.SecurityContext{
Privileged: pointer.BoolPtr(true),
}
} else if buildEngine == BentoImageBuildEngineBuildkitRootless {
kubeAnnotations["container.apparmor.security.beta.kubernetes.io/builder"] = "unconfined"
for _, container := range initContainers {
kubeAnnotations[fmt.Sprintf("container.apparmor.security.beta.kubernetes.io/%s", container.Name)] = "unconfined"
}
builderContainerSecurityContext = &corev1.SecurityContext{
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeUnconfined,
},
RunAsUser: pointer.Int64Ptr(1000),
RunAsGroup: pointer.Int64Ptr(1000),
RunAsUser: pointer.Int64Ptr(unprivilegedUID),
RunAsGroup: pointer.Int64Ptr(unprivilegedUID),
}
} else if buildEngine == BentoImageBuildEngineBuildah {
kubeAnnotations["openshift.io/scc"] = "anyuid"
builderContainerSecurityContext = &corev1.SecurityContext{
RunAsUser: pointer.Int64Ptr(unprivilegedUID),
RunAsGroup: pointer.Int64Ptr(unprivilegedUID),
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{
"KILL",
},
},
}
}

Expand Down Expand Up @@ -1614,6 +1665,12 @@ echo "Done"
Containers: []corev1.Container{
container,
},
SecurityContext: &corev1.PodSecurityContext{
RunAsNonRoot: pointer.BoolPtr(true),
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
},
},
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.18

require (
github.com/aws/aws-sdk-go v1.44.152
github.com/bentoml/yatai-common v0.0.0-20230108151027-0a54d02e79b1
github.com/bentoml/yatai-common v0.0.0-20230109041943-798ca210a16d
github.com/bentoml/yatai-schemas v0.0.0-20221123041958-d3ff9b721451
github.com/huandu/xstrings v1.3.2
github.com/iancoleman/strcase v0.2.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ github.com/aws/aws-sdk-go v1.44.152 h1:L9aaepO8wHB67gwuGD8VgIYH/cmQDxieCt7FeLa0+
github.com/aws/aws-sdk-go v1.44.152/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/bentoml/yatai-common v0.0.0-20230108151027-0a54d02e79b1 h1:VgN2DLopHoMaEVOiD8J4bZO0L1BGXLRSmNSs7GkfbHo=
github.com/bentoml/yatai-common v0.0.0-20230108151027-0a54d02e79b1/go.mod h1:pox0XYk/bVUwKkadn0XwWHEbJmxSEeN3+HwGA4a8uOQ=
github.com/bentoml/yatai-common v0.0.0-20230109041943-798ca210a16d h1:r+iumKOD+Ri4u2NggQYudjQurIYN2Rs0nOW48faSt9E=
github.com/bentoml/yatai-common v0.0.0-20230109041943-798ca210a16d/go.mod h1:pox0XYk/bVUwKkadn0XwWHEbJmxSEeN3+HwGA4a8uOQ=
github.com/bentoml/yatai-schemas v0.0.0-20221123041958-d3ff9b721451 h1:FNxCbN61Ev8ea6BXzlfmRUT5CYNmqlOv8zDRGs8ufVE=
github.com/bentoml/yatai-schemas v0.0.0-20221123041958-d3ff9b721451/go.mod h1:q7tt064G8YIiAwQabKyVaKEdSIHYDQA9Oyt+kyCsflU=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
Expand Down
3 changes: 3 additions & 0 deletions helm/yatai-image-builder/templates/secret-env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ stringData:
INTERNAL_IMAGES_KANIKO: {{ .Values.internalImages.kaniko | quote }}
INTERNAL_IMAGES_BUILDKIT: {{ .Values.internalImages.buildkit | quote }}
INTERNAL_IMAGES_BUILDKIT_ROOTLESS: {{ .Values.internalImages.buildkitRootless | quote }}
INTERNAL_IMAGES_BUILDAH: {{ .Values.internalImages.buildah | quote }}

{{- if .Values.dockerRegistry.useAWSECRWithIAMRole }}
AWS_ECR_WITH_IAM_ROLE: "true"
AWS_ECR_REGION: {{ .Values.dockerRegistry.awsECRRegion | quote }}
{{- end }}

BENTO_IMAGE_BUILD_ENGINE: {{ .Values.bentoImageBuildEngine | quote }}

RUN_IN_OPENSHIFT: {{ .Values.runInOpenshift | quote }}
22 changes: 12 additions & 10 deletions helm/yatai-image-builder/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ serviceAccount:

podAnnotations: {}

podSecurityContext: {}
# fsGroup: 2000
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault

securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL

service:
type: ClusterIP
Expand Down Expand Up @@ -96,9 +96,11 @@ aws:
secretAccessKeyExistingSecretKey: ''

internalImages:
bentoDownloader: quay.io/bentoml/bento-downloader:0.0.1
bentoDownloader: quay.io/bentoml/bento-downloader:0.0.3
kaniko: quay.io/bentoml/kaniko:1.9.1
buildkit: quay.io/bentoml/buildkit:master
buildkitRootless: quay.io/bentoml/buildkit:master-rootless
buildah: quay.io/bentoml/bentoml-buildah:0.0.1

bentoImageBuildEngine: kaniko # options: kaniko, buildkit, buildkit-rootless
runInOpenshift: false
3 changes: 2 additions & 1 deletion scripts/quick-install-yatai-image-builder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ if [ "${USE_LOCAL_HELM_CHART}" = "true" ]; then
--set aws.accessKeyID=${AWS_ACCESS_KEY_ID} \
--set aws.secretAccessKeyExistingSecretName=${AWS_SECRET_ACCESS_KEY_EXISTING_SECRET_NAME} \
--set aws.secretAccessKeyExistingSecretKey=${AWS_SECRET_ACCESS_KEY_EXISTING_SECRET_KEY} \
--set bentoImageBuildEngine=buildkit-rootless
--set bentoImageBuildEngine=buildah \
--set runInOpenshift=true
else
helm_repo_name=bentoml
helm_repo_url=https://bentoml.github.io/helm-charts
Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ var _ = Describe("yatai-image-builder", Ordered, func() {
cmd = exec.Command("kubectl", "-n", "yatai-image-builder", "logs", "--tail", "200", "-l", "app.kubernetes.io/name=yatai-image-builder")
logs, _ = utils.Run(cmd)
fmt.Println(string(logs))
By("Cleaning up BentoRequest resources")
cmd = exec.Command("kubectl", "delete", "-f", "tests/e2e/example.yaml")
_, _ = utils.Run(cmd)
// By("Cleaning up BentoRequest resources")
// cmd = exec.Command("kubectl", "delete", "-f", "tests/e2e/example.yaml")
// _, _ = utils.Run(cmd)
})

Context("BentoRequest Operator", func() {
Expand Down

0 comments on commit 21d1625

Please sign in to comment.