services/api/src/scripts/lib/localMongoTarget.js
Overview
Este archivo define una guardia pura para los scripts administrativos de reconciliación D-09. Su propósito es validar un destino MongoDB antes de operar sobre él, y confirmar después de conectar que el servidor reportado sigue siendo local y no es un mongos. El propio archivo aclara que nunca conecta ni devuelve la URI; solo evalúa el destino y genera una huella estable sin credenciales.
Se usa como pieza compartida por los scripts de inventario y recuperación. Esos scripts llaman a assertLocalMongoTarget antes de conectar y a assertConnectedServerIsLocal después de hello, como parte de su verificación operativa del destino.
[!NOTE] El archivo documenta una limitación explícita: demostrar que la conexión es local y directa no demuestra que la base sea de pruebas. Un túnel local hacia otra base puede parecer indistinguible.
How it works
flowchart TD
URI[Mongo URI] --> LOCAL[assertLocalMongoTarget]
LOCAL --> SEED[evaluateSeedTarget]
LOCAL --> QUERY[uriOptionNames]
LOCAL --> DBCHK[allowedDb check]
LOCAL --> RESULT1[allowed and reasons]
HELLO[hello response] --> SERVER[assertConnectedServerIsLocal]
SERVER --> HOST[hostOnly]
SERVER --> MONGOS[reject mongos]
SERVER --> LOCALMEM[loopback member check]
SERVER --> RESULT2[allowed and reasons]
URI --> FP[targetFingerprint]
FP --> DESC[describeMongoTarget]
FP --> CANON[canonical string]
CANON --> HASH[sha256]
La ruta principal tiene tres pasos. Primero, assertLocalMongoTarget delega la evaluación base en evaluateSeedTarget desde seedTargetGuard.js, inspecciona opciones de URI, y compara la base detectada con allowedDb. Después, assertConnectedServerIsLocal revisa el documento hello y confirma que ningún miembro reportado salga de loopback, además de rechazar mongos. Por último, targetFingerprint calcula una huella reproducible a partir de esquema, hosts y base, sin incluir credenciales.
Key components
Estas funciones forman el núcleo del archivo y están pensadas para ser consumidas por otros scripts del backend. Las tres son exportadas y se usan como utilidades de validación o de derivación de huella.
{
"title": "assertLocalMongoTarget",
"content": "Eval\u00faa una URI de MongoDB contra la guardia local y devuelve allowed, reasons y database. Usa evaluateSeedTarget, bloquea opciones de URI inseguras y exige una base autorizada.",
"type": "function",
"filePath": "services/api/src/scripts/lib/localMongoTarget.js",
"badges": [
"public"
]
}
{
"title": "assertConnectedServerIsLocal",
"content": "Inspecciona la respuesta hello despu\u00e9s de conectar y rechaza miembros remotos o un mongos. Devuelve allowed y reasons.",
"type": "function",
"filePath": "services/api/src/scripts/lib/localMongoTarget.js",
"badges": [
"public"
]
}
{
"title": "targetFingerprint",
"content": "Calcula una huella SHA-256 estable del destino MongoDB usando esquema, hosts ordenados y base. No incluye credenciales.",
"type": "function",
"filePath": "services/api/src/scripts/lib/localMongoTarget.js",
"badges": [
"public"
]
}
Estas helpers no se exportan, pero explican parte del comportamiento del módulo.
uriOptionNamesextrae los nombres de las opciones de query de la URI.hostOnlynormaliza una dirección para comparar solo el host.ALLOWED_URI_OPTIONSdefine las únicas opciones de query aceptadas por esta guardia.LOOPBACKdefine los hosts locales válidos para la comprobación post-conexión.
Data & fields
El archivo no define clases ni modelos de datos complejos. Su información principal son constantes read-only y la forma de los objetos que devuelven sus funciones.
Constantes internas
ALLOWED_URI_OPTIONS[badge:read-only]Set<string>— Solo aceptaauthsourceyauthmechanism.LOOPBACK[badge:read-only]Set<string>— Solo aceptalocalhost,127.0.0.1y::1.
Resultado de assertLocalMongoTarget
[
{
"name": "allowed",
"type": "boolean",
"required": true,
"description": "Indica si la URI cumple todas las reglas aplicadas por la guardia."
},
{
"name": "reasons",
"type": "string[]",
"required": true,
"description": "Lista de motivos de rechazo. Cada motivo usa un código corto."
},
{
"name": "database",
"type": "string",
"required": true,
"description": "Base de datos detectada en la URI o cadena vacía si no pudo determinarse."
}
]
Parámetros de assertLocalMongoTarget
[
{
"name": "uri",
"type": "string",
"required": true,
"description": "URI de MongoDB que se quiere validar."
},
{
"name": "options",
"type": "object",
"description": "Opciones adicionales para la validación del destino.",
"children": [
{
"name": "allowedDb",
"type": "string",
"description": "Nombre de base autorizado. Debe coincidir con la base detectada."
},
{
"name": "env",
"type": "object",
"description": "Entorno que se pasa a evaluateSeedTarget.",
"children": [
{
"name": "NODE_ENV",
"type": "string",
"description": "Se reenvía a evaluateSeedTarget como nodeEnv."
},
{
"name": "APP_ENV",
"type": "string",
"description": "Se reenvía a evaluateSeedTarget como appEnv."
}
]
}
]
}
]
Resultado de assertConnectedServerIsLocal
allowed[badge:required]boolean—truesolo cuando no hay razones de rechazo.reasons[badge:required]string[]— Motivos de rechazo, comoMONGOS_NOT_ALLOWEDoREMOTE_MEMBER_REPORTED.
Parámetros de assertConnectedServerIsLocal
[
{
"name": "hello",
"type": "object",
"description": "Documento hello devuelto por MongoDB.",
"children": [
{
"name": "msg",
"type": "string",
"description": "Si vale isdbgrid, el destino se rechaza."
},
{
"name": "me",
"type": "string",
"description": "Dirección del miembro local que reporta el servidor."
},
{
"name": "primary",
"type": "string",
"description": "Dirección del primario que reporta el servidor."
},
{
"name": "hosts",
"type": "string[]",
"description": "Miembros del replica set que reporta el servidor."
},
{
"name": "passives",
"type": "string[]",
"description": "Miembros pasivos que reporta el servidor."
},
{
"name": "arbiters",
"type": "string[]",
"description": "Miembros árbitro que reporta el servidor."
}
]
}
]
Behaviors
Las funciones exportadas cubren tres responsabilidades distintas: validación previa, verificación post-conexión y derivación de identidad estable del destino. Los motivos de rechazo se expresan como códigos cortos, y assertLocalMongoTarget los normaliza quitando cualquier sufijo posterior a : que venga de evaluateSeedTarget.
assertLocalMongoTarget[badge:public] — Valida la URI y devuelve si el destino está permitido, junto con los motivos y la base detectada.assertConnectedServerIsLocal[badge:public] — Comprueba elhellodevuelto por MongoDB y rechaza miembros remotos omongos.targetFingerprint[badge:public] — Genera una huella SHA-256 del destino sin credenciales.uriOptionNames— Extrae los nombres de las opciones de query de la URI, los normaliza a minúsculas y descarta vacíos.hostOnly— Normaliza direcciones IPv4, IPv6 entre corchetes y valores con puerto.
assertLocalMongoTarget
La función toma una URI y un objeto de opciones. Luego llama a evaluateSeedTarget con uri, NODE_ENV y APP_ENV. Después, revisa las opciones de query y solo admite authSource y authMechanism; cualquier otra opción suma UNSAFE_URI_OPTION. También exige allowedDb; si falta, devuelve ALLOWED_DB_MISSING. Si la base detectada no coincide con allowedDb, devuelve DATABASE_NOT_AUTHORIZED.
assertConnectedServerIsLocal
La función inspecciona la respuesta hello. Si hello.msg === "isdbgrid", agrega MONGOS_NOT_ALLOWED. Luego reúne hello.me, hello.primary, hello.hosts, hello.passives y hello.arbiters, y verifica que cada dirección sea loopback después de normalizarla con hostOnly. Si encuentra alguna dirección remota, agrega REMOTE_MEMBER_REPORTED.
targetFingerprint
La función llama a describeMongoTarget(uri) desde seedTargetGuard.js. Si el destino no puede describirse, devuelve null. Si sí puede, construye una cadena canónica con scheme, los hosts ordenados y la base, y la firma con sha256. El resultado es una huella estable que no expone usuario, contraseña ni parámetros de query.
hostOnly trata dos formatos de forma explícita:
- Direcciones IPv6 entre corchetes, como
[::1]:27017. - Direcciones con puerto único, como
localhost:27017.
La función deja el host listo para compararlo con LOOPBACK. Esto permite validar de forma uniforme la respuesta hello de MongoDB.
Gotchas & edge cases
[!WARNING] Esta guardia no demuestra que la base sea de pruebas. El propio archivo advierte que una conexión local puede apuntar a otra base mediante un túnel local indistinguible.
[!WARNING]
assertLocalMongoTargetsolo aceptaauthSourceyauthMechanismen la query de la URI. Cualquier otra opción suma un rechazoUNSAFE_URI_OPTION.
[!CAUTION]
assertConnectedServerIsLocalsolo analiza el documentohello. No valida contenido de la base ni estado de los datos, solo el origen y la topología reportada.
[!NOTE]
targetFingerprintno incluye credenciales. Dos URIs diferentes pueden producir la misma huella si comparten esquema, hosts y base.
[!IMPORTANT] Este módulo forma parte del flujo operativo de los scripts de inventario y recuperación. Esos scripts lo usan antes y después de conectar, y además fijan
directConnectionen su propia conexión.
Related
Este archivo está ligado a services/api/src/scripts/lib/seedTargetGuard.js, porque reutiliza evaluateSeedTarget y describeMongoTarget para interpretar y describir la URI de destino.
También se conecta con services/api/src/scripts/inventoryDeletionState.js y services/api/src/scripts/resumePendingRequirementDeletions.js, que lo importan para validar el destino antes de operar sobre MongoDB. Esos scripts primero rechazan destinos no autorizados y luego repiten la comprobación con hello tras conectar.
En el contexto del repositorio, el módulo aparece como parte de las utilidades de reconciliación y mantenimiento documentadas en los scripts de inventario y recuperación, no como una API HTTP ni como una capa de negocio general.