Pular para o conteúdo

Princípios

CIA, autenticação, autorização, responsabilização, não-repúdio, privilégio mínimo, defesa em profundidade, zero trust, seguro por desenho e por padrão.

Os princípios existem porque controles isolados envelhecem e as perguntas não. Quando um requisito novo aparece, é a eles que se volta para decidir.

Confidencialidade, integridade, disponibilidade#

A tríade CIA é o enquadramento mais antigo e o mais útil: todo controle serve a pelo menos um dos três, e um controle que não serve a nenhum é cerimônia.

Falha típicaNa prática, aqui
Confidencialidadevazamento, log com dado pessoal, chave no repositóriocifrar em repouso, Seg.segredo, dataforge seguranca
Integridadedado alterado sem marca, log forjadoAEAD, Seg.auditoria, Seg.escapar_log
Disponibilidadenegação de serviço, exaustão de memóriaSeg.limitador, Seg.json_seguro, limite de corpo

Autenticação, autorização, responsabilização, não-repúdio#

Quatro perguntas diferentes, confundidas o tempo todo. Um sistema que autentica muito bem e não autoriza direito entrega o banco inteiro a um usuário legítimo.

dataforge
adopt Arcane.Crypto as Crypto
adopt Arcane.Seguranca as Seg
adopt Arcane.OS as OS

// 1. AUTENTICACAO — quem e voce?
guardada := Crypto.hash_password("uma senha bem forte 2026")
assert Crypto.verify_password("uma senha bem forte 2026", guardada)

// 2. AUTORIZACAO  voce pode fazer isto?
steady PERMISSOES := {
    "leitor": ["ler"],
    "editor": ["ler", "escrever"],
    "admin":  ["ler", "escrever", "apagar"]
}

action pode(papel, acao):
    yield acao in (PERMISSOES[papel] ?? [])

assert pode("editor", "escrever")
assert pode("editor", "apagar") is no

// 3. RESPONSABILIZACAO  quem fez, e quando?
livro := Seg.auditoria($"{OS.temp_dir()}/df-princ-{randint(100000, 999999)}.log")
livro.registrar("apagou_pedido", {"pedido": 42}, quem := "ana")
assert livro.conferir()["ok"]

// 4. NAO-REPUDIO  da para provar que foi voce?
// Com chave simetrica isto prova a origem ENTRE AS DUAS PARTES,
// e nao perante um terceiro: quem confere tambem consegue forjar.
chave := Seg.chave_de_assinatura()
recibo := Seg.assinar({"pedido": 42, "por": "ana"}, chave,
    proposito := "recibo")
assert Seg.ler_assinado(recibo, chave, proposito := "recibo")["valor"]["por"] is "ana"

out "os quatro, e o quarto com a ressalva escrita"

Privilégio mínimo#

Cada parte recebe exatamente a autoridade de que precisa, e por exatamente o tempo em que precisa. É o princípio que mais reduz o estrago de uma falha — ele não impede a invasão, ele limita o que ela alcança.

Onde aplicarComo
no móduloArcane.Capacidade recusa o adopt do que não está na lista
no bancoa conta da aplicação não é a dona do esquema; service_role fica fora do bundle
no tokenpropósito e prazo — um token de confirmar e-mail não troca senha
no contêinerUSER forge no Dockerfile, e é o que dataforge devops gera
no arquivoSeg.caminho_seguro(base, pedido) — a pasta base é a autoridade
dataforge
adopt Arcane.Capacidade as Cap

// A autoridade AMBIENTE e o que se recorta: o 'adopt' de um modulo
// fora da lista e recusado pelo NOME da capacidade que falta.
permitido := Cap.limites()
out $"o que este arquivo alcanca: {len(permitido)} capacidade(s)"

// E o que ela NAO faz, dito no proprio modulo: ela nao tira o que
// ja foi ENTREGUE. Numa linguagem de capacidade, poder e o que se
// PASSA, nao o que esta no ar — e e por isso que bloquear o 'adopt'
// e a fronteira certa, e nao uma meia-medida.

Defesa em profundidade#

Nenhum controle é confiável sozinho. A pergunta que define o desenho é: quando esta camada falhar, o que segura?

CamadaExemploO que ela ainda deixa passar
1. Validar na entradaSeg.numero_seguro(pagina, 1, 1000)um valor válido e malicioso
2. Consulta parametrizadadb.query(sql, [valor])nada de SQL — mas o dado vai para a tela
3. Codificar na saídaSeg.escapar_htmlnada de XSS — mas o navegador pode carregar de fora
4. CabeçalhosCSP, X-Content-Type-Optionsum bug de lógica de autorização
5. Autorização por recursoo dono do pedido é quem o lêuma credencial roubada
6. AuditoriaSeg.auditorianada — mas agora dá para investigar

Zero trust#

O modelo antigo era um perímetro: dentro da rede, confia-se. Zero trust parte de que não há dentro — toda requisição é autenticada, autorizada e registrada, venha de onde vier.

RegraO que ela quebra do modelo antigo
nunca confie na rede de origem“é interno” deixa de ser argumento
autentique cada requisiçãoa sessão longa e implícita dá lugar a token curto
autorize por recurso, e não por papel sóser admin não basta: é admin daquele tenant
presuma violaçãoo log e a auditoria não são opcionais

Seguro por desenho, e seguro por padrão#

São coisas diferentes, e a segunda é a que mais rende. Por desenho é a arquitetura escolhida para tornar a falha impossível; por padrão é o estado inicial ser o mais restritivo — o que protege quem nunca leu a documentação.

DecisãoPor desenho ou por padrãoO que ela evita
record é imutável, pontodesenhoum valor compartilhado mudar sob os pés de quem o leu
limpar_html usa lista de permitidosdesenhoa lista de proibidos que esqueceu <svg onload>
Seg.segredo imprime ***padrãoo vault inteiro impresso para depurar
a grade da Vitrine já vem paginadapadrãouma listagem sem teto travar o painel
POST não é repetido sem chave de idempotênciapadrãoa cobrança em dobro de uma retentativa
Kiln responde 404 de verdade, não 200padrãoum monitor achando que está tudo bem