使用 TLS 将 pymongo 客户端连接到 mongodb 服务器
Posted
技术标签:
【中文标题】使用 TLS 将 pymongo 客户端连接到 mongodb 服务器【英文标题】:Connecting pymongo client to mongodb server with TLS 【发布时间】:2021-08-13 20:19:28 【问题描述】:我在 Google Cloud 上有 2 个实例:
实例 A 和 实例 B - 都具有静态外部 IP 地址。
实例 A 运行社区版 MongoDB 服务器 v4.4.6。
我已生成自签名证书以启用 TLS 我已在我的云网络中设置防火墙规则,以允许来自实例 B的 IP 地址的流量到 MongoDB 端口因此,我成功地使用 Instance B 中的 mongo shell(v4.4.6) 连接到 Instance A 上运行的 mongo 服务器。这是我使用的命令 -
mongo --tls --tlsCertificateKeyFile client.pem --tlsCAFile ca.pem <instance_a_ip>:<port>/admin -u <userName> -p
我想使用 Instance B 中的 pymongo(v3.11.4) 客户端连接到 Instance A 中的 MongoDB 服务器,我已经尝试使用这在交互式 python shell 中 -
client = MongoClient("mongodb://<instance_a_ip>:<port>/admin", tls=True, tlsCertificateKeyFile='./client.pem', tlsCAFile='./ca.pem', username='<userName>', password='<userPassword>')
但是,我无法连接,这是我收到的错误 -
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/varun/test-env/lib/python3.8/site-packages/pymongo/collection.py", line 1319, in find_one
for result in cursor.limit(-1):
File "/home/varun/test-env/lib/python3.8/site-packages/pymongo/cursor.py", line 1207, in next
if len(self.__data) or self._refresh():
File "/home/varun/test-env/lib/python3.8/site-packages/pymongo/cursor.py", line 1100, in _refresh
self.__session = self.__collection.database.client._ensure_session()
File "/home/varun/test-env/lib/python3.8/site-packages/pymongo/mongo_client.py", line 1816, in _ensure_session
return self.__start_session(True, causal_consistency=False)
File "/home/varun/test-env/lib/python3.8/site-packages/pymongo/mongo_client.py", line 1766, in __start_session
server_session = self._get_server_session()
File "/home/varun/test-env/lib/python3.8/site-packages/pymongo/mongo_client.py", line 1802, in _get_server_session
return self._topology.get_server_session()
File "/home/varun/test-env/lib/python3.8/site-packages/pymongo/topology.py", line 496, in get_server_session
self._select_servers_loop(
File "/home/varun/test-env/lib/python3.8/site-packages/pymongo/topology.py", line 215, in _select_servers_loop
raise ServerSelectionTimeoutError(
pymongo.errors.ServerSelectionTimeoutError: <instance_a_ip>:<port>: ("Invalid DNS pattern b'127.0.0.1'.",), Timeout: 30s, Topology Description: <TopologyDescription id: 60ad03827b267af40c2edf4b, topology_type: Single, servers: [<ServerDescription ('<instance_a_ip>', <port>) server_type: Unknown, rtt: None, error=AutoReconnect('<instance_a_ip>:<port>: ("Invalid DNS pattern b\'127.0.0.1\'.",)')>]>
我是 MongoDB 新手,不知道该怎么做,非常感谢您的帮助。
【问题讨论】:
您的设置中的什么解析为 127.0.0.1? 我也不是 100% 确定,因为当我使用 mongo shell 时,我能够很好地连接到 mongo 服务器。我怀疑这与 pymongo 有关吗? 您可以修补驱动程序以重新引发处理 AutoReconnect 的异常,这将为您提供原始问题的堆栈跟踪。 通过为 mongodb 安装 Nodejs 客户端来解决问题。它为我提供了一个更好的例外,我可以追溯到我的代码。 【参考方案1】:通过安装适用于 MongoDB 的 Nodejs 客户端来调试问题。 Node 客户端在失败时提供了更好的消息 -
[Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: IP: 34.126.133.72 is not in the cert's list
感谢这个有意义的错误,我通读了我在创建自签名证书时使用的 OpenSSL 配置文件。纠正了我在配置文件中犯的错误 -
导致错误的原始配置文件
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = 127.0.0.1
DNS.2 = <instance_a_ip>
经过调整的配置文件现在可以与所有 MongoDB 客户端一起使用
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
IP.1 = 127.0.0.1
IP.2 = <instance_a_ip>
【讨论】:
【参考方案2】:您的证书是自签名的,在创建 MongoClient 时添加此选项。
tlsInsecure=True
代码会是这样的
client = MongoClient(
["<instance_a_ip>:<port>"],
tls=True,
tlsInsecure=True,
tlsCertificateKeyFile='./client.pem',
tlsCAFile='./ca.pem',
username='<userName>',
password='<userPassword>'
)
【讨论】:
以上是关于使用 TLS 将 pymongo 客户端连接到 mongodb 服务器的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 pymongo 2.2 连接到 MongoDB 2.0.5 数据库
使用 PyMongo 和 x509 SSL 证书连接到 MongoDB 数据库时出现 ServerSelectionTimeoutError
Pymongo 无法连接到数据库:pymongo.errors.ServerSelectionTimeoutError: connection closed