Conexión SSL autofirmada utilizando PyMongo

Estoy tratando de crear una conexión SSL segura a MongoDB usando PyMongo. El objective es usar esta configuración para una instancia de Mongo que se ejecuta en EC2 a la que puedo conectarme con un cliente de Python. Para las pruebas, solo estoy intentando que la configuración funcione localmente primero. Mi bash fallido todavía se puede encontrar aquí .

Versión corta de lo que creo que es el problema: mi archivo de autoridad de certificado del lado del cliente ca.pem no es correcto. La forma en que lo tengo, este archivo es en realidad idéntico al que estoy usando en el lado del servidor. Ambos se crearon utilizando x509 con openssl , y sospecho que el archivo del lado de mi cliente necesita algún tipo de contenido diferente, pero no estoy seguro de cómo generar ese contenido o si esta sospecha es correcta.

Aquí están los detalles de lo que he hecho para crear los certificados y las claves necesarias (en Mac El Capitan):

Primero, genere una autoridad de certificación:

 $ mkdir ~/ssl $ cd ~/ssl $ openssl req -out ca.pem -new -x509 -days 3650 # enter info 

Generar el archivo .pem servidor:

     $ openssl genrsa -out server.key 2048 $ openssl req -key server.key -new -out server.req # enter info $ openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.crt -days 3650 $ cat server.key server.crt > server.pem 

    Ahora haz lo mismo para el cliente:

     $ openssl genrsa -out client.key 2048 $ openssl req -key client.key -new -out client.req $ openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.crt -days 3650 $ cat client.key client.crt > client.pem 

    Luego hago las siguientes configuraciones en etc/mongod.conf :

     net: ... ssl: mode: requireSSL PEMKeyFile: ~/ssl/server.pem CAFile: ~/ssl/ca.pem 

    Ahora comenzando mongo (Mac) con

     $ mongod --config /etc/mongod.conf 

    Funciona como se espera. El proceso se ejecuta y parece estar aceptando las configuraciones.

    Luego, en el lado de Python (que también se ejecuta en localhost para la depuración), hago lo siguiente al llamar a mongo:

     import ssl from pymongo import MongoClient client = MongoClient( '127.0.0.1', 27017, ssl=True, ssl_certfile='~/ssl/client.pem', ssl_cert_reqs=ssl.CERT_REQUIRED, ssl_ca_certs='~/ssl/ca.pem' ) # try a simple insert 

    Cuando ejecuto esto, el código de Python se bloquea después de crear MongoClient , y veo en los registros de mongo :

     2016-03-03T22:11:30.331-0800 E NETWORK [conn21] SSL: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca 

    Sobre la base del comentario de Wan que se encuentra a continuación, lo hice todo de nuevo, asegurándome de que la información en el ‘Nombre distinguido’ fuera coherente con esas especificaciones. La versión anterior definitivamente usó el mismo nombre común para el servidor y el cliente. La conexión aún no tiene éxito, pero los mensajes son algo diferentes:

     2016-03-11T12:29:40.380-0800 I NETWORK [initandlisten] connection accepted from 127.0.0.1:57363 #3 (1 connection now open) 2016-03-11T12:29:40.386-0800 I NETWORK [conn3] end connection 127.0.0.1:57363 (0 connections now open) 

    Estos 2 mensajes solo se repiten hasta que detenga el proceso de Python, que se bloquea al intentar abrir la conexión. La parte de la end connection ahora se encuentra en el lugar donde la línea de alert unknown ca estaba anteriormente en el registro de Mongo.

    Información adicional para la depuración:

     $ openssl verify -CAfile ca.pem client.pem client.pem: OK $ openssl verify -CAfile ca.pem server.pem server.pem: OK $ openssl x509 -noout -subject -in server.pem subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=server.com/emailAddress=@gmail.com $ openssl x509 -noout -subject -in client.pem subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=client.com/emailAddress=@gmail.com 

    La línea de fondo después de que la línea de asunto se formó correctamente es que mongo está aceptando la conexión, luego la finaliza, y el proceso de Python se bloquea sin tener que realizar la inserción deseada.

    ¡Cualquier ayuda es muy apreciada!

    Hay otras formas de generar un servidor / cliente pem con una Autoridad de Certificación, es decir, sin involucrar file.srl , pero esta respuesta es para hacer un seguimiento de la pregunta.

    Vale la pena mencionar que la mayoría de las distribuciones de MongoDB v3.0 + ahora incluyen soporte para SSL, asegúrese de elegir un paquete que sea compatible con SSL. El siguiente ejemplo se prueba con MongoDB v3.2 en Ubuntu Linux 14.04 con PyMongo v3.2.1 . Donde una sola máquina generó los archivos pem de CA, servidor y cliente para fines de demostración.

    Vamos a generar ca.pem y privkey.pem . La estructura del sujeto es /C=/ST=/L=/O=/emailAddress=/CN= .

     mkdir ~/ssl cd ~/ssl openssl req -out ca.pem -new -x509 -days 3650 -subj "/C=AU/ST=NSW/O=Organisation/CN=root/emailAddress=user@domain.com" 

    Generar el archivo server .pem :

     hostname # note down the value echo "00" > file.srl # two random digits number openssl genrsa -out server.key 2048 openssl req -key server.key -new -out server.req -subj "/C=AU/ST=NSW/O=Organisation/CN=server1/CN=/emailAddress=user@domain.com" openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.crt -days 3650 cat server.key server.crt > server.pem openssl verify -CAfile ca.pem server.pem 

    Aunque también puede utilizar la dirección IP como valor CN , no se recomienda. Ver RFC-6125 .

    Ahora vamos a generar el archivo client.pem :

     openssl genrsa -out client.key 2048 openssl req -key client.key -new -out client.req -subj "/C=AU/ST=NSW/O=Organisation/CN=client1/emailAddress=user@domain.com" openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.crt -days 3650 cat client.key client.crt > client.pem openssl verify -CAfile ca.pem client.pem 

    Después de generar los archivos .pem , ahora puede ejecutar mongod . por ejemplo:

     mongod --sslMode requireSSL --sslPEMKeyFile ~/server.pem --sslCAFile ~/ca.pem 

    Puedes probar la conexión usando el shell mongo , por ejemplo:

     mongo --ssl --sslPEMKeyFile ~/client.pem --sslCAFile ~/ca.pem --host  

    Una vez que puedas conectarte con éxito, puedes probar con PyMongo. Por ejemplo:

     import ssl from pymongo import MongoClient client = MongoClient( '', 27017, ssl=True, ssl_certfile='~/client.pem', ssl_cert_reqs=ssl.CERT_REQUIRED, ssl_ca_certs='~/ca.pem' ) 

    Alternativamente, también puede usar el indicador mongod –sslAllowInvalidHostnames para especificar localhost , etc.

    Para uso de producción, su implementación de MongoDB debe usar certificados válidos generados y firmados por una única autoridad de certificación. Si utiliza un certificado autofirmado, aunque el canal de comunicaciones estará cifrado, no habrá validación de la identidad del servidor. El uso de un certificado firmado por una autoridad de certificación de confianza permitirá a los controladores MongoDB verificar la identidad del servidor. En general, evite utilizar certificados autofirmados a menos que la red sea de confianza.

    Otros enlaces relacionados que pueden ser útiles:

    • MongoDB: Configurar SSL .
    • MongoDB: Tutoriales de seguridad .
    • Lista de verificación de seguridad de MongoDB .