◇ OpenCyber Academy
Ingeniería · Capítulo 4 · Español

Capítulo 4 — Programación I

Aprendizaje gratuito y abierto para quienes desean proteger a las personas y la tecnología. No se necesita una cuenta para estudiar ni consultar las respuestas.

Capítulo 4 — Programación I

Mapa de la lección

Lección 04 publicada. Mapa, ejemplo, EX010.

flowchart TD
  N0["Resultados de aprendizaje"]
  N1["4.1 Decisiones como funciones"]
  N2["4.2 Tipos exactos"]
  N3["4.3 Pruebas con tramas decodificadas sintéticas"]
  N4["4.3b Registrar lo que decidió la función"]
  N5["Síntesis del capítulo"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5
  N5 --> EX["Ejemplo resuelto"]
  EX --> Q["Ejercicio EX010"]

Dibujo lógico

flowchart LR
  N0["Resultados de aprendizaje"]
  N1["4.1 Decisiones como funciones"]
  N2["4.2 Tipos exactos"]
  N3["4.3 Pruebas con tramas decodificadas sintéticas"]
  N4["4.3b Registrar lo que decidió la función"]
  N5["Síntesis del capítulo"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX010"]
[Resultados de aprendizaje]
    |
    v
[4.1 Decisiones como funciones]
    |
    v
[4.2 Tipos exactos]
    |
    v
[4.3 Pruebas con tramas decodificadas sintéticas]
    |
    v
[4.3b Registrar lo que decidió la función]
    |
    v
[Síntesis del capítulo]
    |
    v
[Ejemplo resuelto] --> [Ejercicio EX010]

Resultados de aprendizaje

Usted podrá (1) escribir funciones pequeñas y puras que decidan si un mensaje de TO está permitido; (2) representar direcciones industriales con tipos exactos; (3) probar con tráfico decodificado sintético, nunca con tráfico real de planta.

4.1 Decisiones como funciones

Una lista de permitidos para Modbus es una función permit(source, function_code, register) -> (bool, reason). Hacerla pura —entradas que llegan, decisión que sale, sin configuración oculta— permite probarla en un portátil con registros sintéticos. La cadena del motivo importa: «register-out-of-range» le dice a un revisor que el HMI intentó escribir fuera del bloque de puntos de consigna, lo cual es una historia distinta de la de una estación desconocida que usa una función de diagnóstico. Lena mantiene las cadenas de motivo cortas y fijas para que los registros puedan contarse por motivo.

4.2 Tipos exactos

Guarde los códigos de función como enteros, los rangos de registros como objetos range y las identidades de las estaciones como cadenas fijas tomadas de un inventario. Un error frecuente trata la notación 4xxxx de «registro de retención» como una cadena y compara por prefijo, de modo que 400500 parece 40050. Convierta las direcciones una sola vez, al analizarlas, en enteros con desplazamientos documentados. Lena escribe una única función de conversión para las direcciones de registro y la prueba en ambos extremos del rango escribible del HMI, 40001 y 40010, y un paso fuera de cada uno. Los nombres de estación provienen del inventario, de modo que una errata en la lista de permitidos hace fallar una búsqueda en lugar de crear en silencio una estación nueva que no coincide con nada.

4.3 Pruebas con tramas decodificadas sintéticas

El laboratorio siguiente nunca abre un socket; comprueba tuplas ya decodificadas. Es deliberado. El código del curso no debe enviar tráfico Modbus a ningún dispositivo. Escriba una prueba por regla, más los registros límite 40001 y 40010.

"""Lab: Modbus function-code allow-list on synthetic, already-decoded requests (no network)."""
ALLOW = {("HMI-1", 3), ("HMI-1", 6), ("HIST-1", 3), ("HIST-1", 4)}  # (source, function code)
WRITE_REGS = {("HMI-1", 6): range(40001, 40011)}                     # HMI may write setpoints only
reqs = [("HMI-1", 3, 40001), ("HMI-1", 6, 40003), ("HMI-1", 6, 40050),
        ("HIST-1", 3, 30001), ("HIST-1", 16, 40001), ("ENG-WS", 8, 0), ("HIST-1", 4, 30010)]
for src, fc, reg in reqs:
    if (src, fc) not in ALLOW:
        d = "BLOCK fc-not-allowed"
    elif (src, fc) in WRITE_REGS and reg not in WRITE_REGS[(src, fc)]:
        d = "BLOCK register-out-of-range"
    else:
        d = "PASS"
    print(f"{src:7} fc={fc:2} reg={reg:5} -> {d}")

Salida esperada:

HMI-1   fc= 3 reg=40001 -> PASS
HMI-1   fc= 6 reg=40003 -> PASS
HMI-1   fc= 6 reg=40050 -> BLOCK register-out-of-range
HIST-1  fc= 3 reg=30001 -> PASS
HIST-1  fc=16 reg=40001 -> BLOCK fc-not-allowed
ENG-WS  fc= 8 reg=    0 -> BLOCK fc-not-allowed
HIST-1  fc= 4 reg=30010 -> PASS

Las pruebas se agrupan por regla para que un fallo apunte directamente a la cláusula que se rompió. La prueba de escritura del historiador, que detectó la función 16, se conserva como caso permanente. La tabla de pruebas de Lena enumera cada tupla, la decisión esperada y la cadena del motivo, y un revisor puede leerla sin ejecutar nada. Las nuevas estaciones o registros que se añaden a la lista de permitidos llegan con sus propias filas en la misma solicitud de incorporación de cambios (pull request).

4.3b Registrar lo que decidió la función

Cada decisión debe registrarse con el origen, el código de función, el registro, la decisión, el motivo y la versión del archivo de la lista de permitidos. Cuando un operador pregunta por qué se bloqueó una escritura del HMI a las 03:12, el registro responde en una línea. Sin el campo de versión, nadie puede saber si el bloqueo vino de la lista de ayer o de la de hoy.

Caso sintético — Ashford Batch Plant. La primera lista de permitidos de Lena dejaba que HIST-1 usara la función 16 (escribir múltiples registros) porque «solo lee». La tabla de pruebas lo detectó: el historiador no tiene por qué escribir, así que se eliminó la función 16 y la prueba ahora espera BLOCK.

4.4 Errores y límites

Una lista de permitidos en un monitor es tan buena como su decodificador. Las tramas mal formadas deben contarse y generar alarma, no descartarse en silencio. Los dispositivos reales de aplicación necesitan validación del proveedor antes del despliegue. El monitor de Lena cuenta las tramas mal formadas por minuto y genera una alarma si la cuenta sube, porque una ráfaga repentina puede indicar un dispositivo que falla o un error del decodificador. Tratar esas tramas como permitidas convertiría cada laguna del decodificador en una puerta abierta. El monitor de este curso solo observa; cualquier dispositivo que realmente bloquee tráfico en ABP es un producto de proveedor validado antes en el banco.

Ejercicios — capítulo 4

Síntesis del capítulo

Las funciones de permiso puras, tipadas y probadas son la unidad más pequeña y fiable del software de seguridad de TO.

Siga estudiando — capítulo 04 de 50

← Capítulo 03 (borrador) · Índice de capítulos del curso · Capítulo 05 (borrador) →