Valint é a principal ferramenta do Scribe para criar, gerenciar, assinar e verificar evidências. Em um num post anterior, abordamos a teoria do uso de assinatura e verificação de evidências como ferramenta principal na validação da segurança do seu pipeline de CI/CD. Como um breve lembrete, o modelo proposto pelo Scribe inclui vários blocos de construção que podem ser embaralhados e empilhados da maneira que melhor se adequar às suas necessidades. Os blocos de construção incluem as evidências coletadas (SBOMs, SLSA proveniência, quaisquer resultados de testes de terceiros que você deseja incluir), o contexto ambiental das evidências coletadas (quem as criou, onde, quando, etc.) e a política que você deseja aplicar a essas evidências.
Como as políticas que você deseja aplicar às suas evidências são um fator-chave neste modelo, pensamos em dedicar uma postagem no blog para explorar o potencial do mecanismo de políticas que oferecemos com mais detalhes.
Neste artigo, abordaremos a política mais básica que elaboramos (assinar e verificar informações). Abordaremos a aparência do modelo para uma política mais complexa e daremos alguns exemplos padrão de políticas, como como verificar se um usuário específico foi aquele que criou o último branch 'principal' ou como verificar se o seu pipeline foi executado inclui um teste de ferramenta de terceiros que deve ser incluído.
Comece aqui: assinatura e verificação de evidências
Valint é uma ferramenta muito versátil, mas para manter este artigo simples usaremos principalmente a interface CLI do Valint como exemplo.
O primeiro passo seria baixar Valint:
curl -sSfL https://get.scribesecurity.com/install.sh | sh -s -- -t valint
O comando para criar um SBOM a partir de um repositório ou imagem é 'bom'. Então, por exemplo, se você quiser bom
a imagem de busybox:latest
o comando ficará assim:
$HOME/.scribe/bin/valint bom busybox:latest -o attest -f
Observe que attest
é um apelido para attest-cyclonedx-json
.
Por padrão, Valint está usando Loja de assinaturas fluxo interativo como o mecanismo por trás do mecanismo de assinatura incorporado na biblioteca Cocosign da Scribe. Esta biblioteca trata de assinaturas digitais para assinatura e verificação. Depois de aplicar o comando, você precisará primeiro aprovar que deseja assinar a evidência com uma opção S/[N]:
Você também pode usar PKI padrão para assinatura (suportamos certificados x509). Existem várias opções para armazenar a chave de assinatura – por exemplo, KMS, armazenamento secreto do GitHub, e você pode configurar facilmente o Valint para usar qualquer mecanismo de assinatura que desejar.
Supondo que você aprove a assinatura, você será direcionado para o Sigstore em seu navegador, onde precisará fazer login usando sua conta GitHub, sua conta Google ou sua conta Microsoft:
Depois de fazer login, você verá que o login foi bem-sucedido:
nesse ponto você pode fechar o navegador e voltar para o seu shell, onde poderá ver que a evidência foi criada com sucesso.
O atestado é gravado por padrão no cache local cuja localização é fornecida pelo --output-directory
sinalizador no sinalizador do arquivo de configuração. Você também pode usar o -arquivo de saída sinalizador para fornecer um caminho personalizado para o atestado.
Agora que criamos um atestado assinado, vamos tentar verificar se ele existe e está assinado. O comando para verificar evidências é verify
. A forma de usá-lo é quase idêntica à bom
comando, exceto que usaremos o sinalizador -i
que é curto para --input-format
e o padrão para isso é, como em bom
, atestar-ciclonedx-json. O comando verify primeiro procurará as evidências necessárias no local padrão usado pelo Valint. Você pode especificar um local diferente se quiser salvar as evidências e procurá-las mais tarde.
Então, se quisermos verificar o busybox:latest
atestado de imagem que geramos e assinamos no exemplo anterior, o comando ficará assim:
$HOME/.scribe/bin/valint verify busybox:latest -i attest
Supondo que você fez tudo certo, o resultado deve ficar assim:
Você pode ver a lista de emails que inclui o email do assinante no atestado original e também pode ver o tipo de atestado que foi verificado, neste caso, cyclonedx-json.
Parece bastante simples, certo? Vamos aumentar um pouco.
Modelos de política
A Privacidade consiste em um conjunto de módulos. A política é verificada se todos os módulos que ela inclui forem avaliados e verificados. Um módulo é verificado se for encontrada QUALQUER evidência que esteja em conformidade com a configuração e configuração do módulo.
As políticas são configuradas como parte do arquivo de configuração do Valint, na seção de políticas. Este é um exemplo de parte de um arquivo de configuração Valint, a parte que contém políticas potenciais.
Lembre-se de que você não precisa incluir um arquivo de configuração em seu projeto – Valint pode funcionar perfeitamente apenas com as opções padrão habilitadas. Além disso, como tudo neste arquivo é opcional, é perfeitamente válido ter um arquivo que inclua SOMENTE suas políticas.
O arquivo de configuração, denominado por padrão .valint.yaml, deve ser incluído na raiz do seu repositório. Com base nas políticas incluídas neste arquivo, ao executar o comando valint verify
ele executará quaisquer políticas e módulos habilitados. Como a política básica de 'verificação' é o padrão, você não precisa configurar nada para o verify
comando para funcionar corretamente mesmo sem um arquivo .valint.yaml.
Qualquer política que você adicionar ao arquivo de configuração depende de evidências para procurar. Por padrão, quando você executa o comando 'bom' em seu pipeline, a evidência resultante será carregada no armazenamento de evidências do Scribe. Da mesma forma, quando você executa o comando ‘verify’, ele procurará as evidências no armazenamento de evidências do Scribe. Você pode alterar esse padrão e usar um OCI ou cache como seu armazenamento de evidências, mas para este artigo, assumiremos que o padrão é usado e todas as evidências são carregadas e extraídas do armazenamento de evidências do Scribe.
Assim, com base neste exemplo, vejamos os componentes de uma política. O Privacidade suporta os seguintes campos:
- nome, o nome da política (obrigatório).
- permitir, habilite o módulo (o padrão é falso).
- módulos, lista de configurações do módulo de política.
A módulo seções suportam os seguintes campos:
- nome, o nome do módulo de política (obrigatório).
- permitir, habilite o módulo (o padrão é falso).
- tipo, tipo de módulo, atualmente suportando verificar-artefato e proprietário do git.
- partida, combine as evidências com um contexto específico.
- entrada, configuração específica do módulo.
Uma política pode ter vários módulos e todos os módulos habilitados serão executados assim que você executar o comando ‘verify’.
Como sei que uma lista seca de campos não é muito informativa, vamos direto para a próxima seção, exemplos de políticas.
Exemplos de políticas
Política de verificação de imagem
Vamos começar com a política mais simples, que expressa o fluxo de verificação de sinal Valint.
atestar: cocosign: políticas: - nome: verify_policy enable: true módulos: - nome: assinado_sbom tipo: verify-artifact enable: true entrada: assinado: true formato: attest-cyclonedx-json identidade: emails: - barak@scribesecurity.com
Novamente, esta política deve ser incluída no arquivo .valint.yaml na raiz do seu repositório. Para que funcione, você precisa ter criado um SBOM assinado com antecedência, executando o valint bom
comando. Quando estiver pronto para verificá-lo, você precisará executar o valint verify
comando.
Olhando para este exemplo podemos ver que a política está habilitada e que possui um módulo habilitado do tipo ‘verify-artifact‘
. O módulo verifica se a entrada está assinada, está no formato ‘attest-cyclonedx-json’
, e que foi assinado pela identidade representada pelo email ‘barak@scribesecurity.com’
.
Para executar esta política, precisaremos executar o verify
comando em nosso pipeline assim:
valint verify busybox:latest
Uma vez que o verify
comando agora é baseado na política que fornecemos, ele procurará por um busybox:latest
evidência em seu depósito de evidências Scribe. Ele procurará um SBOM assinado no formato `cyclonedx-json`
e verificaria se a identidade que assinou o SBOM utiliza o e-mail prescrito na política `barak@scribesecurity.com`
.
Você pode dizer que pode haver várias imagens como essa naquele depósito de evidências e você está certo. É aqui que o contexto entra em jogo. Por padrão, verify
O comando procurará a correspondência mais próxima disponível. No entanto, você pode especificar que o comando precisará corresponder ao contexto do ID de execução do pipeline ou ao sistema de compilação no qual o artefato foi criado. match:
com o tipo de contexto apropriado. Por exemplo:
correspondência: context_type: github git_url: github.com/my_org/myimage.git branch: main
Neste caso, as evidências deveriam ter sido geradas pelo Github, pelo repositório nomeado pelo git_url
e pela main
ramificação desse repositório. É importante usar o contexto certo quando necessário para garantir que suas políticas verifiquem exatamente o que você deseja que elas verifiquem.
Política de verificação binária
Vamos examinar outro exemplo. Esta política tem como objetivo verificar se um arquivo exe que estamos verificando veio de um repositório específico e foi assinado por um dos vários indivíduos conhecidos.
atestar: cocosign: políticas: - nome: verify_policy enable: true módulos: - nome: binary_module tipo: verify-artifact enable: true entrada: assinado: true formato: attest-cyclonedx-json identidade: emails: - barak@scribesecurity.com - mikey@scribesecurity.com - adam@scribesecurity.com correspondência: target_type: arquivo context_type: azure git_url: https://dev.azure.com/mycompany/somerepo # Git url do ambiente. nome_entrada: meu_binário.exe
Olhando para este exemplo podemos ver que a política está habilitada e que possui um módulo habilitado do tipo ‘verify-artifact‘
O módulo verifica se a entrada está assinada, se está no formato ‘attest-cyclonedx-json’
, e que foi assinado por 1 dos 3 e-mails permitidos listados no módulo. Além disso, verifica se o verify
comando recebe uma entrada para verificar se a entrada é nomeada ‘my_binary.exe’
, que a entrada é um arquivo criado no Azure e que veio de uma URL git específica: https://dev.azure.com/mycompany/somerepo
.
Como você pode ver, há muito mais requisitos neste exemplo para que a política seja verificada.
Para executar esta política, precisaremos executar o verify
comando em nosso pipeline assim:
valint verify file:my_binary.exe
Para garantir que seu armazenamento de evidências do Scribe tenha uma versão assinada deste binário, você deve primeiro criar as evidências como esta:
valint bom file:my_binary.exe -o attest
Política de verificação de evidências de terceiros
Em nosso exemplo final, vamos ver como podemos verificar se uma ferramenta de terceiros que usamos funcionou corretamente em nosso pipeline e criou o resultado que esperamos na forma de um arquivo JSON.
atestar: cocosign: políticas: - nome: verify_policy enable: true módulos: - nome: tipo de regra de terceiros: verify-artifact enable: true entrada: assinado: falso formato: attest-genérico identidade: emails: - bob@scribesecurity. com correspondência: target_type: context_type genérico: azure git_url: https://dev.azure.com/mycompany/somerepo git_branch: main input_name: 3rd-party-scan.json
Neste exemplo, imaginamos que em algum ponto do pipeline, executamos uma ferramenta de terceiros que criou, como resultado, o arquivo `3rd-party-scan.json`. Para satisfazer a política, esse arquivo deveria ter sido originado do Azure DevOps, acionado pelo `https://dev.azure.com/mycompany/somerepo` repositório e assinado por `bob@scribesecurity.com`.
Para gerar a evidência que procuramos, logo após a execução da ferramenta de terceiros, precisamos capturar o arquivo resultante e transformá-lo em evidência usando Valint:
valint bom 3rd-party-scan.json -o attest-generic --predicate-type https://scanner.com/scan_format
O que as evidências provam?
Vimos que podemos usar Valina para verificar várias coisas em nosso pipeline. Para que essa habilidade realmente pode ser usada?
Vamos imaginar que nosso pipeline foi violado e que alguns bandidos começaram a fazer coisas nele e com ele que não queremos que façam. Ao verificar se as diferentes etapas do pipeline ocorreram conforme o esperado, produzindo os resultados esperados e assinadas pelo pessoal aprovado, tornamos muito mais difícil para os bandidos nos enganarem.
Um ataque potencial é substituir o arquivo binário no final do pipeline para que a versão que seus clientes obtenham seja maliciosa e não a original. Ao assinar sua versão e pedir a seus clientes que verifiquem essa cópia mestre, você pode ter certeza de que todos eles usam o mesmo arquivo que você produziu e não uma falsificação inteligente.
Este modelo de criar provas e depois verificá-las está apenas a começar. Estamos constantemente trabalhando para adicionar recursos adicionais ao Valint para torná-lo ainda mais robusto e versátil. Enquanto isso, encorajo você a conferir nosso documentação para saber mais sobre o que o Scribe tem a oferecer e o que mais você pode fazer com o Valint. Valint é gratuito para baixar e usar, então nada deve impedi-lo de experimentar esta ferramenta hoje.
Este conteúdo é oferecido a você pela Scribe Security, um fornecedor líder de soluções de segurança de cadeia de suprimentos de software ponta a ponta – fornecendo segurança de última geração para artefatos de código e processos de desenvolvimento e entrega de código em todas as cadeias de suprimentos de software. Saiba mais.