Pipeline CI/CD e Segurança
Esta aula aborda a segurança em pipelines de CI/CD, com foco na gestão de secrets, integridade de artefatos, e na aplicação de testes SAST e DAST. O objetivo é capacitar o aluno a implementar práticas seguras em todo o ciclo de desenvolvimento, identificando e mitigando vulnerabilidades de forma automatizada.
Em um mundo de desenvolvimento ágil, os pipelines de CI/CD (Integração Contínua e Entrega Contínua) são o coração da entrega de software. Eles automatizam a construção, o teste e a implantação, permitindo que as equipes entreguem valor rapidamente. No entanto, essa automação também introduz uma nova superfície de ataque: se um pipeline não for projetado com segurança, ele pode se tornar o ponto de entrada para comprometer todo o sistema. Nesta aula, vamos explorar os principais aspectos de segurança em pipelines, desde a proteção de credenciais (secrets) até a análise automatizada de vulnerabilidades em código e aplicações.
Vamos nos aprofundar em quatro áreas críticas: o gerenciamento seguro de secrets, a integridade e autenticidade dos artefatos gerados, e as técnicas de análise estática (SAST) e dinâmica (DAST) que ajudam a detectar problemas antes que cheguem à produção. Ao final, você terá um entendimento prático de como integrar essas práticas no seu fluxo de trabalho, elevando a postura de segurança do seu projeto.
Secrets no pipeline
Secrets são informações sensíveis como senhas, chaves de API, tokens de acesso e certificados. Em um pipeline de CI/CD, esses secrets são frequentemente necessários para autenticar em serviços externos (como registries de contêineres, provedores de nuvem ou repositórios de pacotes) e para configurar o ambiente de execução. O vazamento de um secret pode ter consequências graves, incluindo acesso não autorizado e comprometimento de dados. Portanto, é essencial adotar práticas robustas para armazenar, injetar e rotacionar secrets.
Nunca armazene secrets diretamente no código-fonte ou em variáveis de ambiente definidas de forma estática no arquivo de configuração do pipeline. Em vez disso, utilize ferramentas de gerenciamento de secrets, como HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, ou as funcionalidades nativas do seu provedor de CI/CD (como GitHub Actions Secrets, GitLab CI/CD Variables, Jenkins Credentials). Essas ferramentas permitem que você armazene secrets de forma centralizada, com controle de acesso e auditoria, e os injete no pipeline apenas durante a execução.
# Exemplo de uso de secrets no GitHub Actions
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use a secret
run: echo "${{ secrets.MY_SECRET }}" > secret.txt
# NUNCA imprima o secret em logs!
# Prefira usar a ação específica para o serviço, ex: aws-actions/configure-aws-credentials
Além disso, é importante garantir que os secrets não sejam expostos em logs de build. Configure o pipeline para mascarar valores conhecidos de secrets e evite comandos que possam imprimi-los. Ferramentas como o TruffleHog ou o GitLeaks podem ser usadas para verificar se algum secret foi commitado acidentalmente no repositório. A rotação regular de secrets também é fundamental: defina políticas de expiração e automatize a troca sempre que possível.
Artefatos
Artefatos são os produtos gerados pelo pipeline, como binários, pacotes de código, imagens de contêineres ou arquivos de distribuição. A integridade e a autenticidade desses artefatos são críticas, pois, se um atacante conseguir modificar um artefato, ele poderá introduzir código malicioso no ambiente de produção. Portanto, é essencial proteger o pipeline desde a compilação até a publicação.
Uma prática fundamental é a assinatura de artefatos. Ao assinar um artefato com uma chave privada, você garante que ele não foi adulterado desde a sua criação. Para imagens de contêineres, por exemplo, o Docker Content Trust (Notary) e o cosign (do projeto Sigstore) são ferramentas populares. O cosign permite assinar e verificar imagens em registries, integrando-se com OIDC para fornecer uma cadeia de confiança. Além disso, é importante verificar a integridade dos artefatos por meio de hashes (SHA-256) e mantê-los em um repositório seguro, com controle de acesso restrito.
# Exemplo de assinatura de imagem com cosign
export COSIGN_PASSWORD=my-password
cosign sign --key cosign.key myregistry/myimage:latest
# Verificar a assinatura
cosign verify --key cosign.pub myregistry/myimage:latest
Outra prática relevante é a digitalização de artefatos em busca de vulnerabilidades conhecidas. Ferramentas como Trivy, Grype e Anchore podem ser integradas ao pipeline para escanear imagens de contêineres e pacotes, detectando CVEs (Common Vulnerabilities and Exposures) e sugerindo correções. Isso ajuda a impedir que artefatos vulneráveis cheguem à produção. Além disso, mantenha um registro de proveniência dos artefatos (SBOM - Software Bill of Materials) para rastrear a origem de cada componente.
SAST
SAST (Static Application Security Testing) é uma técnica de análise que examina o código-fonte, o bytecode ou os binários em busca de vulnerabilidades, sem executar o programa. Ela é realizada em estágios iniciais do pipeline, logo após o commit, pois permite identificar problemas rapidamente e a um custo baixo. SAST pode detectar padrões de código inseguro, como injeção de SQL, uso de funções perigosas, vazamento de informações e más práticas de criptografia.
Ferramentas populares de SAST incluem SonarQube, Semgrep, Checkmarx, Fortify e Bandit (para Python). Elas podem ser configuradas para falhar o build quando problemas de severidade alta são encontrados, impedindo que o código seja integrado. No entanto, SAST tem limitações: pode gerar falsos positivos e não detecta vulnerabilidades que só aparecem em tempo de execução. Portanto, é importante ajustar as regras e revisar os resultados manualmente.
# Exemplo de uso do Bandit para análise estática em Python
pip install bandit
bandit -r my_project/ -f html -o bandit_report.html
# O comando acima gera um relatório HTML com as vulnerabilidades encontradas.
Para integrar SAST em um pipeline, adicione uma etapa que execute a ferramenta escolhida e analise a saída. No GitHub Actions, por exemplo, você pode usar ações como SonarSource/sonarqube-scan-action ou github/codeql-action (CodeQL é uma ferramenta de análise semântica da GitHub). Lembre-se de que SAST não substitui a revisão humana de código, mas é um complemento valioso para automatizar a detecção de problemas comuns.
DAST
DAST (Dynamic Application Security Testing) é uma técnica que analisa uma aplicação em execução, simulando ataques de um invasor externo. Diferentemente do SAST, o DAST não tem acesso ao código-fonte; ele testa a aplicação a partir de sua interface externa (HTTP, APIs, etc.). Isso permite detectar vulnerabilidades que só aparecem em tempo de execução, como problemas de autenticação, autorização, configuração incorreta e falhas de lógica de negócio.
Ferramentas de DAST incluem OWASP ZAP, Burp Suite, Acunetix e Qualys Web Application Scanner. Elas são geralmente integradas em estágios mais avançados do pipeline, quando a aplicação está implantada em um ambiente de teste ou staging. O DAST pode ser executado de forma automatizada, gerando relatórios de vulnerabilidades e até mesmo bloqueando a implantação se problemas críticos forem encontrados.
# Exemplo de execução do OWASP ZAP em modo headless
# Instale o ZAP e execute:
zap.sh -cmd -quickurl http://staging.example.com -quickout zap_report.html -quickprogress
# Isso gera um relatório HTML com as vulnerabilidades encontradas.
Uma prática recomendada é combinar SAST e DAST: enquanto o SAST cobre as vulnerabilidades no código, o DAST valida a segurança da aplicação em execução. No entanto, o DAST pode ser mais lento e gerar mais falsos positivos, por isso é importante configurar o escopo e autenticação adequadamente (por exemplo, fornecendo credenciais para áreas autenticadas). Integre o DAST em um ambiente controlado para evitar efeitos colaterais em dados reais.
Boas práticas e observações finais
Além dos tópicos abordados, algumas boas práticas podem melhorar a segurança do seu pipeline: (1) Mantenha as dependências do pipeline atualizadas, pois versões antigas podem conter vulnerabilidades; (2) Use runners efêmeros e isolados para evitar contaminação entre builds; (3) Implemente o princípio do menor privilégio, concedendo apenas as permissões necessárias para cada etapa; (4) Monitore e audite as execuções do pipeline, registrando logs de acesso e alterações; (5) Estabeleça uma cultura de segurança, treinando a equipe e incentivando a revisão de código.
A segurança em CI/CD não é uma etapa única, mas um processo contínuo. À medida que novas vulnerabilidades são descobertas, é preciso ajustar as ferramentas e os processos. Lembre-se de que a automação é uma aliada, mas não substitui a análise humana. Mantenha-se atualizado com as melhores práticas da indústria e participe de comunidades como a OWASP para compartilhar conhecimento.
Referências
- GitHub Actions: Usando secrets
- OWASP Top Ten
- GitLab CI/CD: Secrets
- Docker Content Trust
- Sigstore Cosign
- OWASP ZAP
- SonarQube
- Semgrep
- Trivy
- GitHub Code Scanning
Exercícios
Explique por que nunca se deve armazenar secrets em variáveis de ambiente definidas no arquivo de configuração do pipeline. Dê um exemplo de como fazer de forma segura.
✓ Resposta: Armazenar secrets em variáveis de ambiente no arquivo de configuração é inseguro porque o arquivo fica versionado e acessível a qualquer pessoa com acesso ao repositório, expondo as credenciais. Além disso, logs de build podem revelar o valor. Uma forma segura é usar um gerenciador de secrets, como o GitHub Actions Secrets, que criptografa o valor e o injeta apenas na etapa que o solicita, sem expô-lo em logs. Por exemplo,${{ secrets.DB_PASSWORD }}.Quais são os principais benefícios de assinar artefatos em um pipeline? Cite duas ferramentas para assinatura de imagens de contêineres.
✓ Resposta: Assinar artefatos garante a integridade (não foram alterados) e a autenticidade (origem confiável). Isso impede que um atacante insira código malicioso no artefato sem detecção. Ferramentas: cosign (Sigstore) e Docker Content Trust (Notary).Diferencie SAST e DAST, citando um exemplo de ferramenta para cada e em que estágio do pipeline são aplicados.
✓ Resposta: SAST analisa o código-fonte sem executá-lo, detectando vulnerabilidades em estágios iniciais (ex: SonarQube, Bandit). DAST analisa a aplicação em execução, simulando ataques, e é aplicado em estágios finais (ex: OWASP ZAP). Enquanto SAST foca no código, DAST foca no comportamento externo.Como você integraria uma verificação de vulnerabilidades em imagens de contêineres usando Trivy em um pipeline? Descreva os passos principais.
✓ Resposta: 1) Após construir a imagem, execute o comandotrivy image myimage:latest; 2) Analise a saída para verificar se há vulnerabilidades críticas; 3) Configure o pipeline para falhar se alguma vulnerabilidade de severidade alta for encontrada (ex:--exit-code 1 --severity HIGH,CRITICAL); 4) Gere um relatório (opcional) e publique como artefato.Qual a importância de rotacionar secrets regularmente? Cite uma prática para automatizar a rotação.
✓ Resposta: A rotação regular reduz o risco de um secret vazado ser usado por um longo período. Uma prática é usar serviços como AWS Secrets Manager, que permitem agendar a rotação automática de credenciais, ou implementar scripts que atualizam o secret no gerenciador e atualizam as aplicações que o consomem.