top of page
Foto do escritorRafael Natali

Como incluir informações sensíveis na construção de imagens Docker

Atualizado: 30 de ago. de 2023

Use o Docker Buildkit para configurar de forma segura a sua imagem Docker para acessar recursos privados


Este artigo foi originalmente publicado no Medium em 30 de julho de 2021.


Construção segura de imagens Docker usando o Docker Buildkit - Imagem do autor
Construção segura de imagens Docker usando o Docker Buildkit - Imagem do autor

Desafios no acesso a informações protegidas


Acessar recursos privados, como um repositório Nexus ou GitHub, de dentro de uma imagem Docker sem vazar qualquer informação relacionada à segurança é altamente valorizado.


Primeiro, nunca incluiremos credenciais ou qualquer outra informação segura diretamente no Dockerfile.


Segundo, é possível criar uma compilação em várias etapas¹ e limpar a imagem final e as camadas de qualquer informação privada. No entanto, essa não é uma solução direta e depende muito de quem está desenvolvendo.


Finalmente, alguns de nós podem recorrer ao uso de argumentos — ARG  e passar as informações no comando docker build². No entanto, isso sozinho deixa as informações secretas disponíveis nas camadas da imagem. Mostrarei um exemplo disso a seguir.


Usando argumentos para construir uma imagem


Considere o Dockerfile a seguir, que faz o download de um arquivo de um repositório Nexus:

FROM ubuntu  

ARG USERNAME
ARG PASSWORD

RUN apt-get update && \ 
apt-get upgrade && \ 
apt-get install -y curl  

RUN curl -o nginx_policy.yaml -u $USERNAME:$PASSWORD http://nexus:8081/repository/raw/policy/nginx-policy.yaml

Usando o comando docker build, podemos criar a imagem com sucesso:

docker build -t secret:args --build-arg USERNAME=$user --build-arg PASSWORD=$pass .

Sending build context to Docker daemon  3.072kB
Step 1/5 : FROM ubuntu
 ---> c29284518f49
Step 2/5 : ARG USERNAME
 ---> Using cache
 ---> 720c9732f5db
Step 3/5 : ARG PASSWORD
 ---> Using cache
 ---> 193f8044461b
Step 4/5 : RUN apt-get update &&     apt-get upgrade &&     apt-get install -y curl
 ---> Using cache
 ---> 894b791e5ec3
Step 5/5 : RUN curl -o nginx_policy.yaml -u $USERNAME:$PASSWORD http://172.17.0.2:8081/repository/raw/policy/nginx-policy.yaml
 ---> Using cache
 ---> e4050d5c1743
Successfully built e4050d5c1743
Successfully tagged secret:args

Eu utilizei as variáveis de ambiente na opção build-arg para não armazenar as credenciais no histórico do sistema operacional. Além disso, na imagem, eu não estou salvando essa informação em nenhum lugar.


O problema com essa abordagem aparece quando você executa o comando docker history nesta imagem:

➜  docker history secret:args_env       
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
f11cb0b139f3   2 minutes ago    |2 PASSWORD=admin123 USERNAME=admin /bin/sh …   0B        
6ca5f3fc074a   2 minutes ago    |2 PASSWORD=admin123 USERNAME=admin /bin/sh …   0B        
193f8044461b   43 minutes ago   /bin/sh -c #(nop)  ARG PASSWORD                 0B        
720c9732f5db   43 minutes ago   /bin/sh -c #(nop)  ARG USERNAME                 0B        
c29284518f49   3 days ago       /bin/sh -c #(nop)  CMD ["bash"]                 0B        
<missing>      3 days ago       /bin/sh -c #(nop) ADD file:5c3d9d2597e01d1ce…   72.8MB

Claramente, podemos ver que as credenciais estão armazenadas nos metadados da imagem. Apesar de nossos melhores esforços, ainda estamos vazando informações confidenciais. O BuildKit³ foi integrado⁴ ao Docker exatamente para nos ajudar a manter a segurança.


Hablitando o Buildkit


O Buildkit está presente no Docker desde a versão 18.06 e atualmente suporta apenas contêineres Linux. Para ativar as compilações do Buildkit, defina a variável de ambiente DOCKER_BUILDKIT=1 ao invocar o comando docker build, como:

$ DOCKER_BUILDKIT=1 docker build .

ou configure a opção de configuração do daemon⁵ para true e reinicie-o:

{ “features”: { “buildkit”: true } }

Informações secretas do Docker Build


A nova opçāo --secret para o comando docker build permite ao usuário passar informações secretas para serem usadas no Dockerfile para construir imagens do Docker de forma segura, de modo que essas informações não sejam armazenadas na imagem final.


Para usar esse recurso, precisamos substituir o frontend padrão em nosso Dockerfile. Na primeira linha do Dockerfile, insira:

# syntax=docker/dockerfile:1.2

A opçāo --mount foi adicionada ao comando RUN para permitir que o contêiner de compilação acesse arquivos seguros, como chaves privadas, sem incorporá-los na imagem.

# shows secret from default secret location:RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret

Construindo um contêiner com o Buildkit


Por exemplo, com uma informação secreta armazenada em um arquivo de texto:

echo 'SUPER_SECRET_PASSWORD' > mysecret.txt

E com um Dockerfile que especifica o uso de um frontend BuildKit docker/dockerfile:1.2, o segredo pode ser acessado ao executar um RUN:

# syntax=docker/dockerfile:1.2FROM alpine

# shows secret from default secret location:RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret

Este Dockerfile é apenas para demonstrar que o segredo pode ser acessado. Como você pode ver, o segredo é impresso na saída da compilação. A imagem final construída não terá o arquivo de segredo:

$ DOCKER_BUILDKIT=1 docker build --no-cache --progress=plain -t secret:buildkit --secret id=mysecret,src=mysecret.txt .

#1 [internal] load build definition from Dockerfile
#1 sha256:5c65425f6fc0d6c65a5ddd6784812097b4eff778b9bcbf39bc708aacbad59abd
#1 transferring dockerfile: 196B done
#1 DONE 0.0s

#2 [internal] load .dockerignore
#2 sha256:35c8e51716823a06d8dbd04a2594a31a90f3d02bb55a0b8c3e9f2c1b44f901c7
#2 transferring context: 2B done
#2 DONE 0.0s

#3 resolve image config for docker.io/docker/dockerfile:1.2
#3 sha256:b239a20f31d7f1e5744984df3d652780f1a82c37554dd73e1ad47c8eb05b0d69
#3 DONE 2.5s

#4 docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc
#4 sha256:37e0c519b0431ef5446f4dd0a4588ba695f961e9b0e800cd8c7f5ba6165af727
#4 resolve docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc done
#4 CACHED

#5 [internal] load metadata for docker.io/library/alpine:latest
#5 sha256:d4fb25f5b5c00defc20ce26f2efc4e288de8834ed5aa59dff877b495ba88fda6
#5 DONE 0.0s

#6 [1/2] FROM docker.io/library/alpine
#6 sha256:665ba8b2cdc0cb0200e2a42a6b3c0f8f684089f4cd1b81494fbb9805879120f7
#6 CACHED

#7 [2/2] RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
#7 sha256:75601a522ebe80ada66dedd9dd86772ca932d30d7e1b11bba94c04aa55c237de
#7 0.494 SUPER_SECRET_PASSWORD#7 DONE 0.5s

#8 exporting to image
#8 sha256:e8c613e07b0b7ff33893b694f7759a10d42e180f2b4dc349fb57dc6b71dcab00
#8 exporting layers 0.0s done
#8 writing image sha256:8df0fe20ceab547858702c32456d962b99d66fd40ab29f4e191ac0b52e383039 done
#8 DONE 0.0s

Ao executar o comando docker history, não conseguimos ver nenhuma informação relacionada ao segredo:

$ docker history secret:buildkit

IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT7da5afe48753   16 seconds ago   RUN /bin/sh -c cat /run/secrets/mysecret # b…   0B        buildkit.dockerfile.v0
<missing>      4 weeks ago      /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B        
<missing>      4 weeks ago      /bin/sh -c #(nop) ADD file:f278386b0cef68136…   5.6MB

Em vez de usar um arquivo de segredo, é possível passar a informação do segredo usando uma variável de ambiente⁷, como:

$ export PASSWORD=SUPER_SECRET_PASSWORD

$ DOCKER_BUILDKIT=1 docker build --no-cache --progress=plain -t secret:buildkit --secret id=mysecret,env=PASSWORD .

Conclusāo

Este artigo explicou os passos necessários para tornar o uso de informações restritas mais seguro dentro de contêineres Docker.


Ao definir uma variável de ambiente antes da compilação do Docker e fazer algumas alterações no seu Dockerfile, você pode evitar o vazamento de credenciais usadas para configurar seus contêineres Docker.


O BuildKit do Docker não apenas suporta segredos, mas também outros pontos de montagem de compilação, como cache e SSH. Comece ou continue a explorar o BuildKit e entenda como ele pode ajudar a melhorar a segurança dos seus ambientes.


Referências


0 visualização0 comentário

Posts recentes

Ver tudo

Comments


bottom of page