Problema
Muchos desarrolladores intentan ejecutar scripts Python que consultan o actualizan un clúster de AWS Neptune directamente desde su laptop o estación de trabajo. El síntoma típico es un timeout al usar curl o al iniciar la biblioteca Gremlin en Python. La causa subyacente suele ser que el tráfico no sale de la red local hacia el endpoint privado del clúster, que por defecto sólo es accesible dentro de la VPC donde está desplegado. El problema se repite en diferentes entornos: VPC sin ruta a Internet, reglas de Security Group demasiado restrictivas, o falta de un túnel que lleve el tráfico a la red privada de AWS.
Causa
-
Endpoint privado – Un clúster de Neptune se crea con un DNS interno (por ejemplo
mycluster.cluster-xxxxxxxxxxxx.us-east-1.neptune.amazonaws.com). Ese nombre solo se resuelve dentro de la VPC; desde Internet la resolución falla o devuelve una IP inaccesible. -
Security Group sin permiso de origen – El SG asociado al clúster necesita una regla de entrada que permita el puerto 8182 desde la IP pública del desarrollador (o desde el rango de la subred que usará el túnel). Si la regla permite “0.0.0.0/0” pero la VPC no tiene salida a Internet, sigue sin funcionar.
-
Ruta de red inexistente – La subred del clúster debe tener una ruta a un Internet Gateway (para acceso público) o a un NAT Gateway (para tráfico saliente). Sin ella, cualquier intento de conexión desde fuera de la VPC es descartado antes de llegar al SG.
-
Falta de punto de salto – Cuando el clúster está en una subred privada, la práctica recomendada es usar una instancia EC2 (bastión) en una subred pública y crear un túnel SSH que reenvíe el puerto 8182 hacia el endpoint de Neptune.
-
Política IAM insuficiente – Aunque la mayoría de los accesos a Neptune se hacen a nivel de red, algunas operaciones (por ejemplo, usar el Neptune Data API) requieren permisos IAM específicos. La ausencia de esas políticas puede generar errores de autorización después de que la red ya esté funcionando.
Solución
1. Verificar la arquitectura de red
- Subred pública vs privada: Si el clúster está en una subred privada, crea una instancia EC2 en una subred pública (con Elastic IP) que actuará como bastión.
- Internet/NAT Gateway: Asegúrate de que la tabla de rutas de la subred del clúster incluya una ruta
0.0.0.0/0hacia un IGW (para acceso público) o un NAT (para salidas controladas). En entornos de desarrollo, habilitar IGW suele ser suficiente.
2. Configurar el Security Group del clúster
- Añade una regla de entrada:
- Protocolo: TCP
- Puerto: 8182
- Origen: tu IP pública (obtenida en
https://ifconfig.me) o el rango de la subred donde está la instancia bastión.
- Si usas un bastión, la regla solo necesita permitir el tráfico desde la IP privada de esa instancia.
3. Lanzar una instancia bastión (si es necesario)
- Selecciona una AMI Amazon Linux 2.
- Asigna una Elastic IP para que sea accesible desde tu máquina.
- Asocia el mismo SG que usará para el túnel (puede ser el SG predeterminado o uno nuevo con SSH abierto al mundo o a tu IP).
4. Crear el túnel SSH
Desde tu laptop, abre un túnel que reenvíe el puerto local 8182 al endpoint de Neptune a través del bastión:
ssh -i ~/.ssh/my-key.pem -L 8182:mycluster.cluster-xxxxxxxxxxxx.us-east-1.neptune.amazonaws.com:8182 ec2-user@<BASTION_PUBLIC_IP>
Mantén la sesión abierta; el túnel permanecerá activo mientras la ventana de terminal esté viva.
5. Probar la conectividad con curl
Con el túnel activo, ejecuta:
curl -v http://localhost:8182/status
Deberías obtener un JSON con el estado del clúster ("status":"healthy"). Si sigue el timeout, revisa los logs de la instancia bastión y confirma que la regla SG permite el tráfico desde la IP del bastión al clúster.
6. Configurar el cliente Python
Instala la librería Gremlin‑Python:
pip install gremlinpython
Ejemplo mínimo:
from gremlin_python.driver import client, serializer
neptune_endpoint = "ws://localhost:8182/gremlin"
c = client.Client(neptune_endpoint, 'g',
username="/db/graph", # opcional si usas IAM auth
password="", # vacío si no usas auth
message_serializer=serializer.GraphSONSerializersV2d0())
callback = c.submitAsync("g.V().limit(1)")
if callback.result():
print(callback.result().all().result())
c.close()
El script se conecta al puerto local 8182, que está reenviado al clúster real mediante el túnel.
7. Alternativa sin bastión (solo para pruebas rápidas)
Si decides exponer el clúster públicamente (no recomendado en producción), modifica el SG para aceptar tráfico 8182 desde 0.0.0.0/0 y habilita un Publicly Accessible al crear el clúster. Luego puedes usar curl directamente contra el DNS del clúster sin túnel. Esta opción solo se usa en entornos aislados y temporales.
Cuándo aplicar esta solución
- Desarrollo local: Necesitas ejecutar pruebas unitarias o scripts de carga desde tu IDE.
- Clúster en subred privada: La arquitectura de producción mantiene Neptune sin IP pública.
- Política de seguridad estricta: No puedes abrir el puerto 8182 a Internet, pero sí a una instancia controlada.
- No aplicar: Cuando el clúster ya está configurado con un endpoint público y el SG permite tu IP; en ese caso el túnel es innecesario y basta con conectar directamente.
Código
# 1. Obtener IP pública local
MY_IP=$(curl -s https://ifconfig.me)
# 2. Añadir regla SG al clúster (reemplaza SG_ID y CLUSTER_ENDPOINT)
aws ec2 authorize-security-group-ingress \
--group-id sg-0123456789abcdef0 \
--protocol tcp --port 8182 \
--cidr ${MY_IP}/32
# 3. Lanzar bastión (ejemplo simplificado)
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name my-key \
--subnet-id subnet-0abcde1234567890f \
--associate-public-ip-address \
--security-group-ids sg-0fedcba9876543210
# 4. Crear túnel SSH (reemplaza BASTION_IP y KEY_PATH)
ssh -i KEY_PATH -L 8182:mycluster.cluster-xxxxxxxxxxxx.us-east-1.neptune.amazonaws.com:8182 ec2-user@BASTION_IP
# 5. Probar con curl
curl -v http://localhost:8182/status
Verificación
- Respuesta de curl: Debe devolver un JSON con
"status":"healthy"y sin tiempo de espera. - Salida del cliente Python: El script debe imprimir un objeto de vértice o una lista vacía, indicando que la conexión Gremlin está operativa.
- Logs de la instancia bastión: En
/var/log/auth.logo/var/log/secureno deben aparecer rechazos de conexión al puerto 8182. - CloudWatch: Verifica que el clúster no muestra errores de “Connection refused” en los logs de métricas.
Notas adicionales
- IAM auth: Si tu clúster tiene IAM authentication habilitado, genera una firma SigV4 y pásala como encabezado
Authorization. La libreríaboto3puede ayudar a crear la firma. - TLS: Neptune requiere TLS 1.2. Si usas
curl, añade--tlsv1.2y--cacertcon el certificado de Amazon si tu entorno lo requiere. - Persistir el túnel: Usa
autosshpara que el túnel se restablezca automáticamente en caso de caída. - **Ev