Skip to content

Commit

Permalink
Use scratch as base image
Browse files Browse the repository at this point in the history
The goal with this changes is to decrease the attack surface of the
published images, by relying on a scratch base image.
In order to support such approach, the following changes were made:
- Statically compile the application to use the network and os/user implementations from Pure Go.
- Embed time zone data into the application via time/tzdata.
- Embed x509 roots from Go, which was introduced on Go 1.20.
- Create a top layer dir structure that complies with FHS 3.0.
- Create files /etc/{passwd,shadow,group,nsswitch.conf}.
- Bump Go to 1.21 (given that 1.20 is half way through its life)

Signed-off-by: Paulo Gomes <paulo.gomes@suse.com>
  • Loading branch information
pjbgf committed Nov 15, 2023
1 parent 87f29e5 commit 6653991
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Dockerfile.dapper
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.suse.com/bci/golang:1.19
FROM registry.suse.com/bci/golang:1.21

# k3d and kubectl versions must be aligned with the Kubernetes versions
# set in tests/k3s-bench-test.yaml.
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/rancher/cis-operator

go 1.19
go 1.21

require (
github.com/blang/semver v3.5.1+incompatible
Expand Down Expand Up @@ -69,6 +69,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.15.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
golang.org/x/crypto/x509roots/fallback v0.0.0-20231030152948-74c2ba9521f1 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/oauth2 v0.5.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,8 @@ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto/x509roots/fallback v0.0.0-20231030152948-74c2ba9521f1 h1:wQ75dCmVn5ExryuIUzbi2MC1/10fUNIL1FP918r4jx8=
golang.org/x/crypto/x509roots/fallback v0.0.0-20231030152948-74c2ba9521f1/go.mod h1:kNa9WdvYnzFwC79zRpLRMJbdEFlhyM5RPFBBZp/wWH8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down
10 changes: 10 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ import (

cisoperatorapiv1 "github.com/rancher/cis-operator/pkg/apis/cis.cattle.io/v1"
cisoperator "github.com/rancher/cis-operator/pkg/securityscan"

// Automatically sets fallback trusted x509 roots, in case they are
// not available at runtime. This is required to establish trust
// when deployed into a scratch container.
_ "golang.org/x/crypto/x509roots/fallback"

// Embed a copy of the timezone database, so that it does not depend
// on it being available at runtime.
_ "time/tzdata"

corev1 "k8s.io/api/core/v1"
)

Expand Down
43 changes: 40 additions & 3 deletions package/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,44 @@
FROM registry.suse.com/bci/bci-busybox:15.5
FROM registry.suse.com/bci/bci-busybox:15.5 as builder

COPY bin/cis-operator /usr/bin/
# There is no real need for containers to fully comply with the
# Filesystem Hierarchy Standard (FHS). However, some applications
# could malfunction if some specific basic dirs are not available.
# Therefore, create top level structure.
#
# https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
RUN mkdir -p /final/boot && \
mkdir -p /final/etc && \
mkdir -p /final/home && \
mkdir -p /final/lib && \
mkdir -p /final/lib64 && \
mkdir -p /final/media && \
mkdir -p /final/mnt && \
mkdir -p /final/opt && \
mkdir -p /final/run && \
mkdir -p /final/usr/sbin && \
mkdir -p /final/var/lib/nobody

USER 65535:65535
# Some dirs require very specific permissions.
RUN install -dv -m 0750 /final/root && \
install -dv -m 1777 /final/tmp /final/var/tmp

# Keep name search configured in line with BCI.
RUN cp /etc/nsswitch.conf /final/etc

# Differs from BCI, by removing /bin/sh from root:
RUN echo "root:x:0:0:root:/root:/usr/bin/false\nnobody:x:65534:65534:nobody:/var/lib/nobody:/usr/bin/false" > /final/etc/passwd

RUN cp /etc/shadow /final/etc
RUN cp /etc/group /final/etc

COPY bin/cis-operator /final/usr/bin/

FROM scratch as final

COPY --from=builder /final/ /

# Aligns nobody user ID with BCI.
USER 65534:65534
ENV PATH=/usr/bin

CMD ["cis-operator"]
21 changes: 14 additions & 7 deletions scripts/build
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ source $(dirname $0)/version
cd $(dirname $0)/..

mkdir -p bin

# Leans on Pure Go for the network stack and os/user. For more information:
# - https://github.com/golang/go/blob/4cd201b14b6216e72ffa175747c20d1191e5eb57/src/net/net.go#L39-L81
# - https://github.com/golang/go/blob/4cd201b14b6216e72ffa175747c20d1191e5eb57/src/os/user/user.go#L6-L17
GO_TAGS="netgo osusergo"
LINKFLAGS="-X github.com/rancher/cis-operator.Version=${VERSION}"
LINKFLAGS="-X github.com/rancher/cis-operator.GitCommit=${COMMIT} ${LINKFLAGS}"

if [ "$(uname)" = "Linux" ]; then
OTHER_LINKFLAGS="-extldflags -static -s"
LINKFLAGS="${LINKFLAGS} -extldflags -static -s -w"
fi
LINKFLAGS="-X github.com/rancher/cis-operator.Version=$VERSION"
LINKFLAGS="-X github.com/rancher/cis-operator.GitCommit=$COMMIT $LINKFLAGS"
CGO_ENABLED=0 go build -ldflags "$LINKFLAGS $OTHER_LINKFLAGS" -o bin/cis-operator
if [ "$CROSS" = "true" ] && [ "$ARCH" = "amd64" ]; then
GOOS=darwin go build -ldflags "$LINKFLAGS" -o bin/cis-operator-darwin
GOOS=windows go build -ldflags "$LINKFLAGS" -o bin/cis-operator-windows

CGO_ENABLED=0 go build -trimpath -tags "${GO_TAGS}" -ldflags "${LINKFLAGS}" -o bin/cis-operator
if [ "${CROSS}" = "true" ] && [ "${ARCH}" = "amd64" ]; then
GOOS=darwin go build -trimpath -ldflags "${LINKFLAGS}" -o bin/cis-operator-darwin
GOOS=windows go build -trimpath -ldflags "${LINKFLAGS}" -o bin/cis-operator-windows
fi

0 comments on commit 6653991

Please sign in to comment.