Remover Segredos de Build de uma Imagem

DockerBeginner
Pratique Agora

Introdução

Segredos de build podem vazar para dentro de imagens quando um Dockerfile copia excessivamente o contexto de build. O erro comum é COPY . /app/: é conveniente, mas pode trazer tokens, credenciais, notas locais e arquivos temporários para a imagem final. Uma vez que um segredo está dentro de uma camada da imagem, os controles de tempo de execução (runtime) não conseguem apagar de forma confiável esse erro na cadeia de suprimentos.

Neste laboratório, você construirá uma imagem local deliberadamente vulnerável, provará que um token de build está presente nela e, em seguida, corrigirá o build restringindo o limite de cópia do Dockerfile e adicionando um .dockerignore. Por fim, você implantará a imagem limpa e verificará que o contêiner em execução não contém mais o segredo de build.

Inspecionar o Contexto de Build Inseguro

Nesta etapa, você inspecionará o contexto de build e o Dockerfile inseguro. O contexto de build é o diretório enviado ao construtor da imagem. Se o Dockerfile copiar todo o contexto, cada arquivo nesse diretório pode se tornar parte da imagem final.

Comece no ambiente de trabalho do laboratório:

cd /home/labex/project/build-secret-image

Leia as notas:

sed -n '1,120p' BUILD_SECRET_NOTES.md

Liste os arquivos que existem atualmente no contexto de build:

find . -maxdepth 1 -type f -printf '%f\n' | sort | tee evidence/initial-context-files.txt

Revise o Dockerfile inseguro:

sed -n '1,120p' Dockerfile.insecure | tee evidence/insecure-dockerfile-review.txt

A linha de risco é COPY . /app/. Ela copia o app.sh, mas também copia o build-token.txt. Na próxima etapa, você construirá essa imagem e provará o vazamento a partir do tempo de execução da imagem.

Construir a Imagem com Vazamento e Provar a Presença do Segredo

Nesta etapa, você construirá a imagem insegura dentro do perfil labex-v134 do minikube. Construir dentro do perfil torna a imagem visível para o runtime do nó do Kubernetes.

Copie o Dockerfile inseguro para o nome do Dockerfile ativo e construa a imagem com vazamento:

cp Dockerfile.insecure Dockerfile
minikube -p labex-v134 image build -t labex/leaky-build:1.0 .

Execute a imagem dentro do runtime Docker do minikube e verifique a existência do arquivo de token:

minikube -p labex-v134 ssh -- 'docker run --rm --entrypoint /bin/sh labex/leaky-build:1.0 -c "ls -l /app && cat /app/build-token.txt"' | tee evidence/leaky-image-contents.txt

Você deverá ver build-token=labex-temporary-secret. Esse é o vazamento. A imagem é executada, mas contém um arquivo que deveria ter permanecido fora da imagem final de runtime.

Construir uma Imagem Limpa com um Limite de Cópia Restrito

Nesta etapa, você corrigirá o build da imagem. Duas mudanças são importantes: o .dockerignore mantém o token fora do contexto de build enviado ao construtor, e o Dockerfile copia apenas o app.sh em vez de copiar todo o diretório.

Crie o .dockerignore:

cat > .dockerignore <<'EOF'
build-token.txt
evidence/
*.txt
EOF

Crie o Dockerfile limpo:

cat > Dockerfile <<'EOF'
FROM busybox:1.36

WORKDIR /app
COPY app.sh /app/app.sh
RUN chmod 0555 /app/app.sh

USER 65534:65534
ENTRYPOINT ["/app/app.sh"]
EOF

Construa a imagem limpa:

minikube -p labex-v134 image build -t labex/clean-build:1.0 .

Inspecione a imagem limpa a partir do runtime Docker do minikube:

minikube -p labex-v134 ssh -- 'docker run --rm --entrypoint /bin/sh labex/clean-build:1.0 -c "ls -l /app; if [ -f /app/build-token.txt ]; then echo BUILD_SECRET_PRESENT; else echo NO_BUILD_SECRET; fi; id -u"' | tee evidence/clean-image-contents.txt

A saída deve mostrar NO_BUILD_SECRET e o UID 65534.

Implantar a Imagem Limpa

Nesta etapa, você implantará a imagem limpa e verificará se o contêiner em execução relata que nenhum segredo de build está presente. Isso mantém a prova final próxima ao Kubernetes, onde a imagem será efetivamente executada.

Crie e aplique o manifesto do Pod:

cat > clean-build-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: clean-build-app
  namespace: cks-prep-build-secret
  labels:
    app: clean-build-app
spec:
  restartPolicy: Never
  containers:
    - name: app
      image: labex/clean-build:1.0
      imagePullPolicy: Never
      securityContext:
        runAsNonRoot: true
        runAsUser: 65534
        runAsGroup: 65534
        allowPrivilegeEscalation: false
EOF
kubectl apply -f clean-build-pod.yaml

Aguarde o Pod e leia seus logs:

kubectl -n cks-prep-build-secret wait --for=condition=Ready pod/clean-build-app --timeout=120s
kubectl -n cks-prep-build-secret logs clean-build-app | tee evidence/clean-pod-logs.txt

Os logs devem incluir:

clean build image ready
NO_BUILD_SECRET

Resumo

Você inspecionou um contexto de build de imagem inseguro, construiu uma imagem com vazamento, provou que o token de build estava presente e, em seguida, corrigiu o build com um .dockerignore e uma instrução COPY restrita no Dockerfile. Você construiu e implantou uma imagem limpa que é executada como um usuário não privilegiado (non-root) e relata NO_BUILD_SECRET. Isso conclui a etapa da cadeia de suprimentos ao conectar a higiene do build da imagem com a verificação em tempo de execução no Kubernetes.