I'm trying to create a secure SSL connection to MongoDB using PyMongo. The goal is to use this configuration for a Mongo instance running on EC2 to which I can connect with a Python client. For testing, I'm just trying to get the configuration working locally first. My as yet failing attempt can be found here.
我正在尝试使用PyMongo创建一个到MongoDB的安全SSL连接。目标是将此配置用于在EC2上运行的Mongo实例,我可以将其与Python客户端连接。为了测试,我只是想让配置首先在本地工作。我的失败尝试可以在这里找到。
Short version of what I think is the problem: My client side certificate authority file ca.pem
isn't correct. The way I have it, this file is actually identical to the one I'm using server side. Both were created using x509
with openssl
, and I suspect that my client side file needs some kind of different content, but I'm not sure exactly how to generate that content or if this suspicion is even correct.
我认为是问题的简短版本:我的客户端证书颁发机构文件ca.pem不正确。我拥有它的方式,这个文件实际上与我使用服务器端的文件相同。两者都是使用带有openssl的x509创建的,我怀疑我的客户端文件需要某种不同的内容,但我不确定如何生成该内容或者这种怀疑是否正确。
Here are the details of what I've done for creating the necessary certificates and keys (on Mac El Capitan):
以下是我为创建必要的证书和密钥所做的详细信息(在Mac El Capitan上):
First, generate a certificate authority:
首先,生成证书颁发机构:
$ mkdir ~/ssl
$ cd ~/ssl
$ openssl req -out ca.pem -new -x509 -days 3650
# enter info
Generate server .pem
file:
生成服务器.pem文件:
$ 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
Now do the same for the client:
现在为客户做同样的事情:
$ 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
Then I do the following configurations in etc/mongod.conf
:
然后我在etc / mongod.conf中进行以下配置:
net:
...
ssl:
mode: requireSSL
PEMKeyFile: ~/ssl/server.pem
CAFile: ~/ssl/ca.pem
Now starting mongo (Mac) with
现在用mongo(Mac)启动
$ mongod --config /etc/mongod.conf
works as expected. The process runs and seems to be accepting the configurations.
按预期工作。该过程运行并且似乎接受配置。
Then on the Python side (also running on localhost for debugging), I do the following in calling mongo:
然后在Python端(也在localhost上运行以进行调试),我在调用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
When I run this, the Python code blocks after creating the MongoClient
, and I see in the mongo
logs:
当我运行它时,Python代码在创建MongoClient后阻塞,我在mongo日志中看到:
2016-03-03T22:11:30.331-0800 E NETWORK [conn21] SSL: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
On the basis of Wan's comment below, I redid the whole thing, making sure that the information in the 'Distinguished Name' was consistent with those specifications. The old version definitely used the same Common Name for both server and client. The connection still isn't succeeding, but the messages are somewhat different:
根据Wan在下面的评论,我重新整理了所有内容,确保“专有名称”中的信息与这些规范一致。旧版本肯定对服务器和客户端使用相同的公用名。连接仍然没有成功,但消息有些不同:
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)
These 2 messages just repeat until I stop the Python process, which blocks when attempting to open the connection. The end connection
part is now in the place where the alert unknown ca
line was previously in the mongo log.
这两条消息只是重复,直到我停止Python进程,在尝试打开连接时阻塞。终端连接部分现在位于mongo日志中之前警报未知ca行的位置。
Additional info for debugging:
其他调试信息:
$ 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
The bottom line after getting the subject line properly formed is that mongo is accepting the connection, then ending it, and the Python process is blocking without ever making the intended insert.
在正确形成主题行之后的底线是mongo正在接受连接,然后结束它,并且Python进程阻塞而没有进行预期的插入。
Any help is much appreciated!
任何帮助深表感谢!
12
There are other ways of generating server/client pem with a Certificate Authority i.e. without involving file.srl
, but this answer is to follow up on the question.
还有其他方法可以使用证书颁发机构生成服务器/客户端pem,即不涉及file.srl,但这个答案是跟进问题。
Worth mentioning that most MongoDB v3.0+ distributions now include support for SSL, please be sure to choose a package that supports SSL. The example below is tested with MongoDB v3.2 on Ubuntu Linux 14.04 with PyMongo v3.2.1. Where a single machine generated the CA, server and client pem files for demonstration purposes.
值得一提的是,大多数MongoDB v3.0 +发行版现在都支持SSL,请务必选择支持SSL的软件包。下面的示例是在带有PyMongo v3.2.1的Ubuntu Linux 14.04上使用MongoDB v3.2进行测试的。单个计算机生成CA,服务器和客户端pem文件以用于演示目的。
Let's generate ca.pem
and privkey.pem
. The subject structure is /C=
.
让我们生成ca.pem和privkey.pem。主题结构是/ C = <国家名称> / ST = <状态> / L = <位置名称> / O = <组织名称> / emailAddress =
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"
Generate server .pem
file:
生成服务器.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
Although you can use IP address as CN
value as well, it is not recommended. See RFC-6125.
虽然您也可以使用IP地址作为CN值,但不建议这样做。请参阅RFC-6125。
Now let's generate client.pem
file:
现在让我们生成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
After generating the .pem
files, now you can run mongod. for example:
生成.pem文件后,现在可以运行mongod。例如:
mongod --sslMode requireSSL --sslPEMKeyFile ~/server.pem --sslCAFile ~/ca.pem
You can test the connection using the mongo shell, for example:
您可以使用mongo shell测试连接,例如:
mongo --ssl --sslPEMKeyFile ~/client.pem --sslCAFile ~/ca.pem --host
Once you can get connected successfully, you can try with PyMongo. For example:
成功连接后,您可以尝试使用PyMongo。例如:
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'
)
Alternatively, you can also use mongod
flag --sslAllowInvalidHostnames to specify localhost
, etc.
或者,您也可以使用mongod标志--sslAllowInvalidHostnames来指定localhost等。
For production use, your MongoDB deployment should use valid certificates generated and signed by a single certificate authority. If you use a self-signed certificate, although the communications channel will be encrypted, there will be no validation of server identity. Using a certificate signed by a trusted certificate authority will permit MongoDB drivers to verify the server’s identity. In general, avoid using self-signed certificates unless the network is trusted.
对于生产用途,MongoDB部署应使用由单个证书颁发机构生成和签名的有效证书。如果使用自签名证书,虽然通信通道将被加密,但不会验证服务器标识。使用由受信任的证书颁发机构签名的证书将允许MongoDB驱动程序验证服务器的标识。通常,除非网络受信任,否则请避免使用自签名证书。
Other related links that you may find useful:
您可能会发现有用的其他相关链接:
MongoDB:配置SSL。
MongoDB:安全教程。
MongoDB安全检查表。