尝试使用pgAdmin3连接到Heroku PostgresSQL DB时出现以下错误:
Error connecting to the server: SSL error: certificate verify failed
连接基于pg:credentials
输出,定义如下:
[属性]:
[SSL]:
require
[SSH隧道]和[高级]保留默认值
根据Heroku指南启用SSL(设置为:[**require**]
)。
如何提供/修复错误消息引用的证书?
答案 0 :(得分:2)
pgAdmin可能正在获取已在您的系统上配置的一组CA证书,在这种情况下,require
将尝试针对该捆绑包验证服务器证书。
通常,这是root.crt
文件,位于Windows下的%APPDATA%\postgresql\
(C:\Users\YourUserName\AppData\Roaming\postgresql\
)或Linux下的~/.postgresql/
。
如果有这样的文件,请尝试暂时将其移开以检查其是否有效。
将它移开的问题在于,您不再验证任何远程PostgreSQL证书,但它仍可正常工作(使用require
,它将失败verify-full
)。< / p>
您可以通过将root.crt
文件放在正确的位置并将服务器证书添加到可信证书列表中来解决此问题。
找到远程PostgreSQL证书可能有点棘手,但是这个简单的Python应用程序应该允许你这样做(根据需要替换hostname
和port
):
import socket
import ssl
import struct
hostname = '...'
port = 5432
sock = socket.socket()
sock.connect((hostname, port))
# We first connect without encryption and tell the server
# we want to upgrade to SSL/TLS.
initiate_ssl_command = struct.Struct('!ii').pack(8, 80877103)
sock.sendall(initiate_ssl_command)
resp = sock.recv(1)
print "Response should be S: %s" % (resp,)
# We then initiate an SSL/TLS connection on this socket.
ssl_sock = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_NONE)
ssl_sock.do_handshake()
peer_cert = ssl_sock.getpeercert(True)
print ssl.DER_cert_to_PEM_cert(peer_cert)
ssl_sock.close()
(有关此代码的作用的详细信息,请参阅PostgreSQL协议文档,特别是"SSL Session Encryption" section和SSLRequest
message,这与STARTTLS
在其他协议中的作用类似,例如SMTP。)
安全警告:在这里,您只是希望此特定连接未受到攻击并首次返回正版证书。这是您将用作后续连接的信任锚的内容。 (这与为第一个连接接受SSH服务器密钥非常相似,如果证书发生更改,它将标记对证书的更改。)
还值得注意的是,证书主题DN可能与您要连接的服务器的证书不匹配,因此您可能无法使用PostgreSQL的verify-full
模式(这是唯一真正安全的模式,因为它还验证主机名和信任锚。
理想情况下,Heroku(或提供此服务的任何人)应通过其他安全方式向您提供该证书,并确保该证书中的主题DN与他们为您提供的主机名相匹配。 (我不确定目前是否属于这种情况,也许可以从管理界面获得。)