Automatize a integridade de arquivos com sha512sum em CI/CD
Use sha512sum --check --strict checksums.sha512 para comparar arquivos com um manifesto de checksums aprovado
antes que o seu pipeline os utilize. O comando retorna um status de saída diferente de zero quando a
verificação falha, então um artefato alterado ou ausente pode interromper a tarefa. O que importa de
fato é decidir de onde vêm os checksums esperados.
Escolha uma linha de base confiável
Um checksum SHA-512 descreve os bytes de um arquivo. Um checksum correspondente não diz, por si só, quem criou esses bytes. Se alguém conseguir substituir tanto um arquivo quanto o checksum esperado dele, a verificação ainda pode passar.
Para os seus próprios recursos fixos, gere um manifesto a partir dos arquivos aprovados e revise as alterações nesse manifesto. Para um download, obtenha o checksum esperado por um canal autenticado do publicador; quando houver checksums assinados disponíveis, siga primeiro as instruções de verificação de assinatura do publicador. O guia de verificação de imagens do Debian mostra essa distinção entre conferir os bytes baixados e autenticar a origem deles.
O exemplo abaixo registra dois arquivos pequenos como linha de base e depois reutiliza essa linha de base no CI. Gerar novos checksums a partir do que quer que o CI receba anularia a comparação.
Fluxo de verificação de arquivos
Use o Bash e o GNU coreutils. Estes exemplos foram testados com Bash 5.1 e coreutils 8.32 no Ubuntu 22.04, e com Bash 5.3 e coreutils 9.12 no macOS. Confira a implementação antes de continuar:
sha512sum --version
A primeira linha deve identificar GNU coreutils. Um comando com o mesmo nome pode
ser uma implementação diferente. No macOS, o
pacote coreutils do Homebrew fornece as ferramentas GNU; siga as
instruções dele sobre o gnubin no PATH para usar as ferramentas pelos nomes
sem prefixo.
Execute cada bloco Bash abaixo a partir do mesmo diretório pai. Os parênteses mantêm as mudanças de
diretório dentro de um subshell. Esta configuração cria um novo diretório
sha512-demo e se recusa a reutilizar um existente, então executá-la de novo não
sobrescreverá seus arquivos:
(
set -eC
mkdir sha512-demo
cd sha512-demo
mkdir assets
printf 'release 1\n' > assets/app.txt
printf '{"mode":"production"}\n' > assets/config.json
)
Aqui, set -e interrompe o subshell em caso de falha, e
-C faz o redirecionamento de saída se recusar a sobrescrever um arquivo
regular existente. Se a configuração falhar, resolva o erro antes de passar para o próximo bloco;
escolha outro diretório pai se precisar de outra demonstração.
Gerando os hashes
Crie o manifesto uma única vez, enquanto os dois arquivos contêm os bytes aprovados:
(
set -eC
cd sha512-demo
sha512sum -- assets/app.txt assets/config.json > checksums.sha512
)
Cada linha contém um digest SHA-512 hexadecimal de 128 dígitos, um marcador de modo e um nome de arquivo. A lista explícita de arquivos transforma uma entrada ausente em erro e impede que o manifesto calcule o hash de si mesmo. Para os seus próprios arquivos, substitua essa lista e coloque entre aspas os nomes de arquivo que contêm espaços.
Este comando também se recusa a sobrescrever um checksums.sha512 existente. Se a
geração falhar, não use o manifesto recém-criado: ele pode estar vazio ou incompleto. Preserve o
manifesto aprovado anterior ao preparar uma atualização intencional e revise o substituto antes de
adotá-lo.
Verificando os arquivos
Faça a verificação a partir do diretório usado para criar os nomes de arquivo relativos:
(
cd sha512-demo &&
sha512sum --check --strict checksums.sha512
)
Com os arquivos originais, a saída é:
assets/app.txt: OK
assets/config.json: OK
--check lê o manifesto e compara cada arquivo nomeado.
--strict também faz com que linhas de checksum malformadas sejam tratadas como
falha, mesmo quando outras entradas correspondem. Um manifesto vazio também falha. Não adicione
--ignore-missing quando todos os artefatos listados forem obrigatórios. Essas opções
estão documentadas no manual do GNU sha512sum empacotado pelo Debian.
Para testar o cenário de falha, edite sha512-demo/assets/app.txt e execute o bloco de
verificação novamente. Ele informa assets/app.txt: FAILED e termina com status de saída
diferente de zero. Restaure os bytes originais aprovados antes de usar os exemplos de CI
bem-sucedidos abaixo; deixe o manifesto inalterado.
Tratamento de erros e problemas comuns
Problemas de permissão
O verificador precisa de acesso de leitura ao manifesto e aos arquivos, além de acesso pelos diretórios pai deles. Inspecione as permissões e peça ao proprietário o acesso adequado, se necessário. Não altere a propriedade de forma ampla nem torne arquivos sensíveis públicos só para fazer uma verificação passar.
Solução de problemas de hash divergente
Uma divergência significa que os bytes são diferentes da linha de base. Um download truncado, finais de linha alterados ou uma edição intencional podem causá-la. Obtenha uma nova cópia confiável ou investigue a alteração; gerar novamente o checksum esperado a esconderia.
Um erro de arquivo ausente também pode significar que você executou o comando no diretório errado. Caminhos relativos dentro do manifesto são resolvidos a partir do diretório de trabalho do processo, não da localização do manifesto. Para linhas malformadas, obtenha o manifesto original em vez de copiar uma tabela de checksums formatada de uma página web. Mantenha tanto a saída padrão quanto o erro padrão nos logs de CI para conseguir ver a causa.
Integração com CI/CD
Para este exemplo de recursos fixos, adicione sha512-demo/assets/ e o
sha512-demo/checksums.sha512 aprovado ao seu repositório. Os dois fluxos de trabalho abaixo
verificam esses arquivos obtidos via checkout sem gerar o manifesto novamente. Revise as alterações
no manifesto: um pull request que altere tanto os recursos quanto os hashes esperados deles pode
passar nesta verificação.
Coloque a verificação antes da etapa que consome os arquivos e faça a implantação depender do sucesso dela. Se os seus artefatos vierem de outra tarefa, obtenha-os antes da verificação e mantenha o manifesto aprovado separado da saída gerada por essa tarefa.
Exemplo com GitHub Actions
Adicione isto como .github/workflows/integrity.yml ou mescle a etapa de verificação em um fluxo de
trabalho existente. Ele usa actions/checkout para obter o
repositório:
name: Verify file integrity
on: [push, pull_request]
permissions:
contents: read
jobs:
verify:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v7
- name: Verify approved assets
working-directory: sha512-demo
shell: bash
run: sha512sum --check --strict checksums.sha512
Quando declarado explicitamente, o shell bash do GitHub propaga para a
etapa a falha de um comando; consulte a
documentação sobre shells em fluxos de trabalho do GitHub.
Deixe a supressão de falhas desativada nesta etapa.
Exemplo com GitLab CI
Para um runner do GitLab com executor Docker, mescle esta tarefa em .gitlab-ci.yml:
verify_integrity:
image: ubuntu:22.04
script:
- cd sha512-demo
- sha512sum --check --strict checksums.sha512
A imagem do Ubuntu fornece o GNU coreutils. O GitLab
marca a tarefa como falha quando um comando do script termina com status diferente de zero,
incluindo uma mudança de diretório que falhou. Mantenha os comandos como entradas de script separadas
e não ative allow_failure para esta verificação obrigatória.
Detecte alterações após um build do Docker
Para conferir artefatos copiados para fora de uma imagem, verifique esses arquivos exportados com o manifesto aprovado antes de distribuí-los. Um manifesto gerado dentro do build só consegue detectar alterações posteriores nos bytes enquanto esse manifesto continuar confiável. Ele não consegue comprovar a autenticidade das entradas do build nem proteger contra alguém que substitua tanto os arquivos quanto o manifesto.
Saiba o que uma verificação aprovada cobre
A verificação lê todos os arquivos listados, então artefatos grandes exigem ler todos os seus bytes novamente. Ela não verifica arquivos não listados nem a propriedade, as permissões ou os carimbos de data e hora dos arquivos. Um resultado aprovado significa que os bytes listados correspondem à linha de base; isso não prova que o diretório contém apenas arquivos aprovados nem que o build é reproduzível.
