Capítulo 28 — Infraestrutura crítica e segurança setorial: implementação I
Mapa da aula
Aula 28 publicada. Mapa, exemplo, EX055.
flowchart TD
N0["28.1 Da especificação ao código"]
N1["28.2 Codificação segura para os caminhos de controle"]
N2["28.3 A bancada de testes"]
N3["28.4 Evidências"]
N4["28.6 Atividade prática"]
N5["Síntese do capítulo"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Exemplo resolvido"]
EX --> Q["Exercício EX055"]
Desenho lógico
flowchart LR
N0["28.1 Da especificação ao código"]
N1["28.2 Codificação segura para os caminhos de controle"]
N2["28.3 A bancada de testes"]
N3["28.4 Evidências"]
N4["28.6 Atividade prática"]
N5["Síntese do capítulo"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX055"]
[28.1 Da especificação ao código]
|
v
[28.2 Codificação segura para os caminhos de controle]
|
v
[28.3 A bancada de testes]
|
v
[28.4 Evidências]
|
v
[28.6 Atividade prática]
|
v
[Síntese do capítulo]
|
v
[Exemplo resolvido] --> [Exercício EX055]
Objetivos de aprendizagem e conexão
Ao fim deste capítulo você será capaz de (1) implementar um controle de segurança como código funcional com testes, a partir da especificação; (2) aplicar práticas de codificação segura para o tratamento de entradas, a criptografia e o tratamento de erros; (3) construir uma bancada de testes que exercite o controle off-line; e (4) registrar evidências de implementação que remetam aos requisitos. Ele implementa as especificações do Capítulo 27 e prepara o Capítulo 29.
28.1 Da especificação ao código
Parta da especificação do controle (Capítulo 27): cada "deverá" se torna pelo menos um teste antes do código ou junto com ele. Mantenha a implementação pequena e sem dependências onde for possível — o gateway deste livro usa apenas a biblioteca padrão do Python. Estruture-a como recomenda o Capítulo 9: um interpretador (Capítulo 4), um verificador (Capítulo 19), um repositório de estado (contadores contra repetição) e uma interface de saída, cada um testado separadamente. O gateway do TMRP segue essa estrutura, e é por isso que seu bug de NaN pôde ser encontrado e corrigido apenas no validador.
28.2 Codificação segura para os caminhos de controle
- Valide a entrada antes de usá-la: comprimento, MAC, contador, formato, faixa física (laboratórios 3 e 8).
- Compare segredos em tempo constante (
hmac.compare_digest). - Carregue as chaves de um armazenamento protegido, nunca do código-fonte ou de arquivos legíveis por todos.
- Trate toda exceção no caminho de verificação como uma rejeição; nunca aceite por padrão.
- Limite o uso de recursos: tamanho máximo de mensagem, comprimento máximo de fila, limites de taxa por origem.
- Registre as rejeições em log com contexto suficiente para investigar, sem registrar segredos.
Essas regras vêm diretamente dos laboratórios 3, 8 e 11. Cada uma tem um teste no conjunto de testes do gateway.
28.3 A bancada de testes
Uma bancada de testes reproduz off-line o ambiente do controle: RTUs simuladas que enviam mensagens válidas, malformadas, forjadas, repetidas e atrasadas; um SCADA simulado que recebe a saída do gateway; e um relógio que você controla. O Laboratório 15 (Capítulo 40) é uma versão compacta. As bancadas permitem testar modos de falha que seriam inseguros ou impossíveis de provocar num sistema em operação. A bancada do TMRP inclui RTUs simuladas da PS2 e da PS4, um receptor SCADA simulado e um relógio controlável, para que reinícios, atrasos e repetições possam ser produzidos sob demanda. O mesmo arcabouço carrega depois a campanha de injeção de falhas com sementes, e é por isso que investir nele cedo poupa tempo quando começa a verificação do projeto final.
28.4 Evidências
Registre para cada implementação: as versões do requisito e da especificação implementadas; a revisão do código-fonte; os resultados dos testes, com as versões das ferramentas; as limitações conhecidas; e a aprovação do revisor. Isso passa a fazer parte do dossiê de evidências (Capítulo 48). Para o validador de setpoint do TMRP, o registro mostra a versão da especificação, os commits da v1 e da v2, os resultados do T3 para cada uma, a limitação conhecida de que a v1 aceitava NaN e o revisor que fez a pergunta sobre o NaN. Sem esse registro, a constatação posterior do dossiê sobre a situação do T3 teria sido impossível de resolver, porque ninguém conseguiria mostrar qual versão tinha sido aprovada. Registrar as evidências enquanto o trabalho é feito custa minutos; reconstruí-las depois custa dias.
28.5 Exemplo resolvido: validador de setpoint v1 (sintético)
A equipe do TMRP implementa R3 a partir da especificação da §27.5. A versão 1 verifica new < lo, new > hi e o limite de passo, e passa nos testes de exemplo: dentro da faixa, aceito; acima e abaixo da faixa, rejeitado; passo grande demais, rejeitado. A revisão de código pergunta: e o NaN? Na aritmética IEEE 754, toda comparação ordenada com NaN é falsa, então nan < lo e nan > hi são ambas falsas e abs(nan - old) > max_step é falsa — a v1 aceita NaN. A versão 2 rejeita explicitamente valores não finitos e expressa a região segura de forma positiva (lo <= new <= hi), o que é falso para NaN. Os testes baseados em propriedades do Capítulo 30 confirmam a diferença de forma sistemática (Laboratório 11). Essa é a reprovação do teste T3 no cenário de aprovação do Capítulo 10.
28.6 Atividade prática
Implemente um gateway mínimo que combine a saída do interpretador do Laboratório 3 com a selagem do Laboratório 8, de modo que uma leitura Modbus validada se torne um quadro autenticado. Escreva testes para cada caminho de rejeição. Mantenha as duas partes separadas por interfaces claras: o interpretador devolve uma leitura validada ou um motivo de rejeição, e apenas uma leitura validada é selada. Teste cada caminho de rejeição do Laboratório 3 e confirme que nada chega à função de selagem. Depois verifique se o quadro selado passa no receptor do Laboratório 8 e se uma cópia adulterada é recusada. Guarde a chave fora do arquivo-fonte, mesmo neste exercício, para que o hábito já esteja estabelecido antes que apareçam chaves reais.
28.7 Erros comuns e limites
- Código escrito antes que a especificação esteja clara.
- Comportamento de aceitar por padrão diante de exceções.
- Verificações negativas (
if x > hi: reject) que deixam passar o NaN; prefira verificações positivas da região segura. - Chaves no código-fonte.
- Evidências reconstruídas depois do fato.
A primeira versão do validador de setpoint mostra o terceiro erro, e o dossiê do TMRP existe para impedir o último. Sua aceitação do NaN veio das verificações negativas, e a correção foi declarar a região segura de forma positiva. As chaves no código da bancada do TMRP são carregadas de um arquivo protegido, nunca escritas no código-fonte, e toda exceção no caminho de verificação termina numa rejeição registrada em log.
Exercícios — capítulo 28
EX055 — O NaN e seus amigos. Objetivo: encontrar aceitações inseguras. Entradas: validate_v1 no Laboratório 11. Passos: avalie à mão a v1 e a v2 para new = NaN, +∞, −∞, 5.5 e 5.50001 com old = 5.2, e explique cada resultado. Evidência esperada: tabela. Rubrica: 3 = entre os valores especiais, a v1 só aceita NaN (∞ rejeitado por > hi, −∞ por < lo), 5.5 aceito pelas duas (limite inclusivo), 5.50001 rejeitado; a v2 rejeita todos os não finitos; explicações corretas; 2 = um erro; 1 = sem explicações; 0 = nada.
EX056 — Registro das rejeições em log. Objetivo: projetar logs úteis. Entradas: o gateway. Passos: defina um registro de log para cada tipo de rejeição (etiqueta, repetição, inatividade, formato, faixa), com os campos, e explique um campo que você exclui deliberadamente. Evidência esperada: esquema. Rubrica: 3 = os campos permitem a investigação (fonte de tempo, estação, contador, motivo, ID do gateway, hash da mensagem), exclui material de chaves e a carga útil completa onde for sensível; 2 = falta a fonte de tempo ou a estação; 1 = texto livre; 0 = nada.
Síntese do capítulo
Implemente os controles a partir de especificações, com testes para cada "deverá". Codifique o caminho de controle de forma defensiva: valide por completo, compare em tempo constante, proteja as chaves, rejeite diante de qualquer erro, limite os recursos, registre em log de forma útil. Prefira verificações positivas da região segura. Teste numa bancada capaz de produzir as falhas que você não consegue provocar em operação e registre as evidências à medida que avança.
Continue estudando — capítulo 28 de 50
← Capítulo 27 · Índice de capítulos do curso · Capítulo 29 →
Siga para a próxima lição escrita.