CI/CD: como automatizar testes e deploy com segurança

O pipeline possui acesso ao código, artefatos, segredos e produção. Automatizá-lo sem um modelo de ameaça apenas torna o risco mais rápido.

O pipeline é um sistema privilegiado Um pipeline pode: ler código privado; executar conteúdo do repositório; baixar dependências; acessar segredos; publicar pacotes; assinar artefatos; alterar infraestrutura; executar migrações; reiniciar serviços; chegar à produção. Isso o torna um alvo de alto valor. Uma configuração aparentemente simples pode criar uma ponte entre código não confiável e credenciais privilegiadas. A pergunta inicial não é quais etapas adicionar. É quais fronteiras o pipeline precisa preservar. Separe três zonas Zona 1: contribuição não confiável Inclui: pull requests; branches de desenvolvimento; dependências alteradas; scripts do repositório; arquivos gerados; conteúdo vindo de forks. Nessa zona, o pipeline deve possuir acesso mínimo. Zona 2: build controlado Após integração em branch protegida, o pipeline: resolve dependências; executa testes; gera artefato; produz metadados; envia ao registro. Ainda não precisa necessariamente acessar produção. Zona 3: deploy privilegiado O processo: autentica no ambiente; recupera configuração; aplica mudança; executa validações; registra a versão; aciona rollback quando necessário. Essa zona precisa de regras próprias. Misturar todas as etapas em um único workflow com as mesmas permissões elimina a separação. Comece negando permissões A documentação de uso seguro do GitHub Actions recomenda conceder ao GITHUB TOKEN apenas as permissões necessárias. Base: FULL COMMIT SHA representa o SHA completo e verificado da versão escolhida da action. O exemplo precisa ser ajustado antes de uso. O GitHub informa que fixar uma action em SHA completo é a forma de tratá la como referência imutável. Tags podem ser movidas. Defina permissão elevada apenas no job que precisa dela: Não conceda write all por conveniência. Inputs de pull request são dados não confiáveis Este trecho é perigoso: O conteúdo pode ser inserido na construção do script. Prefira variável intermediária: Ainda é necessário escrever shell defensivo. A variável impede que o conteúdo seja interpolado diretamente na estrutura do script. Tenha cautela adicional com: nome da branch; corpo da issue; comentários; nomes de arquivo; outputs de ferramentas; artefatos produzidos por workflows não privilegiados. Evite combinar contexto privilegiado com checkout não confiável Eventos como pull request target são úteis em casos específicos, mas executam no contexto da branch base. O GitHub alerta que combinar gatilhos privilegiados com checkout de código não confiável pode comprometer o repositório. Não use esse contexto para: 1. buscar código da pull request; 2. instalar suas dependências; 3. executar seus scripts; 4. disponibilizar segredos ou token de escrita. Quando precisar comentar ou rotular contribuições, mantenha o workflow privilegiado sem executar o código proposto. Proteja o próprio pipeline Workflows são código de produção. Use CODEOWNERS : Exija: pull request; aprovação; checks; revisão de owners; histórico; restrição de bypass; proteção da branch principal. Uma alteração de uma linha no workflow pode ser mais sensível do que centenas de linhas na interface. O code review eficaz deve classificar mudanças de pipeline como alto risco. Dependências do pipeline também são dependências de software Uma action de terceiros executa no runner com acesso ao workspace, ao token e aos segredos disponíveis. Para cada action: verifique mantenedor; leia código relevante; fixe SHA; acompanhe atualizações; limite permissões; evite actions abandonadas; reduza o número de componentes. Atualizações podem ser propostas por automação, mas precisam passar por revisão e checks. O mesmo vale para: imagens de build; plugins; pacotes; instaladores baixados com curl ; scripts remotos. Nunca execute curl URL sh em um pipeline privilegiado sem verificar origem, integridade e conteúdo. Cache não é artefato confiável Cache é uma otimização. Ele pode conter: dependências; compilação intermediária; dados reutilizáveis. Artefato é uma saída identificada: binário; pacote; imagem; bundle; manifesto; SBOM; migração. Não promova diretamente conteúdo arbitrário de cache para produção. Também trate caches compartilhados entre workflows privilegiados e não privilegiados como possível vetor de contaminação. Build único, digest conhecido Fluxo recomendado: Manifesto hipotético: A produção deve referenciar o digest ou identificador imutável, não apenas uma tag como latest . Proveniência responde de onde o artefato veio A especificação SLSA 1.2 organiza garantias crescentes para o processo de build e sua rastreabilidade até a fonte. Proveniência pode registrar: origem; commit; builder; parâmetros; dependências; artefato produzido; identidade do processo. Ela não comprova que o código está livre de vulnerabilidades. Ajuda a verificar que o artefato corresponde a um processo conhecido e não foi substituído silenciosamente. O NIST SP 800 204D trata especificamente da integração de controles da cadeia de software a pipelines DevSecOps. Assinar não basta; o deploy precisa verificar Ferramentas como Cosign podem assinar e verificar imagens e outros artefatos. Um fluxo coerente: Assinar sem verificar no ponto de consumo cria evidência que ninguém utiliza. A política precisa responder: qual identidade pode assinar; quais repositórios são aceitos; quais workflows podem produzir; como revogar; como tratar indisponibilidade; onde a verificação ocorre. Prefira identidade temporária a segredo permanente Um segredo de nuvem armazenado no CI pode permanecer válido por meses. Com OIDC, quando suportado, o workflow troca uma identidade do pipeline por credenciais temporárias e limitadas. Vantagens: ausência de chave estática no repositório; expiração curta; política por repositório, branch e ambiente; auditoria de emissão; rotação simplificada. O GitHub recomenda OIDC para provedores compatíveis. A política deve restringir: organização; repositório; workflow; branch ou tag; ambiente; audiência; ações permitidas. O artigo sobre segredos no CI/CD aprofunda rotação e escopo. Self hosted runners exigem isolamento real Runners próprios são necessários quando o pipeline precisa: acessar rede interna; usar hardware específico; controlar ambiente; reduzir custo em determinadas cargas. Também aumentam o risco. O GitHub informa que self hosted runners não possuem automaticamente a garantia de uma máquina virtual limpa e efêmera por job e podem ser comprometidos de forma persistente. Controles: não usar para PR pública não confiável; separar por ambiente; limitar repositórios autorizados; restringir rede; remover chaves permanentes; destruir e recriar; não compartilhar workspace; monitorar processos; aplicar patches; bloquear acesso ao metadata service; controlar Docker socket; usar grupos e labels específicas. Arquitetura: Um runner genérico com acesso à rede inteira transforma qualquer job em ponto de movimento lateral. Gates precisam corresponder ao risco Pipeline de uma página estática: build; links; acessibilidade básica; segurança de dependências; deploy; smoke test. Pipeline de pagamento: unitários; integração; contrato; autorização; idempotência; migrações; análise de dependências; imagem; DAST em homologação; aprovação; teste pós deploy; monitoramento. A estratégia de testes deve definir o que bloqueia. Não bloqueie toda entrega por alertas sem contexto. Classifique: severidade; explorabilidade; componente; alcance; correção disponível; exceção; prazo; responsável. Migração precisa ser tratada como parte do release Antes do deploy: validar sintaxe; testar em cópia compatível; estimar locks; verificar espaço; definir compatibilidade; preparar backup; criar observabilidade. Evite pipeline que executa automaticamente qualquer arquivo novo de migração sem análise. Estratégias expansivas permitem publicar aplicação e banco em etapas. Ambiente de produção não deve ser acessado pelo job de teste Separe jobs e credenciais. A separação formal de ambientes reduz o alcance de uma falha. O pipeline também precisa de rollback Defina: versão anterior; comando ou playbook; compatibilidade de banco; configuração anterior; condição automática ou humana; validação após retorno; comunicação. Fluxo: O plano de rollback precisa ser testado antes da crise. Registre a entrega Para cada deploy: serviço; ambiente; versão; digest; commit; aprovadores; horário; migrações; configuração alterada; resultado; métricas iniciais; rollback disponível. Esse registro é mais útil do que depender do histórico do terminal. Checklist de pipeline seguro Fonte [ ] Branch protegida. [ ] Revisão obrigatória. [ ] Workflows com owners. [ ] Inputs não confiáveis tratados. [ ] Actions verificadas e fixadas. Permissões [ ] Token somente leitura por padrão. [ ] Permissões por job. [ ] Ambientes separados. [ ] OIDC quando possível. [ ] Segredos sem longa duração desnecessária. Build [ ] Instalação reproduzível. [ ] Artefato gerado uma vez. [ ] Digest registrado. [ ] Dependências e imagem analisadas. [ ] SBOM ou proveniência quando necessário. Deploy [ ] Identidade exclusiva. [ ] Aprovação proporcional ao risco. [ ] Migração validada. [ ] Healthcheck. [ ] Smoke test. [ ] Monitoramento. [ ] Rollback testado. Operação [ ] Logs sem segredo. [ ] Histórico de execução. [ ] Alertas de falha. [ ] Runners atualizados. [ ] Credenciais revogáveis. [ ] Incidentes investigáveis. CI/CD seguro não é adicionar um scanner ao final. É preservar confiança entre fonte, build, artefato e ambiente. A automação deve tornar a entrega mais repetível sem conceder a cada mudança acesso irrestrito ao que a organização possui de mais sensível.