--- name: rdap_lookup kind: function lang: py domain: cybersecurity version: "1.0.0" purity: impure signature: "def rdap_lookup(target: str, timeout_s: int = 30) -> dict" description: "Lookup RDAP de un dominio, IP o ASN via el CLI `rdap` (openrdap, ~/go/bin/rdap). RDAP es el reemplazo moderno de WHOIS sobre HTTP/JSON. Resuelve el binario con shutil.which y fallback a ~/go/bin/rdap, ejecuta `rdap --json `, captura el JSON crudo en raw y lo parsea a dict. Extrae handle y ldhName. Devuelve siempre un dict {status: ok|error}; nunca lanza excepciones. OSINT pasivo: datos de registro estructurados de dominios, redes IP y autonomous systems." tags: [recon, rdap, osint-passive, cybersecurity] params: - name: target desc: "Dominio (ej. google.com), direccion IP, o ASN con prefijo AS (ej. AS15169). Vacio devuelve status error." - name: timeout_s desc: "Segundos maximo de espera del subproceso rdap (default 30)." output: "dict. En exito: {status: 'ok', target, raw (JSON crudo como string, SIEMPRE presente), data (dict parseado o None), handle (data['handle'] o None), ldhName (data['ldhName'] o None)}. Si el JSON no parsea: status 'ok' con data=None y clave 'warning'. En fallo de ejecucion (binario ausente, timeout, salida vacia): {status: 'error', error: str, target}." uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_py_core" imports: [] tested: true tests: ["test_target_vacio_devuelve_error", "test_parseo_json_sample", "test_estructura_dict_de_error"] test_file_path: "python/functions/cybersecurity/rdap_lookup_test.py" file_path: "python/functions/cybersecurity/rdap_lookup.py" --- ## Ejemplo ```python import sys, os sys.path.insert(0, os.path.join("python", "functions")) from cybersecurity import rdap_lookup info = rdap_lookup("google.com") if info["status"] == "ok": print(info["handle"]) # '2138514_DOMAIN_COM-VRSN' print(info["ldhName"]) # 'GOOGLE.COM' print(info["data"]["status"]) # ['client transfer prohibited', ...] # info["raw"] tiene el JSON RDAP completo para guardar en OSINT else: print("fallo:", info["error"]) # Tambien acepta IPs y ASNs: rdap_lookup("8.8.8.8") rdap_lookup("AS15169") ``` ## Cuando usarla Usala cuando quieras datos de registro **estructurados (JSON)** de un dominio, una IP o un ASN: handle, ldhName, eventos de registro/expiracion, entidades, nameservers, estado. RDAP es mas limpio y parseable que el texto WHOIS, asi que preferela para enriquecer entidades OSINT programaticamente. Combina con `whois_lookup_py_cybersecurity` cuando el TLD no tenga RDAP desplegado y necesites caer al WHOIS clasico (texto crudo). ## Gotchas - IMPURA: hace red via el bootstrap RDAP. Sujeta a latencia y rate-limit del servidor RDAP autoritativo; por eso hay `timeout_s` (default 30) y los fallos devuelven `{"status": "error", ...}` sin lanzar. - **RDAP no cubre todos los TLDs**: muchos ccTLDs y algunos gTLDs aun no lo tienen desplegado. En esos casos `rdap` falla y conviene caer a `whois_lookup_py_cybersecurity`. - El binario `rdap` (openrdap) suele NO estar en el PATH de un subproceso: se resuelve con `shutil.which("rdap")` y fallback a `~/go/bin/rdap`. Si no se encuentra, devuelve status error con instruccion de instalacion (`go install github.com/openrdap/rdap/cmd/rdap@latest`). - El flag es `--json` (equivalente corto `-j`). Se usa `--json`. - Si la salida no es JSON parseable (error textual del CLI capturado como stdout), devuelve `status: ok` con `data=None`, `handle=None`, `ldhName=None` y una clave `warning`; el JSON/texto crudo siempre esta en `raw`. - El registrante personal suele estar redactado por privacy/GDPR en las entidades RDAP. ## Capability growth log - v1.0.0 (2026-06-14) — version inicial. Wrapper del CLI openrdap `rdap`, acepta dominios/IPs/ASNs, estilo dict `{status: ok|error}` sin excepciones.