AUR-563: tutoriais executaveis da cadeia de suprimentos
O que entrega
- Cinco tutoriais em
docs/tutorials/(pt-BR), linkados da pagina inicial (docs/index.md, secao Cadeia de suprimentos) e do indicedocs/tutorials/README.md:sast,sbom-dependency-track,assinatura,xbom,dados-de-analise. - As demonstracoes em
demo/tutoriais/<tutorial>/(run.shcom uma fase por caso,expected/,out/da execucao real, repositorios-exemplo). demo/tutoriais/_lib/cadeia.sh(arquivo novo em_lib; otutorial.shdo AUR-561 nao foi alterado): le oimages.lockdo guia corporativo (AUR-554) em vez de copiar digests (cad_lock,cad_pull,cad_bins,cad_run).tests/acceptance/AUR-563.sh:all,AC-001..AC-004,AC-002-MUT-001; seletor desconhecido sai 64.
Decisoes
- Mesmo contrato do AUR-561. Blocos
<!-- arquivo: PATH -->identicos aos arquivos;<!-- saida: caso -->com linhas literais doout/;--checkporgrep -F; linhasRESULTADO:sao conclusao do script. - Nenhum digest digitado a mao. O unico lugar com digests e
demo/gate-corporativo/images.lock;compose.ymldo Dependency-Track usa${DTRACK_IMAGE}/${POSTGRES_IMAGE}exportados pelorun.sha partir dele. O Semgrep e o da imagem do produto (versao de.board/bootstrap/locks/scanners.yml). - Provedor sempre fixture; aurumcode sempre na imagem do produto, com
--user "$(id -u):$(id -g)". Rede:none, excetosbom-dependency-track(--network host: o gate so aceita https ou IP de loopback) edados-de-analise(um servidor falso que atende como a API do GitHub dentro do mesmo container, com CA de demonstracao gerado a cada execucao em.estado/). api.github.comno aceite. O produto fixa esse endereco para oanalysis_data(nao ha variavel que o troque); o AC-003 o admite na lista de dominios, junto dos reservados. E a API publica do GitHub, nao dado interno.
Achados sobre o produto
- Corrida nas metricas do Dependency-Track (grave). O gate le as metricas
assim que o servidor responde
processing: false, e a avaliacao de politica pode terminar depois. Num servidor novo, a primeira revisao com lodash 4.17.15 leupolicy_violations=0e aprovou o que a politica reprova (2 de 2 vezes); em outra execucao, logo apos trocar a dependencia, leu a violacao antiga e reprovou. O tutorial contorna com um aquecimento e a funcaodt_assenta(linhaassentamento:nosout/) e declara que e contorno do script. Causa nao investigada; vale um card (reler ate estabilizar). --semgrep-binnao existe: o Semgrep e resolvido peloPATH(cmd/aurumcode/aur548.go). O caso de falha poe um Semgrep falso a frente noPATH.- O
check_idleva o caminho do arquivo de regras (semgrep:regras.demo-sem-evalno repositorio;semgrep:policy.regras.demo-sem-evalsob politica em/policy).rule_packslocal e relativo ao repositorio; sob politica precisa ser absoluto. - Com o SAST inconclusivo o parecer ainda diz
No issues found.; so as linhasSAST ... inconclusivemostram o estado real. - O endereco da API do GitHub do
analysis_datae fixo no binario; so o seam de teste Go o troca.AURUMCODE_GITHUB_API_URLvale so para o cliente de PR. aurumcode signvalida o arquivo do bundle, nao o exit do Cosign: Cosign que sai 0 sem bundle falha (cosign exited 0 but wrote no signature bundle). Semquality_gates.supply_chain,signsai 0 sem assinar. Falha de assinatura usa o exit 1 generico (exitQualityNotReviewed).xbom --helpimprime so a linha de uso (sem lista de flags); a politica central precisa de.aurumcode/config.ymlvalido mesmo paraxbom; um catalogo do repositorio ou da politica substitui o embutido por inteiro.- Resultado inconclusivo de
analysis_dataou do Dependency-Track deixa o veredito emComment, nuncaApprove, comwarnoublock. - O Trivy lista
package-lock.json@Nonecomo componente de arquivo sem versao.
Limites (o que NAO foi demonstrado)
- Pacote do registry do Semgrep com sucesso (
p/...): exige rede; o caso prova so a falha sem rede (e nao distingue timeout de recusa de rede). max_critical/max_high: o Trivy roda com--scanners licensee o servidor nao tem feeds, entao critical/high ficam 0; sopolicy_violationse provado.dtrack_unreachable,dtrack_http_errore 403 nao foram executados.- Timeout do Dependency-Track: provado contra um servidor falso (sempre
processing: true), nao contra o Dependency-Track real. - Assinatura keyless, upload do artefato e
verify-blobkeyless: so conferencia estatica (exigem o OIDC do GitHub Actions). Assinatura de imagem real (exige registry). - xBOM: envio ao Dependency-Track, modelo real, prompt sobrescrito pela politica.
analysis_data: GitHub real, release imutavel, repositorio privado com token,analysis_data_invalid, download da copia OSV. O workflow agendado so e conferido estaticamente. Nao ha runner real do GitHub em nenhum tutorial.
Imagens (por digest, de demo/gate-corporativo/images.lock)
dtrack_apiserver=dependencytrack/apiserver@sha256:764dee822521e43d50ad7d0ca5bc35f48968b6b098ef97945e2ecac8c55d52e5
postgres=library/postgres@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
trivy=aquasec/trivy@sha256:7cced7cae583819fc7806d4cbc0dbbc7cad18b99f7d3e235192e6da8c091045c
semgrep=semgrep/semgrep@sha256:65dcd4408adda7c183a6b4550cb1e9b19f7f627a6fbb7e0559bd466bedc44d7b
cosign=sigstore/cosign/cosign@sha256:9e5c2f2edc34351160407ca3416c61855bdf9403c3c5936e0f0be7fc261611b8
Baixadas so para a demonstracao e removidas ao final: dtrack_apiserver,
postgres (pelo down) e cosign. O trivy e o semgrep ja estavam no
host por outros usos do repositorio e nao foram removidos.
Execucao real
Execucao real, em container, com a imagem aurum-tutoriais:local construida do
Dockerfile do worktree, provedor fixture e a rede descrita acima:
bash demo/tutoriais/<t>/run.sh all (os cinco terminaram com exit 0) e
run.sh --check. A saida completa de cada caso e demo/tutoriais/<t>/out/<caso>.log
(1235 linhas no total). No fim do sbom-dependency-track, o caso down mediu 0
containers, redes e volumes restantes.
sast
sast/regra-local: exit_code(s) 3; a regra local achou eval() e o gate de SAST reprovou, sem redesast/registry-sem-rede: exit_code(s) 1; sem rede, o pacote p/security-audit nao baixa: inconclusivo, gate.inconclusive block reprovasast/nosemgrep-e-semgrepignore: exit_code(s) 0,3; sem politica, o nosemgrep e o .semgrepignore silenciam os dois eval() | sob politica, os dois eval() aparecem apesar de nosemgrep e .semgrepignoresast/origem-sast: exit_code(s) 3,0; a politica conta o achado de origem sast | com gate.sources sem sast, o achado do Semgrep e publicado mas nao reprova o gatesast/semgrep-falha: exit_code(s) 1,0; semgrep falhou: inconclusivo e, com block, o gate reprova | semgrep falhou: com warn o alerta e publicado e o comando sai 0, sem aprovarsast/govet-achado: exit_code(s) 3; go vet achou o printf errado na linha adicionada; o achado antigo de legado.go nao entra (caso acrescentado pelo AUR-492)sast/govet-sem-go: exit_code(s) 1; sem go no PATH: inconclusivo (lint_unavailable) e o gate reprova; nada e instalado (caso acrescentado pelo AUR-492)
caso regra-local: ok
caso registry-sem-rede: ok
caso nosemgrep-e-semgrepignore: ok
caso origem-sast: ok
caso semgrep-falha: ok
CHECK OK
sbom-dependency-track
sbom-dependency-track/up: exit_code(s) n/a; servidor, time, chave, quatro projetos e uma politica de violacao prontossbom-dependency-track/sbom-versao-minima: exit_code(s) 0,1,2,2; SBOM CycloneDX 1.7 aceito contra o minimo 1.6 (mesma major) | SBOM 1.7 recusado contra minimo 2.0 (major diferente) | nenhum SBOM foi escrito | "1.6.0" falha na carga da configuracao, antes do Trivy | format: spdx falha na carga da configuracao, antes do Trivysbom-dependency-track/upload-e-metricas: exit_code(s) 0,0; o gate enviou o SBOM, esperou o processamento e aprovousbom-dependency-track/limiares: exit_code(s) 0,3,0; uma violacao de politica acima do limite 0 reprova o gate | com limite 1, a mesma violacao esta dentro do limiar e o gate aprovasbom-dependency-track/violacao-de-politica: exit_code(s) 0,3,0,0; a politica do servidor reprova o componente | sem o componente proibido, o gate aprovasbom-dependency-track/secret-ausente: exit_code(s) 1,0; secret ausente com block: o gate reprova (inconclusivo, nunca aprovado) | com warn, o alerta inconclusivo e publicado e o comando sai 0sbom-dependency-track/timeout: exit_code(s) 0,1; timeout_seconds: 2 vencido com block: inconclusivo e reprovadosbom-dependency-track/projeto-por-microservico: exit_code(s) 0,0,0,0,0,0; servico-a enviado | servico-b enviado ao mesmo projeto | o segundo upload substituiu o primeiro: ms@2.1.3 (servico-a) sumiu do projeto compartilhado (conclusao do script: ms ausente e semver presente) | servico-a no projeto servico-a | servico-b no projeto servico-b | com um projeto por servico, os dois inventarios coexistem (conclusao do script: ms no projeto servico-a, semver no projeto servico-b)sbom-dependency-track/down: exit_code(s) n/a; nenhum container, rede ou volume do tutorial ficou vivo
caso up: ok
caso sbom-versao-minima: ok
caso upload-e-metricas: ok
caso limiares: ok
caso violacao-de-politica: ok
caso secret-ausente: ok
caso timeout: ok
caso projeto-por-microservico: ok
caso down: ok
CHECK OK
assinatura
assinatura/chave-efemera: exit_code(s) 0; sign terminou com exit 0 e relatou o bundle | o bundle sbom_app_cyclonedx.json.sigstore.json existe e nao esta vazio (conferido pelo script)assinatura/verificacao-por-terceiro: exit_code(s) 0,0,1; sbom assinado | o terceiro verificou a assinatura com a chave publica | o SBOM adulterado foi rejeitado pelo Cosign (invalid signature)assinatura/keyless-actions: exit_code(s) n/a; conferencia estatica do workflow e das flags; a assinatura keyless em si nao foi demonstradaassinatura/bundle-artefato: exit_code(s) 0; sbom assinado | o bundle que aurumcode sign escreve casa com o glob do upload-artifact (conferido pelo script; o upload em si so ocorre no Actions)assinatura/falha-cosign: exit_code(s) 1; sign falhou (exit 1) e nomeou o SBOM sem assinatura | nenhum bundle foi deixado no repositorioassinatura/falha-sem-bundle: exit_code(s) 1; cosign saiu 0 sem bundle e mesmo assim sign falhou (exit 1)assinatura/falha-imagem-sem-digest: exit_code(s) 1,1; tag sem digest recusada (exit 1) | o Cosign nao foi chamado (cosign-chamado.txt nao existe) | com digest de 64 hex a referencia passou da validacao e o Cosign (falso) foi chamado (cosign-chamado.txt existe) | o Cosign falso saiu 0 sem bundle, e sign falhou: a recusa anterior foi a da validacao, nao a do Cosign
caso chave-efemera: ok
caso verificacao-por-terceiro: ok
caso keyless-actions: ok
caso bundle-artefato: ok
caso falha-cosign: ok
caso falha-sem-bundle: ok
caso falha-imagem-sem-digest: ok
CHECK OK
xbom
xbom/build-bom: exit_code(s) 0; Build BOM gerado e validado (CycloneDX 1.6) sem provedor de modeloxbom/cbom: exit_code(s) 0; CBOM gerado e validadoxbom/evidencia: exit_code(s) 0,0; CBOM gerado | toda ocorrencia do CBOM cita uma linha que contem o token (conferencia do script)xbom/catalogo: exit_code(s) 0,0; catalogo do repositorio usado | catalogo da politica usado, o do repositorio ignoradoxbom/enriquecimento: exit_code(s) 0; BOM enriquecido pelo modelo (fixture) e verificadoxbom/tipos-documentados: exit_code(s) 2,2,2,64; tipo aibom e apenas documentado: exit 2 com a ancora da documentacao | tipo saasbom e apenas documentado: exit 2 com a ancora da documentacao | tipo netbom e apenas documentado: exit 2 com a ancora da documentacao | tipo desconhecido: exit 64xbom/falha-catalogo-invalido: exit_code(s) 2; catalogo invalido do repositorio: exit 2, sem voltar ao catalogo embutido | nenhum arquivo foi escrito (conferido pelo script)
caso build-bom: ok
caso cbom: ok
caso evidencia: ok
caso catalogo: ok
caso enriquecimento: ok
caso tipos-documentados: ok
caso falha-catalogo-invalido: ok
CHECK OK
dados-de-analise
dados-de-analise/declarado-ou-nao: exit_code(s) 0,0; sem analysis_data declarado o review nao fez nenhuma requisicao e nao imprimiu linha analysis_data | artefato valido: o review aprovou e registrou digest e data na auditoriadados-de-analise/vencido: exit_code(s) 1,0; artefato vencido com block: o review falha (analysis_data_stale) | artefato vencido com warn: exit 0, mas a linha inconclusiva continua no parecerdados-de-analise/cache: exit_code(s) 0,0,1; primeira execucao: artefato remoto verificado e guardado no cache | listagem fora do ar com copia valida em cache: usa o cache e o declara | sem copia em cache e sem listagem: analysis_data_unavailabledados-de-analise/workflow-agendado: exit_code(s) n/a; o workflow tem o agendamento, o teste antes de publicar e a publicacao em duas etapas que o texto descreve (conferencia estatica; a imutabilidade do release depende de 'Immutable releases' no repositorio e NAO foi demonstrada)dados-de-analise/adulterado: exit_code(s) 1,1; arquivo adulterado: analysis_data_digest_mismatch reprova | manifesto adulterado: analysis_data_digest_mismatch reprovadados-de-analise/indisponivel: exit_code(s) 1,1,0; listagem 503 sem cache: analysis_data_unavailable reprova | sem rede e sem cache: analysis_data_unavailable reprova | sem rede com warn: exit 0, mas nunca aprovado silenciosamente
caso declarado-ou-nao: ok
caso vencido: ok
caso cache: ok
caso workflow-agendado: ok
caso adulterado: ok
caso indisponivel: ok
CHECK OK
Aceite
bash tests/acceptance/AUR-563.sh all (offline; o AC-003 usa AURUMCODE_BIN,
.bin/aurumcode ou go build no go-shared). Selecionadores: AC-001..AC-004,
AC-002-MUT-001. Selecionador desconhecido sai 64. Selado:
./.board/bin/oci-run --profile go-unit-offline-v1 --card AUR-563.