Ir para o conteúdo

Projeto independente de P&D · Colônia

Notas técnicas

Correções curtas de erros de categoria frequentes.

Não normativo

Versão do Companion
1.0
Corresponde ao COADF Core
2.2
Status
Atual
Última revisão

Cada nota corrige um erro de categoria: duas coisas que se parecem e oferecem coisas diferentes.

OpenTelemetry não é uma trilha de auditoria

O OpenTelemetry registra e propaga contexto de execução: quais chamadas uma requisição fez, quanto tempo levaram, onde falharam. Ele foi projetado para ser amostrado, filtrado e transformado no caminho até um backend, e um trace que não é amostrado não é exportado; o filter processor do Collector descarta, por configuração, a telemetria que casa com seus critérios. Sua identidade é uma execução, levada no cabeçalho W3C traceparent. Uma trilha de auditoria responde a outra pergunta, sobre outra unidade: o que aconteceu com uma transação de negócio, quem agiu e com base em que evidência, de forma completa e sem edições posteriores.

  • Nunca amostrar, filtrar ou rotear entradas de auditoria por uma pipeline de telemetria.
  • Correlacionar as duas: registrar o trace_id de auditoria nos spans como atributo. Não reutilizar um identificador de trace distribuído como identidade de auditoria.
  • Classificar aquilo com que se faz a correlação. Um atributo de span sai do repositório de auditoria rumo a exporters, fornecedores e uma retenção própria: uma referência opaca, nunca dado pessoal nem segredo.
  • Contar com que uma transação de negócio atravesse vários traces distribuídos: a requisição de entrada, um job assíncrono, uma decisão tomada dias depois.

OPA é um motor de políticas, não uma autoridade reguladora

O Open Policy Agent avalia regras que alguém escreveu contra entradas que alguém forneceu. Ele desacopla a decisão de sua imposição, e é isso que torna as regras gerenciáveis como dados. Ele não sabe o que um regulamento exige, e uma regra escrita em Rego é exatamente tão correta quanto a leitura do texto que ela codifica. A resposta do motor é evidência de que uma regra foi aplicada, nunca evidência de que a regra estava certa.

  • Toda regra precisa de um dono, de uma fonte e de uma revisão, como qualquer outra interpretação de um texto.
  • Registrar a versão com cada decisão, para que uma correção posterior da regra possa ser distinguida das decisões tomadas sob a versão anterior.
  • Uma suíte de testes que passa para uma política prova que a regra se comporta como seu autor pretendia, e nada sobre se o autor leu o texto corretamente.

Políticas de admissão do Kubernetes não substituem a validação na aplicação

O controle de admissão intercepta requisições ao servidor de API do Kubernetes depois da autenticação e da autorização, antes de o objeto ser persistido. Ele vê Deployments, Pods e ConfigMaps, e as requisições de leitura desses objetos passam totalmente ao largo dele. Ele nunca vê as requisições HTTP que um serviço atende, as mensagens que ele consome nem as respostas que um modelo devolve. Ele julga as requisições à medida que chegam, o que o Kubernetes deixa explícito para um plugin de admissão: quando um LimitRange é adicionado, os pods que já existem continuam inalterados.

  • Usar a admissão para propriedades das cargas de trabalho: imagens fixadas por digest, versões nomeadas, credenciais ausentes onde precisam estar ausentes.
  • Manter a validação de fronteira na aplicação, em cada ponto de entrada que ela tiver.
  • Auditar os objetos existentes separadamente, como faz a auditoria do Gatekeeper; a admissão só vê mudanças.

Event sourcing não é necessário para uma evidência somente de inserção

O event sourcing faz de um log de eventos somente de inserção o sistema de registro e deriva o estado a partir dele. Isso rende um histórico completo por construção, a um preço considerável: todo modelo de leitura é uma projeção, e toda mudança no formato de um evento é uma migração do histórico. Uma trilha de auditoria somente de inserção ao lado do estado comum entrega o que o P-4 do COADF pede (um histórico que só recebe inserções e nunca é reescrito, reconstituível em uma consulta) sem mudar a forma como o resto do sistema guarda seu estado. Privilégios por operação e triggers de recusa bastam para construir uma no PostgreSQL.

  • Escolher event sourcing pelas razões do próprio domínio, não para obter uma trilha de auditoria.
  • Uma tabela somente de inserção, com um papel que só pode inserir, triggers de recusa e escritas idempotentes, realiza evidência somente de inserção sem event sourcing, dentro da fronteira de confiança do próprio banco de dados.
  • Em qualquer dos casos, a entrada é gravada na mesma transação que a mudança que ela registra.

Microsserviços não são necessários para o isolamento probabilístico

A fronteira probabilística é uma propriedade dos caminhos de código: nenhum caminho deixa a saída de um modelo virar um objeto com autoridade sem uma etapa explícita e registrada. Uma fronteira de módulo que o build impõe mantém essa propriedade dentro de um único processo, com contratos de importação em Python ou regras de arquitetura como testes unitários em Java. Uma fronteira de rede acrescenta imposição pela infraestrutura e, com ela, versionamento de contratos, falhas parciais, novas tentativas e propagação de contexto entre saltos, que são novos lugares onde a propriedade pode se perder.

  • Implantar o componente probabilístico separadamente quando escalar, isolar uma biblioteca de fornecedor ou liberar de forma independente o pedir, não porque um princípio o pede.
  • Impor a fronteira de módulo com um teste de arquitetura em qualquer dos casos.
  • Quando a fronteira é uma rede, validar de novo no lado que recebe.

A tipagem estática não substitui a validação em tempo de execução nas fronteiras externas

Um sistema de tipos confere o código contra ele mesmo. Numa fronteira externa, os dados vêm de fora do código: um modelo, um cliente, uma fila. As anotações de tipo do TypeScript são apagadas antes de o programa rodar e JSON.parse é tipado como retornando any; o runtime do Python não impõe as anotações de tipo; e um tipo Java descreve o que se pediu que um desserializador produzisse, não o que o remetente enviou. O tipo é uma promessa que a fronteira tem de cumprir, em tempo de execução, com um esquema.

  • Derivar o tipo estático do esquema de tempo de execução sempre que a linguagem permitir.
  • Validar em cada lado que recebe, não só no ponto de entrada web.
  • Manter casts fora do código de fronteira: um cast é onde o sistema de tipos para de verificar.

Uma pipeline de CI verde não prova que um controle seja suficiente para a arquitetura

Uma pipeline verde prova que as verificações que ela executou passaram. Ela não diz nada sobre verificações que foram puladas e reportadas como bem-sucedidas, seleções que não casaram com teste algum, fences colocados no caminho errado, ou propriedades para as quais ninguém escreveu verificação. O modelo de relatório de controles do COADF enuncia a mesma regra pelo outro lado: um controle só é relatado como imposto quando sua evidência rodou na execução identificada e passou.

  • Registrar, a cada execução, quais verificações rodaram e quantas asserções foram executadas.
  • Provar os dentes de cada fence no seu caminho real, e prová-los de novo quando o caminho mudar.
  • Revisar o que não é verificado com a mesma seriedade que o que é.

COADF Engineering Companion 1.0 · não normativo · corresponde ao COADF Core 2.2

Direitos de publicação reservados. Nenhuma licença pública é concedida, no momento, para o COADF Engineering Companion 1.0 nem para seus exemplos de referência.

Status de propriedade intelectual e de publicação