You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCP部署应用中psycopg2传入SSL证书字符串连接数据库失败

问题:Psycopg2使用字符串形式的SSL证书/密钥连接GCP数据库失败

在GCP部署应用时,使用psycopg2连接数据库,当传入证书文件路径时连接正常:

psycopg2.connect(host='hostname',port=1234, connect_timeout=100, database='db', user='user', password='pwd',
sslrootcert="server-cert.pem",
sslcert="client-cert.pem",
sslkey="key.pem")

但直接传入证书/密钥字符串时连接失败,报错:

FATAL: connection requires a valid client certificate
connection to server at "hostname", port 1234 failed

使用的代码如下:

SERVER_CERT = """-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----"""
CLIENT_CERT = """-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----"""
KEY = """-----BEGIN RSA PRIVATE KEY-----
xxxxn-----END RSA PRIVATE KEY-----"""
psycopg2.connect(host='hostname',port=1234, connect_timeout=100, database='db', user='user', password='pwd',
sslrootcert=SERVER_CERT,
sslcert=CLIENT_CERT,
sslkey=KEY)

尝试过ssl.DER_cert_to_PEM_cert()和RSA.importKey()处理字符串,但仍然失败。请问如何直接传入字符串而非文件路径建立连接?


解决方案

核心原因

psycopg2的sslrootcert、sslcert、sslkey参数仅接受文件路径,而非证书/密钥的字符串内容。直接传入字符串会被当作文件路径解析,导致找不到对应文件,最终触发证书验证失败。

方法一:使用Python SSLContext对象(推荐)

通过创建ssl.SSLContext对象,直接加载字符串形式的证书和密钥,再将该对象传入psycopg2的sslcontext参数,无需创建临时文件。

import ssl
import psycopg2

SERVER_CERT = """-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----"""
CLIENT_CERT = """-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----"""
KEY = """-----BEGIN RSA PRIVATE KEY-----
xxxxn-----END RSA PRIVATE KEY-----"""

# 创建SSL上下文,指定用于服务器认证的用途
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)

# 加载CA证书(服务器根证书),使用cadata参数传入字符串内容
ctx.load_verify_locations(cadata=SERVER_CERT)

# 加载客户端证书和密钥,分别通过cert_data和key_data传入字符串内容
ctx.load_cert_chain(certfile=None, cert_data=CLIENT_CERT, keyfile=None, key_data=KEY)

# 建立数据库连接,传入sslcontext参数
conn = psycopg2.connect(
    host='hostname',
    port=1234,
    connect_timeout=100,
    database='db',
    user='user',
    password='pwd',
    sslcontext=ctx
)

方法二:使用临时文件

如果不想处理SSLContext,可以将字符串写入临时文件,再传入文件路径,使用后清理临时文件。

import tempfile
import psycopg2
import os

SERVER_CERT = """-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----"""
CLIENT_CERT = """-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----"""
KEY = """-----BEGIN RSA PRIVATE KEY-----
xxxxn-----END RSA PRIVATE KEY-----"""

# 创建临时文件存储证书和密钥,delete=False避免文件被自动删除
with tempfile.NamedTemporaryFile(mode='w', suffix='.pem', delete=False) as root_cert_file:
    root_cert_file.write(SERVER_CERT)
    root_cert_path = root_cert_file.name

with tempfile.NamedTemporaryFile(mode='w', suffix='.pem', delete=False) as client_cert_file:
    client_cert_file.write(CLIENT_CERT)
    client_cert_path = client_cert_file.name

with tempfile.NamedTemporaryFile(mode='w', suffix='.pem', delete=False) as key_file:
    key_file.write(KEY)
    key_path = key_file.name

try:
    # 传入临时文件路径建立连接
    conn = psycopg2.connect(
        host='hostname',
        port=1234,
        connect_timeout=100,
        database='db',
        user='user',
        password='pwd',
        sslrootcert=root_cert_path,
        sslcert=client_cert_path,
        sslkey=key_path
    )
finally:
    # 强制删除临时文件,避免遗留
    os.unlink(root_cert_path)
    os.unlink(client_cert_path)
    os.unlink(key_path)

内容的提问来源于stack exchange,提问作者ds_Abc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:20:17