Construindo Imagens de Container Imutáveis e Seguras com Wolfi e Chainguard
A superfície de ataque da cadeia de suprimentos de software é uma preocupação primordial em ambientes de desenvolvimento e operações modernos. Vulnerabilidades em imagens de container, muitas vezes decorrentes de pacotes desnecessários ou bases de sistemas operacionais obsoletas, representam um risco significativo. Para mitigar esses riscos, a adoção de imagens de container minimalistas e verificáveis tornou-se uma estratégia mandatoria. Este artigo explora a construção de imagens de container inerentemente mais seguras utilizando Wolfi, a distribuição linux base da Chainguard, e o ecossistema de ferramentas que a suporta.
A Base da Segurança: Entendendo Wolfi
Wolfi é uma distribuição Linux focada em segurança, projetada especificamente para containers e ambientes de nuvem. Diferente de distribuições tradicionais como Debian ou Alpine, Wolfi adota uma abordagem de segurança por design, fornecendo apenas os pacotes essenciais, compilados a partir do código fonte com opções de segurança rigorosas.
Características Essenciais de Wolfi:
- Musl libc como Padrão: Utiliza musl libc em vez de glibc, resultando em imagens de container menores e com menos dependências, simplificando a análise de segurança.
- Construções Reproduzíveis: Todos os pacotes em Wolfi são construídos de forma reproduzível, o que permite a verificação independente da origem binária e garante que o binário corresponde ao código fonte.
- SBOMs Nativos (Software Bill of Materials): Cada imagem Wolfi gera um SBOM detalhado, fornecendo uma lista exaustiva de todos os componentes, suas versões e licenças. Este é um pilar fundamental para a conformidade e análise de vulnerabilidades.
- Foco em Segurança: Projetada para ter uma superfície de ataque mínima. Pacotes são mantidos atualizados e vulnerabilidades (CVEs) são corrigidas proativamente.
- Ferramentas de Construção Próprias: Wolfi utiliza o
apko, uma ferramenta de construção de imagens de container que gera imagens OCI (Open Container Initiative) diretamente de arquivos de configuração declarativos.
A filosofia por trás de Wolfi é de fornecer uma base limpa e transparente, onde cada byte na imagem é justificado e auditável. Este enfoque contrasta drasticamente com imagens base monolíticas que incluem inúmeros utilitários e bibliotecas desnecessárias, aumentando exponencialmente o vetor de ataque.
Chainguard Images: Imagens Otimizadas por Padrão
As Chainguard Images são coleções de imagens de container pré-construídas e otimizadas para segurança, mantidas pela Chainguard e baseadas em Wolfi. Elas representam um passo adiante na segurança da cadeia de suprimentos, oferecendo imagens com:
- Zero CVEs Conhecidas: No momento da construção, estas imagens visam ter zero vulnerabilidades conhecidas. Isso é alcançado pela sua base Wolfi e pelo monitoramento contínuo de pacotes.
- Tamanho Mínimo: Redução drástica no tamanho das imagens, o que acelera o download, melhora o tempo de inicialização e, criticamente, reduz a superfície de ataque.
- Assinatura com Sigstore: Todas as Chainguard Images são assinadas com Sigstore e Cosign, permitindo a verificação criptográfica da sua integridade e proveniência.
- Ciclo de Vida Gerenciado: A Chainguard se responsabiliza pela atualização e correção de vulnerabilidades, aliviando o fardo de manutenção para os usuários.
Para utilizar uma Chainguard Image, o processo é semelhante ao de qualquer outra imagem OCI. Basta substituir sua imagem base atual por uma equivalente da Chainguard. Por exemplo, para um aplicativo Go, em vez de usar golang:1.21-alpine, você usaria cgr.dev/chainguard/go:latest (ou uma tag de versão específica):
# Dockerfile de exemplo com Chainguard Go Image
FROM cgr.dev/chainguard/go:1.21-static as builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o myapp .
FROM cgr.dev/chainguard/static:latest
COPY --from=builder /app/myapp /usr/local/bin/myapp
EXPOSE 8080
CMD ["myapp"]
Observe o uso da imagem static da Chainguard para a fase final. Esta imagem é a mais mínima possível, contendo apenas o essencial para executar binários estaticamente compilados, garantindo a menor superfície de ataque.
Construindo Imagens Wolfi Customizadas com apko
Embora as Chainguard Images cubram muitos casos de uso comuns, pode ser necessário construir imagens Wolfi personalizadas para aplicações específicas. É aqui que o apko, a ferramenta de construção de imagens da Chainguard, entra em cena. O apko permite definir o conteúdo de uma imagem OCI de forma declarativa via um arquivo YAML.
Estrutura de um Arquivo apko.yaml:
# apko.yaml para uma imagem customizada com Nginx
# Versão do formato de arquivo apko
apiVersion: "apko.dev/v1beta1"
kind: "Configuration"
# Informações da imagem
metadata:
name: "meu-nginx"
version: "1.0.0"
architecture: "amd64"
# Pacotes a serem incluídos na imagem
packages:
- ca-certificates
- nginx
# Comandos a serem executados na inicialização do container
cmd: "nginx -g 'daemon off;'"
# Usuário padrão para o container
user: "nginx"
# Porta exposta
ports:
- 80/tcp
# Adiciona um novo diretório com permissões específicas
# (exemplo: para arquivos de configuração)
accounts:
groups:
- groupname: "nginx"
gid: 1000
users:
- username: "nginx"
uid: 1000
gid: 1000
env:
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Adicionando arquivos extras (ex: configurações customizadas)
# Se você tem um diretório 'configs/' local, por exemplo
# paths:
# - path: /etc/nginx/conf.d/
# source: ./configs/
Processo de Construção:
Após definir o apko.yaml, a construção da imagem é um processo simples:
- Instale o
apkoCLI. - Execute o comando de construção, especificando o arquivo YAML e o nome da imagem de saída.
# Instalação do apko (exemplo via curl)
curl -sfL https://raw.githubusercontent.com/chainguard-dev/apko/main/install.sh | sh
# Construção da imagem
apko build meu-nginx.apko.yaml meu-nginx:latest
Este comando gera um arquivo .tar.gz contendo a imagem OCI. Para empurrá-la para um registry, pode-se usar apko push ou extrair o tar e usar ferramentas como docker load e docker push. O uso de apko elimina a necessidade de um Dockerfile complexo para a imagem base, concentrando-se apenas nos pacotes e configurações essenciais.
Integrando Assinatura de Imagens com Sigstore e Cosign
A segurança da cadeia de suprimentos não termina na construção de imagens mínimas. É crucial verificar a proveniência e a integridade das imagens. O Sigstore, em conjunto com cosign, oferece uma maneira padrão e robusta de assinar e verificar artefatos de software, incluindo imagens de container.
Assinando uma Imagem com Cosign:
Após construir sua imagem com apko (ou Docker), você pode assiná-la. Primeiro, certifique-se de que a imagem está disponível em um registry (ex: Docker Hub, GCR, ECR).
# Faça login no registry, se necessário
# docker login your.registry.com
# Tag e push da imagem para o registry
docker tag meu-nginx:latest your.registry.com/meu-nginx:latest
docker push your.registry.com/meu-nginx:latest
# Geração de uma chave de assinatura (se ainda não tiver)
# cosign generate-key-pair
# Assinatura da imagem (usando uma chave previamente gerada)
# cosign sign --key cosign.key your.registry.com/meu-nginx:latest
# Alternativamente, para assinatura sem chave com o Fulcio (mais simples)
cosign sign your.registry.com/meu-nginx:latest
O cosign sign sem a flag --key interage com o Sigstore Fulcio para emitir certificados efêmeros baseados em sua identidade OIDC (ex: GitHub, Google), e o Rekor para armazenar a assinatura publicamente em um log de transparência. Isso permite um modelo de assinatura de imagem sem a complexidade do gerenciamento de chaves estáticas.
Verificando a Assinatura:
Em ambientes de CI/CD ou em clusters Kubernetes, a verificação da assinatura pode ser automatizada para garantir que apenas imagens confiáveis sejam implantadas.
# Verificação da assinatura (para assinatura sem chave)
cosign verify your.registry.com/meu-nginx:latest
# Para verificação de assinatura baseada em chave, você precisaria da chave pública
# cosign verify --key cosign.pub your.registry.com/meu-nginx:latest
Um resultado bem-sucedido indica que a imagem não foi adulterada e que sua proveniência pode ser rastreada até o signatário. Integrações com ferramentas como Gatekeeper ou Kyverno no Kubernetes podem impor políticas para só permitir a implantação de imagens verificadas pelo Cosign.
Gerenciamento de Dependências e SBOMs Nativos
Um dos maiores benefícios de Wolfi e Chainguard Images é a geração nativa de SBOMs (Software Bill of Materials). Cada imagem contém um registro completo de todos os pacotes, suas versões, licenças e hashes, permitindo uma visibilidade sem precedentes sobre o conteúdo da imagem.
Extraindo e Analisando SBOMs:
O apko e as ferramentas Chainguard facilitam a extração e o consumo de SBOMs. Eles são geralmente armazenados em formatos padronizados como SPDX ou CycloneDX, que são interoperáveis com scanners de vulnerabilidades e outras ferramentas de segurança.
# Exemplo: Extraindo o SBOM de uma imagem Chainguard
# Assumindo que a imagem já está puxada localmente ou em um registry acessível
# Usando a ferramenta 'melange' (que é a base do apko) ou outras ferramentas de imagem
# para imagens Chainguard publicadas, os SBOMs geralmente estão disponíveis diretamente no registry
# Para uma imagem construída com apko, o SBOM é gerado junto
# apko build meu-nginx.apko.yaml meu-nginx:latest --sbom "./sbom.spdx.json"
# Para consultar SBOMs de imagens já existentes em um registry
# cosign sbom your.registry.com/meu-nginx:latest
A posse de um SBOM permite que equipes de segurança identifiquem rapidamente se uma vulnerabilidade recém-descoberta (CVE) afeta suas imagens em produção, sem a necessidade de escanear toda a imagem. Isso acelera a resposta a incidentes e a aplicação de patches.
Automatizando a Construção e o Deploy Seguro em CI/CD
A verdadeira força das imagens seguras reside na sua integração perfeita em pipelines de CI/CD, garantindo que a segurança seja um aspecto inerente a cada build e deploy. Um pipeline típico envolveria as seguintes etapas:
- Construção da Imagem: Utilizando
apkopara imagens Wolfi customizadas ou um Dockerfile com base Chainguard. - Análise de Segurança (Opcional, mas Recomendado): Embora Wolfi/Chainguard minimizem CVEs, uma varredura adicional com ferramentas como Grype, Trivy ou Syft pode validar o conteúdo do SBOM e identificar configurações de segurança impróprias.
- Assinatura da Imagem: Com
cosign, garantindo que a imagem seja auditável e verificável. - Push para o Registry: Envio da imagem e suas assinaturas (e SBOMs) para um registry OCI seguro.
- Deploy Automatizado: Ferramentas como Argo CD ou Flux CD, integradas com Gatekeeper/Kyverno, verificam as assinaturas do Cosign antes de permitir o deploy no cluster Kubernetes.
Exemplo de GitHub Actions para Construção e Assinatura:
# .github/workflows/build-and-sign.yaml
name: Build and Sign Container Image
on:
push:
branches:
- main
pull_request:
branches:
- main
env:
REGISTRY: your.registry.com
IMAGE_NAME: meu-nginx
jobs:
build-and-sign:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write # Necessário para autenticação OIDC do cosign
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup apko (para builds Wolfi customizados)
uses: chainguard-dev/apko-action@v1 # Ou instale apko manualmente
- name: Build Wolfi Image (se apko.yaml estiver presente)
if: runner.os == 'Linux'
run: |
apko build meu-nginx.apko.yaml "${{ env.IMAGE_NAME }}:latest"
docker tag "${{ env.IMAGE_NAME }}:latest" "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
- name: Build Docker Image (se Dockerfile estiver presente, usando Chainguard base)
# Construa sua imagem via Dockerfile se não estiver usando apko diretamente
run: |
docker build -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" .
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GH_TOKEN }} # Ou use token de um cloud provider
- name: Push Image to Registry
run: docker push "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
- name: Setup Cosign
uses: sigstore/[email protected]
- name: Sign the Image with Cosign
# Assinatura usando OIDC do GitHub Actions com Fulcio e Rekor
env:
COSIGN_EXPERIMENTAL: "true" # Necessário para algumas funcionalidades mais novas
run: |
cosign sign --yes "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
- name: Verify the Image Signature
run: |
cosign verify "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
Este pipeline ilustra como as práticas de segurança, desde a escolha da imagem base até a assinatura e verificação, podem ser automatizadas, criando um guardrail eficaz contra artefatos não autorizados ou comprometidos. A utilização de id-token: write e COSIGN_EXPERIMENTAL: "true" permite que o Cosign utilize o provedor OIDC do GitHub Actions para autenticação, eliminando a necessidade de gerenciar chaves de assinatura manualmente.
Considerações Operacionais e o Futuro da Imagem Segura
A adoção de Wolfi e Chainguard Images representa um investimento significativo na resiliência da cadeia de suprimentos de software. No entanto, a segurança é um processo contínuo. É fundamental manter um monitoramento ativo sobre as vulnerabilidades, mesmo para imagens consideradas seguras. Scanners de vulnerabilidade em tempo de execução, como Falco, podem complementar a segurança baseada em imagens, detectando comportamentos anômalos em containers já implantados.
A evolução para padrões como SLSA (Supply Chain Levels for Software Artifacts) visa formalizar a segurança da cadeia de suprimentos, estabelecendo níveis de garantia para o processo de construção. Ferramentas como Wolfi e apko, com sua ênfase em builds reproduzíveis, SBOMs e assinaturas, estão intrinsecamente alinhadas com os requisitos SLSA, posicionando as organizações para alcançar níveis mais altos de conformidade e segurança. A transição para essas bases mais seguras não é apenas uma melhoria técnica; é uma mudança cultural em direção a uma mentalidade de segurança proativa e transparente, onde a proveniência e a integridade de cada componente são verificáveis em cada etapa do ciclo de vida do software.
Sou um profissional na área de Tecnologia da informação, especializado em monitoramento de ambientes, Sysadmin e na cultura DevOps. Possuo certificações de Segurança, AWS e Zabbix.


