Mar*_*ier 10 python ssl mongodb x509 pymongo
我正在尝试使用PyMongo创建一个到MongoDB的安全SSL连接.目标是将此配置用于在EC2上运行的Mongo实例,我可以将其与Python客户端连接.为了测试,我只是想让配置首先在本地工作.我的失败尝试可以在这里找到.
我认为是问题的简短版本:我的客户端证书颁发机构文件ca.pem不正确.我拥有它的方式,这个文件实际上与我使用服务器端的文件相同.两者都是使用x509with 创建的openssl,我怀疑我的客户端文件需要某种不同的内容,但我不确定如何生成该内容或者这种怀疑是否正确.
以下是我为创建必要的证书和密钥所做的详细信息(在Mac El Capitan上):
首先,生成证书颁发机构:
$ mkdir ~/ssl
$ cd ~/ssl
$ openssl req -out ca.pem -new -x509 -days 3650
# enter info
Run Code Online (Sandbox Code Playgroud)
生成服务器.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
Run Code Online (Sandbox Code Playgroud)
现在为客户做同样的事情:
$ 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
Run Code Online (Sandbox Code Playgroud)
然后我在以下配置中进行etc/mongod.conf:
net:
...
ssl:
mode: requireSSL
PEMKeyFile: ~/ssl/server.pem
CAFile: ~/ssl/ca.pem
Run Code Online (Sandbox Code Playgroud)
现在用mongo(Mac)启动
$ mongod --config /etc/mongod.conf
Run Code Online (Sandbox Code Playgroud)
按预期工作.该过程运行并且似乎接受配置.
然后在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
Run Code Online (Sandbox Code Playgroud)
当我运行它时,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
Run Code Online (Sandbox Code Playgroud)
根据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)
Run Code Online (Sandbox Code Playgroud)
这两条消息只是重复,直到我停止Python进程,在尝试打开连接时阻塞.该end connection部件现在位于alert unknown ca以前在mongo日志中的行.
调试的其他信息:
$ 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=<my-email-address>@gmail.com
$ openssl x509 -noout -subject -in client.pem
subject= /C=US/ST=Washington/L=Seattle/O=codeMelon/OU=Engineering/CN=client.com/emailAddress=<my-email-address>@gmail.com
Run Code Online (Sandbox Code Playgroud)
在正确形成主题行之后的底线是mongo正在接受连接,然后结束它,并且Python进程阻塞而没有进行预期的插入.
任何帮助深表感谢!
Wan*_*iar 19
还有其他方法可以使用证书颁发机构生成服务器/客户端pem,即不涉及file.srl,但是这个答案是跟进问题.
值得一提的是,大多数MongoDB v3.0 +发行版现在都支持SSL,请务必选择支持SSL的软件包.下面的示例使用MongoDB v3.2在带有PyMongo v3.2.1的 Ubuntu Linux 14.04上进行测试.单个计算机生成CA,服务器和客户端pem文件以用于演示目的.
让我们生成ca.pem和privkey.pem.主题结构是/C=<Country Name>/ST=<State>/L=<Locality Name>/O=<Organisation Name>/emailAddress=<email>/CN=<Common Name>.
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"
Run Code Online (Sandbox Code Playgroud)
生成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=<hostname value>/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
Run Code Online (Sandbox Code Playgroud)
虽然您也可以使用IP地址作为CN值,但不建议这样做.请参阅RFC-6125.
现在让我们生成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
Run Code Online (Sandbox Code Playgroud)
生成.pem文件后,现在可以运行mongod.例如:
mongod --sslMode requireSSL --sslPEMKeyFile ~/server.pem --sslCAFile ~/ca.pem
Run Code Online (Sandbox Code Playgroud)
您可以使用mongo shell测试连接,例如:
mongo --ssl --sslPEMKeyFile ~/client.pem --sslCAFile ~/ca.pem --host <server hostname>
Run Code Online (Sandbox Code Playgroud)
成功连接后,您可以尝试使用PyMongo.例如:
import ssl
from pymongo import MongoClient
client = MongoClient(
'<server hostname>',
27017,
ssl=True,
ssl_certfile='~/client.pem',
ssl_cert_reqs=ssl.CERT_REQUIRED,
ssl_ca_certs='~/ca.pem'
)
Run Code Online (Sandbox Code Playgroud)
或者,您也可以使用mongod标志--sslAllowInvalidHostnames来指定localhost等.
对于生产用途,MongoDB部署应使用由单个证书颁发机构生成和签名的有效证书.如果使用自签名证书,虽然通信通道将被加密,但不会验证服务器标识.使用由受信任的证书颁发机构签名的证书将允许MongoDB驱动程序验证服务器的身份.通常,除非网络受信任,否则请避免使用自签名证书.
您可能会发现有用的其他相关链接: