From ecabb6cc4ddd0699b999ba4f86fcbd2fa17aa839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Mart=C3=ADnez=20Fay=C3=B3?= Date: Fri, 7 Jun 2024 13:25:34 -0300 Subject: [PATCH] Fix Dockerfile to have the proper permissions in directories (#4967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Agustín Martínez Fayó --- Dockerfile | 73 +++++++++---------- test/integration/setup/x509pop/gencerts.go | 2 +- .../delegatedidentity/05-test-endpoints | 4 +- .../join-token/04-create-workload-entry | 2 +- .../suites/k8s/conf/agent/spire-agent.yaml | 33 +++++---- .../suites/k8s/conf/server/spire-server.yaml | 7 -- .../suites/nested-rotation/00-setup | 6 +- .../nested-rotation/docker-compose.yaml | 2 + .../suites/node-attestation/00-setup | 2 - .../node-attestation/03-test-node-attestation | 10 +-- .../04-test-x509pop-attestation | 4 +- .../docker-compose.yaml | 3 + .../suites/rotation/04-create-workload-entry | 2 +- test/integration/suites/svidstore/common | 4 +- .../conf/server/spire-server.yaml | 7 -- .../conf/server/base/spire-server.yaml | 7 -- test/integration/test-one.sh | 7 ++ 17 files changed, 81 insertions(+), 94 deletions(-) diff --git a/Dockerfile b/Dockerfile index bf3eaeffab..82cd8a5136 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,38 +23,6 @@ ARG TARGETPLATFORM ARG TARGETARCH COPY --link --from=xx / / -# For users that wish to run SPIRE containers as a non-root user, -# provide a default unprivileged user such that the default paths -# that SPIRE will try to read from, write to, and create at runtime -# can be given the correct file ownership/permissions at build time. -ARG spireuid=1000 -ARG spiregid=1000 - -# Set up directories that SPIRE expects by default -# Set up base directories -RUN install -d -o root -g root -m 777 /spireroot -RUN install -d -o root -g root -m 755 /spireroot/etc/ssl/certs -RUN install -d -o root -g root -m 755 /spireroot/run -RUN install -d -o root -g root -m 755 /spireroot/var/lib -RUN install -d -o root -g root -m 1777 /spireroot/tmp - -# Set up directories used by SPIRE -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireroot/etc/spire -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireroot/run/spire -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireroot/var/lib/spire - -# Set up spire-server directories -RUN cp -r /spireroot /spireserverroot -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireserverroot/etc/spire/server -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireserverroot/run/spire/server/private -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireserverroot/var/lib/spire/server - -# Set up spire-agent directories -RUN cp -r /spireroot /spireagentroot -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireagentroot/etc/spire/agent -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireagentroot/run/spire/agent/public -RUN install -d -o ${spireuid} -g ${spiregid} -m 755 /spireagentroot/var/lib/spire/agent - RUN xx-go --wrap RUN set -e ; xx-apk --no-cache --update add build-base musl-dev libseccomp-dev ENV CGO_ENABLED=1 @@ -65,26 +33,53 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ for f in $(find bin -executable -type f); do xx-verify --static $f; done FROM --platform=${BUILDPLATFORM} scratch AS spire-base +COPY --link --from=builder --chown=root:root --chmod=755 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ WORKDIR /opt/spire -CMD [] -COPY --link --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# Preparation environment for setting up directories +FROM alpine as prep-spire-server +RUN mkdir -p /spireroot/opt/spire/bin \ + /spireroot/etc/spire/server \ + /spireroot/run/spire/server/private \ + /spireroot/tmp/spire-server/private \ + /spireroot/var/lib/spire/server + +FROM alpine as prep-spire-agent +RUN mkdir -p /spireroot/opt/spire/bin \ + /spireroot/etc/spire/agent \ + /spireroot/run/spire/agent/public \ + /spireroot/tmp/spire-agent/public \ + /spireroot/var/lib/spire/agent + +# For users that wish to run SPIRE containers as a non-root user, +# a default unprivileged user is provided such that the default paths +# that SPIRE will try to read from, write to, and create at runtime +# can be given the correct file ownership/permissions at build time. +# This is done through the spireuid and spiregid arguments that the +# spire-server, spire-agent, and oidc-discovery-provider build stages use. # SPIRE Server FROM spire-base AS spire-server +ARG spireuid=1000 +ARG spiregid=1000 USER ${spireuid}:${spiregid} ENTRYPOINT ["/opt/spire/bin/spire-server", "run"] -COPY --link --from=builder /spireserverroot / -COPY --link --from=builder /spire/bin/static/spire-server bin/ +COPY --link --from=prep-spire-server --chown=${spireuid}:${spiregid} --chmod=755 /spireroot / +COPY --link --from=builder --chown=${spireuid}:${spiregid} --chmod=755 /spire/bin/static/spire-server /opt/spire/bin/ # SPIRE Agent FROM spire-base AS spire-agent +ARG spireuid=1000 +ARG spiregid=1000 USER ${spireuid}:${spiregid} ENTRYPOINT ["/opt/spire/bin/spire-agent", "run"] -COPY --link --from=builder /spireagentroot / -COPY --link --from=builder /spire/bin/static/spire-agent bin/ +COPY --link --from=prep-spire-agent --chown=${spireuid}:${spiregid} --chmod=755 /spireroot / +COPY --link --from=builder --chown=${spireuid}:${spiregid} --chmod=755 /spire/bin/static/spire-agent /opt/spire/bin/ # OIDC Discovery Provider FROM spire-base AS oidc-discovery-provider +ARG spireuid=1000 +ARG spiregid=1000 USER ${spireuid}:${spiregid} ENTRYPOINT ["/opt/spire/bin/oidc-discovery-provider"] -COPY --link --from=builder /spire/bin/static/oidc-discovery-provider bin/ +COPY --link --from=builder --chown=${spireuid}:${spiregid} --chmod=755 /spire/bin/static/oidc-discovery-provider /opt/spire/bin/ diff --git a/test/integration/setup/x509pop/gencerts.go b/test/integration/setup/x509pop/gencerts.go index f2d5e060f9..440a21f0e7 100644 --- a/test/integration/setup/x509pop/gencerts.go +++ b/test/integration/setup/x509pop/gencerts.go @@ -74,7 +74,7 @@ func writeKey(path string, key crypto.Signer) { Type: "PRIVATE KEY", Bytes: keyBytes, }) - writeFile(path, pemBytes, 0o600) + writeFile(path, pemBytes, 0o644) // This key is used only for testing purposes. } func writeCerts(path string, certs ...*x509.Certificate) { diff --git a/test/integration/suites/delegatedidentity/05-test-endpoints b/test/integration/suites/delegatedidentity/05-test-endpoints index 78f3011028..81ea845408 100755 --- a/test/integration/suites/delegatedidentity/05-test-endpoints +++ b/test/integration/suites/delegatedidentity/05-test-endpoints @@ -1,9 +1,9 @@ #!/bin/bash log-info "Test Delegated Identity API (for success)" -docker-compose exec -u 1001 -T spire-agent \ +docker-compose exec -u 1001:1000 -T spire-agent \ /opt/spire/conf/agent/delegatedidentityclient -expectedID spiffe://domain.test/workload || fail-now "Failed to check Delegated Identity API" log-info "Test Delegated Identity API (expecting permission denied)" -docker-compose exec -u 1002 -T spire-agent \ +docker-compose exec -u 1002:1000 -T spire-agent \ /opt/spire/conf/agent/delegatedidentityclient || fail-now "Failed to check Delegated Identity API" diff --git a/test/integration/suites/join-token/04-create-workload-entry b/test/integration/suites/join-token/04-create-workload-entry index 9d261b885a..81007d4469 100755 --- a/test/integration/suites/join-token/04-create-workload-entry +++ b/test/integration/suites/join-token/04-create-workload-entry @@ -5,7 +5,7 @@ docker-compose exec -T spire-server \ /opt/spire/bin/spire-server entry create \ -parentID "spiffe://domain.test/node" \ -spiffeID "spiffe://domain.test/workload" \ - -selector "unix:uid:0" \ + -selector "unix:uid:1000" \ -ttl 0 # Check at most 30 times (with one second in between) that the agent has diff --git a/test/integration/suites/k8s/conf/agent/spire-agent.yaml b/test/integration/suites/k8s/conf/agent/spire-agent.yaml index 6c6b897f1e..726b3f315e 100644 --- a/test/integration/suites/k8s/conf/agent/spire-agent.yaml +++ b/test/integration/suites/k8s/conf/agent/spire-agent.yaml @@ -6,36 +6,32 @@ metadata: namespace: spire --- - # Required cluster role to allow spire-agent to query k8s API server kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: spire-agent-cluster-role rules: -- apiGroups: [""] - resources: ["pods","nodes","nodes/proxy"] - verbs: ["get"] + - apiGroups: [""] + resources: ["pods", "nodes", "nodes/proxy"] + verbs: ["get"] --- - # Binds above cluster role to spire-agent service account kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: spire-agent-cluster-role-binding subjects: -- kind: ServiceAccount - name: spire-agent - namespace: spire + - kind: ServiceAccount + name: spire-agent + namespace: spire roleRef: kind: ClusterRole name: spire-agent-cluster-role apiGroup: rbac.authorization.k8s.io - --- - # ConfigMap for the SPIRE agent featuring: # 1) PSAT node attestation # 2) K8S Workload Attestation over the secure kubelet port @@ -90,7 +86,6 @@ data: } --- - apiVersion: apps/v1 kind: DaemonSet metadata: @@ -117,6 +112,12 @@ spec: serviceAccountName: spire-agent containers: - name: spire-agent + # Make sure that we can create the directory for the socket in the host, + # this is needed because we use a hostPath volume to share the socket + # for the Workload API. + securityContext: + runAsUser: 0 + runAsGroup: 0 image: spire-agent:latest-local imagePullPolicy: Never args: ["-config", "/run/spire/config/agent.conf"] @@ -151,6 +152,8 @@ spec: - name: spire-bundle configMap: name: spire-bundle + # The volume containing the SPIRE Agent socket that will be used by + # the workload container. - name: spire-agent-socket hostPath: path: /run/spire/agent-sockets @@ -158,7 +161,7 @@ spec: - name: spire-token projected: sources: - - serviceAccountToken: - path: spire-agent - expirationSeconds: 7200 - audience: spire-server + - serviceAccountToken: + path: spire-agent + expirationSeconds: 7200 + audience: spire-server diff --git a/test/integration/suites/k8s/conf/server/spire-server.yaml b/test/integration/suites/k8s/conf/server/spire-server.yaml index b206991e9c..bad6a2a7b0 100644 --- a/test/integration/suites/k8s/conf/server/spire-server.yaml +++ b/test/integration/suites/k8s/conf/server/spire-server.yaml @@ -199,9 +199,6 @@ spec: - name: spire-config mountPath: /run/spire/config readOnly: true - - name: spire-server-socket - mountPath: /tmp/spire-server/private - readOnly: false livenessProbe: httpGet: path: /live @@ -218,10 +215,6 @@ spec: - name: spire-config configMap: name: spire-server - - name: spire-server-socket - hostPath: - path: /run/spire/server-sockets - type: DirectoryOrCreate --- diff --git a/test/integration/suites/nested-rotation/00-setup b/test/integration/suites/nested-rotation/00-setup index 29ccb4d988..607b5446e3 100755 --- a/test/integration/suites/nested-rotation/00-setup +++ b/test/integration/suites/nested-rotation/00-setup @@ -1,13 +1,13 @@ #!/bin/bash # create shared folder for root agent socket -mkdir -p shared/rootSocket +mkdir -p -m 777 shared/rootSocket # create shared folder for intermediateA agent socket -mkdir -p shared/intermediateASocket +mkdir -p -m 777 shared/intermediateASocket # create shared folder for intermediateB agent socket -mkdir -p shared/intermediateBSocket +mkdir -p -m 777 shared/intermediateBSocket # root certificates "${ROOTDIR}/setup/x509pop/setup.sh" root/server root/agent diff --git a/test/integration/suites/nested-rotation/docker-compose.yaml b/test/integration/suites/nested-rotation/docker-compose.yaml index cb8b92ffcf..3dd9b52c9e 100644 --- a/test/integration/suites/nested-rotation/docker-compose.yaml +++ b/test/integration/suites/nested-rotation/docker-compose.yaml @@ -19,6 +19,8 @@ services: - ./root/agent:/opt/spire/conf/agent - /var/run/docker.sock:/var/run/docker.sock command: ["-config", "/opt/spire/conf/agent/agent.conf"] + # Make sure that we can access the Docker daemon socket + user: 0:0 # IntermediateA intermediateA-server: # Share the host pid namespace so this server can be attested by the root agent diff --git a/test/integration/suites/node-attestation/00-setup b/test/integration/suites/node-attestation/00-setup index b8b14e18fd..9bb3aae582 100755 --- a/test/integration/suites/node-attestation/00-setup +++ b/test/integration/suites/node-attestation/00-setup @@ -5,8 +5,6 @@ echo ${ROOTDIR} # Move test x509pop certificate and key mv conf/agent.key.pem conf/agent/test.key.pem mv conf/agent.crt.pem conf/agent/test.crt.pem -# add read access to prevent error when reading with user 1001 -chmod +r conf/agent/test.key.pem "${ROOTDIR}/setup/node-attestation/build.sh" "${RUNDIR}/conf/server/node-attestation" "${ROOTDIR}/setup/node-attestation/build.sh" "${RUNDIR}/conf/agent/node-attestation" diff --git a/test/integration/suites/node-attestation/03-test-node-attestation b/test/integration/suites/node-attestation/03-test-node-attestation index fcc83e5e2e..c493b63d8d 100755 --- a/test/integration/suites/node-attestation/03-test-node-attestation +++ b/test/integration/suites/node-attestation/03-test-node-attestation @@ -1,31 +1,31 @@ #!/bin/bash # Test node attestation api -jointoken=`docker-compose exec -u 1001 -T spire-server /opt/spire/conf/server/node-attestation -testStep jointoken` +jointoken=`docker-compose exec -u 1000 -T spire-server /opt/spire/conf/server/node-attestation -testStep jointoken` echo "Created Join Token" $jointoken -svid1=`docker-compose exec -u 1001 -T spire-agent /opt/spire/conf/agent/node-attestation -testStep jointokenattest -tokenName $jointoken` +svid1=`docker-compose exec -u 1000 -T spire-agent /opt/spire/conf/agent/node-attestation -testStep jointokenattest -tokenName $jointoken` if [[ $? -ne 0 ]]; then fail-now "Failed to do initial join token attestation" fi echo "Received initial SVID:" $svid1 -svid2=`docker-compose exec -u 1001 -T spire-agent /opt/spire/conf/agent/node-attestation -testStep renew -certificate "${svid1}"` +svid2=`docker-compose exec -u 1000 -T spire-agent /opt/spire/conf/agent/node-attestation -testStep renew -certificate "${svid1}"` if [[ $? -ne 0 ]]; then fail-now "Failed to do SVID renewal" fi echo "Received renewed SVID:" $svid2 -docker-compose exec -u 1001 -T spire-server /opt/spire/conf/server/node-attestation -testStep ban -tokenName ${jointoken} +docker-compose exec -u 1000 -T spire-server /opt/spire/conf/server/node-attestation -testStep ban -tokenName ${jointoken} if [[ $? -ne 0 ]]; then fail-now "Failed to do initial join token attestation" fi echo "Agent banned" -if docker-compose exec -u 1001 -T spire-server /opt/spire/conf/server/node-attestation -testStep renew -certificate "${svid2}" +if docker-compose exec -u 1000 -T spire-server /opt/spire/conf/server/node-attestation -testStep renew -certificate "${svid2}" then fail-now "Expected agent to be banned" fi diff --git a/test/integration/suites/node-attestation/04-test-x509pop-attestation b/test/integration/suites/node-attestation/04-test-x509pop-attestation index c652c7acd6..207194e7ac 100755 --- a/test/integration/suites/node-attestation/04-test-x509pop-attestation +++ b/test/integration/suites/node-attestation/04-test-x509pop-attestation @@ -5,10 +5,10 @@ docker-compose exec -T spire-server \ /opt/spire/bin/spire-server entry create \ -parentID "spiffe://domain.test/spire/agent/x509pop/$(fingerprint conf/agent/agent.crt.pem)" \ -spiffeID "spiffe://domain.test/admin" \ - -selector "unix:uid:1001" \ + -selector "unix:uid:1000" \ -admin \ -ttl 0 check-synced-entry "spire-agent" "spiffe://domain.test/admin" log-debug "running x509pop test..." -docker-compose exec -u 1001 -T spire-agent /opt/spire/conf/agent/node-attestation -testStep x509pop || fail-now "failed to check x509pop attestion" +docker-compose exec -u 1000 -T spire-agent /opt/spire/conf/agent/node-attestation -testStep x509pop || fail-now "failed to check x509pop attestion" diff --git a/test/integration/suites/oidc-discovery-provider/docker-compose.yaml b/test/integration/suites/oidc-discovery-provider/docker-compose.yaml index bce24a1bf5..6857a1332c 100644 --- a/test/integration/suites/oidc-discovery-provider/docker-compose.yaml +++ b/test/integration/suites/oidc-discovery-provider/docker-compose.yaml @@ -15,6 +15,7 @@ services: - ./conf/agent:/opt/spire/conf/agent - /var/run/docker.sock:/var/run/docker.sock command: [ "-config", "/opt/spire/conf/agent/agent.conf" ] + user: 0:0 # Required to access the Docker daemon socket oidc-discovery-provider-server: image: oidc-discovery-provider:latest-local hostname: oidc-discovery-provider-server @@ -24,6 +25,7 @@ services: - ./conf/agent:/opt/spire/conf/agent - ./conf/server:/opt/spire/conf/server command: [ "-config", "/opt/spire/conf/oidc-discovery-provider/provider-server-api.conf" ] + user: 0:0 # Required to access the Docker daemon socket oidc-discovery-provider-workload: pid: "host" image: oidc-discovery-provider:latest-local @@ -37,3 +39,4 @@ services: - ./conf/agent:/opt/spire/conf/agent - ./conf/server:/opt/spire/conf/server command: [ "-config", "/opt/spire/conf/oidc-discovery-provider/provider-workload-api.conf" ] + user: 0:0 # Required to access the Docker daemon socket diff --git a/test/integration/suites/rotation/04-create-workload-entry b/test/integration/suites/rotation/04-create-workload-entry index 8686f3eaa9..af9c30ae03 100755 --- a/test/integration/suites/rotation/04-create-workload-entry +++ b/test/integration/suites/rotation/04-create-workload-entry @@ -5,7 +5,7 @@ docker-compose exec -T spire-server \ /opt/spire/bin/spire-server entry create \ -parentID "spiffe://domain.test/spire/agent/x509pop/$(fingerprint conf/agent/agent.crt.pem)" \ -spiffeID "spiffe://domain.test/workload" \ - -selector "unix:uid:0" \ + -selector "unix:uid:1000" \ -ttl 0 # Check at most 30 times (with one second in between) that the agent has diff --git a/test/integration/suites/svidstore/common b/test/integration/suites/svidstore/common index f94d6b5ff1..b2a8b81341 100644 --- a/test/integration/suites/svidstore/common +++ b/test/integration/suites/svidstore/common @@ -23,7 +23,7 @@ check-stored-svids() { fi done - docker-compose exec -u 1001 -T spire-server \ + docker-compose exec -u 1000 -T spire-server \ /opt/spire/conf/server/checkstoredsvids /opt/spire/conf/agent/svids.json || fail-now "failed to check stored svids" } @@ -48,6 +48,6 @@ check-deleted-svids() { fail-now "timed out waiting for agent to delete all svids" fi - docker-compose exec -u 1001 -T spire-server \ + docker-compose exec -u 1000 -T spire-server \ /opt/spire/conf/server/checkstoredsvids /opt/spire/conf/agent/svids.json || fail-now "failed to check stored svids" } diff --git a/test/integration/suites/upstream-authority-cert-manager/conf/server/spire-server.yaml b/test/integration/suites/upstream-authority-cert-manager/conf/server/spire-server.yaml index c8bfa4c394..5370924e54 100644 --- a/test/integration/suites/upstream-authority-cert-manager/conf/server/spire-server.yaml +++ b/test/integration/suites/upstream-authority-cert-manager/conf/server/spire-server.yaml @@ -128,9 +128,6 @@ spec: - name: spire-config mountPath: /run/spire/config readOnly: true - - name: spire-server-socket - mountPath: /tmp/spire-server/private - readOnly: false livenessProbe: httpGet: path: /live @@ -147,7 +144,3 @@ spec: - name: spire-config configMap: name: spire-server - - name: spire-server-socket - hostPath: - path: /run/spire/server-sockets - type: DirectoryOrCreate diff --git a/test/integration/suites/upstream-authority-vault/conf/server/base/spire-server.yaml b/test/integration/suites/upstream-authority-vault/conf/server/base/spire-server.yaml index db9ee52b4d..05b8bfe53c 100644 --- a/test/integration/suites/upstream-authority-vault/conf/server/base/spire-server.yaml +++ b/test/integration/suites/upstream-authority-vault/conf/server/base/spire-server.yaml @@ -201,9 +201,6 @@ spec: - name: spire-config mountPath: /run/spire/config readOnly: true - - name: spire-server-socket - mountPath: /tmp/spire-server/private - readOnly: false - name: vault-tls mountPath: "/run/spire/vault" readOnly: true @@ -223,10 +220,6 @@ spec: - name: spire-config configMap: name: spire-server - - name: spire-server-socket - hostPath: - path: /run/spire/server-sockets - type: DirectoryOrCreate - name: vault-tls secret: secretName: vault-tls diff --git a/test/integration/test-one.sh b/test/integration/test-one.sh index 821734aef5..dc29eadabc 100755 --- a/test/integration/test-one.sh +++ b/test/integration/test-one.sh @@ -68,6 +68,13 @@ trap cleanup EXIT ################################################# # Prepare the run directory ################################################# + +# Prepare common directories used by tests. +# These directories on the host are mapped to paths in containers, possibly +# running with a different user. +mkdir -p -m 777 "${RUNDIR}/conf/agent" +mkdir -p -m 777 "${RUNDIR}/conf/server" + cp -R "${TESTDIR}"/* "${RUNDIR}/" #################################################