01
A troca atômica é a causa da indisponibilidade, não a solução
O modelo mental que produz o incidente é o de que um segredo é um valor único, guardado num lugar único, e que rotacionar significa substituir esse valor por outro num instante determinado. Esse modelo funcionaria se o sistema fosse um único processo lendo uma única variável, e é falso em qualquer arquitetura que tenha mais de uma instância. Na prática o segredo está simultaneamente no gerenciador de segredos, na variável de ambiente do contêiner que subiu há três dias, no cache em memória do processo que leu a variável uma vez na inicialização, no painel de configuração do parceiro externo, no token que já foi emitido e ainda não expirou, e na fila de mensagens que guarda uma requisição assinada esperando processamento. Trocar o valor na origem não troca nenhuma dessas cópias no mesmo instante.
A consequência é que existe sempre uma janela de propagação, e ela não é um detalhe operacional que pode ser encurtado até desaparecer. Ela é composta pelo tempo de detecção do gerenciador de segredos, pelo tempo de reinício ou de recarga de cada instância, pelo tempo de vida do cache local, pelo tempo de vida dos tokens já emitidos e pelo tempo que o parceiro externo leva para aplicar a mudança do lado dele, que pode ser de dias. Durante essa janela, parte do sistema conhece a chave nova e parte conhece a antiga, e as duas partes precisam conseguir conversar. Uma troca atômica declara por decreto que a janela tem duração zero, e todo tráfego que cai dentro dela falha.
TROCA ATOMICA (o que quebra)
t0: chave K1 em todo lugar verificacao: aceita K1
t1: gerenciador passa a servir K2 emissao: K2 em 2 de 12 instancias
|
+-> instancia A (reiniciada) assina com K2 -> receptor so aceita K1 FALHA
+-> instancia B (nao reiniciada) assina com K1 -> parceiro so aceita K2 FALHA
+-> webhook em voo assinado com K1 chega em t1+3s FALHA
+-> token JWT emitido em t0-600s ainda valido por mais 3000s FALHA
Janela de falha = max(propagacao interna, TTL de token, aplicacao no parceiro)
ROTACAO POR CONJUNTO (o que funciona)
fase 1 verifica: {K1, K2} assina: K1 <- K2 introduzida, ninguem usa ainda
fase 2 verifica: {K1, K2} assina: K1 <- propaga ate 100% conhecer K2
fase 3 verifica: {K1, K2} assina: K2 <- promocao: so muda quem EMITE
fase 4 verifica: {K2} assina: K2 <- retirada, apos uso de K1 zerar
Em nenhuma fase existe instante em que quem verifica desconhece
a chave que alguem esta usando para assinar.A inversão que resolve o problema é simples de enunciar e incômoda de aceitar: durante a rotação, o segredo deixa de ser um valor e passa a ser um conjunto. Quem verifica aceita todos os membros válidos do conjunto, quem emite escolhe exatamente um. Como verificar é uma operação tolerante e emitir é uma operação exclusiva, é possível introduzir uma chave nova sem que nada mude de comportamento, propagar essa introdução no ritmo que a infraestrutura permitir e só então mover a emissão. A troca deixa de ser um evento instantâneo e vira uma transição com quatro estados observáveis, e a indisponibilidade desaparece porque em nenhum momento existe alguém verificando com um conjunto que não contém a chave que o outro lado está usando.