621e8895c9
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
3.2 KiB
Markdown
67 lines
3.2 KiB
Markdown
---
|
|
name: wg_peer_revoke
|
|
kind: function
|
|
lang: go
|
|
domain: infra
|
|
version: "1.0.0"
|
|
purity: impure
|
|
signature: "func WGPeerRevoke(deviceID, operator, reason string, configPath, auditDBPath string) (WGPeerRevokeAudit, error)"
|
|
description: "Kill switch: revoca peer permanentemente. Anade a blacklist + audit log hash-chained inviolable (SHA256 chain). Para dispositivos perdidos/comprometidos."
|
|
tags: [wireguard, hub, revoke, kill-switch, audit, security]
|
|
uses_functions:
|
|
- wg_peer_remove_go_infra
|
|
uses_types: []
|
|
returns: []
|
|
returns_optional: false
|
|
error_type: "error_go_core"
|
|
imports: []
|
|
params:
|
|
- name: deviceID
|
|
desc: "Identificador unico del dispositivo a revocar. Debe coincidir con '# DeviceID:<id>' en wg0.conf."
|
|
- name: operator
|
|
desc: "Nombre del operador que ejecuta la revocacion. Se guarda en audit log. No puede ser vacio."
|
|
- name: reason
|
|
desc: "Motivo de la revocacion (ej. 'dispositivo perdido', 'comprometido'). No puede ser vacio. No incluir PII."
|
|
- name: configPath
|
|
desc: "Ruta absoluta al wg0.conf del hub. El peer se elimina del config activo via syncconf."
|
|
- name: auditDBPath
|
|
desc: "Ruta al SQLite de audit. Se crea con schema si no existe. Contiene la cadena de hashes inviolable."
|
|
output: "WGPeerRevokeAudit con DeviceID, PublicKey, RevokedAt (unix), RevokedBy, Reason, PrevHash y ThisHash. ThisHash = SHA256(PrevHash|DeviceID|PublicKey|RevokedAt|Operator|Reason)."
|
|
tested: true
|
|
tests:
|
|
- "audit DB contiene registro con this_hash != prev_hash"
|
|
- "segunda revoke del mismo peer → error already revoked"
|
|
test_file_path: "functions/infra/wg_peer_revoke_test.go"
|
|
file_path: "functions/infra/wg_peer_revoke.go"
|
|
---
|
|
|
|
## Ejemplo
|
|
|
|
```go
|
|
audit, err := infra.WGPeerRevoke(
|
|
"device-laptop-alice",
|
|
"operator-bob",
|
|
"dispositivo perdido en viaje",
|
|
"/etc/wireguard/wg0.conf",
|
|
"/var/lib/wg-hub/revoked.db",
|
|
)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Printf("revoked: device=%s pubkey=%s hash=%s\n",
|
|
audit.DeviceID, audit.PublicKey, audit.ThisHash)
|
|
```
|
|
|
|
## Cuando usarla
|
|
|
|
Cuando un dispositivo esta perdido, robado o comprometido y NO debe poder volver a conectarse nunca. Deja registro inmutable en audit DB con hash chain SHA256 y escribe la PublicKey en `/etc/wireguard/wg_revoked.list`. Para baja temporal (rotar claves, reconfigurar) usa `wg_peer_remove_go_infra`.
|
|
|
|
## Gotchas
|
|
|
|
- **Reason obligatorio**: reason vacio devuelve error antes de tocar nada.
|
|
- **Idempotencia**: revocar el mismo deviceID dos veces devuelve `already revoked`. La comprobacion es sobre la audit DB, no sobre el config.
|
|
- **Audit DB borrada**: si auditDBPath se borra, la chain se reinicia desde genesis (prev_hash vacio). El break de integridad es visible (primer registro sin prev_hash). El sistema lo acepta pero queda evidencia del gap.
|
|
- **Blacklist `/etc/wireguard/wg_revoked.list`**: requiere permisos de escritura en `/etc/wireguard/`. Si falla, el audit DB ya tiene el registro (no se revierte) pero la funcion devuelve error indicando el gap.
|
|
- **Reason no debe contener PII**: se guarda en texto plano en SQLite y en la blacklist. Usar referencias internas en vez de nombres reales.
|
|
- **syncconf**: hereda el requisito de privilegios de WGPeerRemove. Ver gotchas de `wg_peer_remove_go_infra`.
|