grpc Python:忽略不受信任的证书

use*_*984 11 python ssl grpc

我想为我信任的来源创建一个 grpc 通道,但我缺少其证书。使用默认凭据设置安全通道失败:

import gprc
ssh_channel = grpc.secure_channel(<gprc url>, grpc.ssl_channel_credentials())
grpc.channel_ready_future(ssh_channel).result()
Run Code Online (Sandbox Code Playgroud)

结果是:

E1017 10:05:15.783011100   11539 ssl_transport_security.cc:1229] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.
E1017 10:05:16.846366639   11539 ssl_transport_security.cc:1229] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.
E1017 10:05:18.688887874   11539 ssl_transport_security.cc:1229] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.
E1017 10:05:21.557399186   11539 ssl_transport_security.cc:1229] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.
Run Code Online (Sandbox Code Playgroud)

我知道这是可能的,因为例如在 Java 中,会执行以下操作:

import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyChannelBuilder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
...
sslContext = GrpcSslContexts.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
channel = NettyChannelBuilder.forAddress(<gprc url>, 443).sslContext(sslContext).build();
Run Code Online (Sandbox Code Playgroud)

但是我还没有找到任何类似的 Python 方法。的文档grpc.secure_channel还描述了一个option论点,根据文档是:

用于配置通道的可选键值对列表(gRPC Core 运行时中的通道参数)。

此处对通道参数的引用也不提供任何帮助。有任何想法吗?

更新:(19/01/14):

有一个开放的拉取请求在 Python 代码中添加这个选项,但它似乎在 PR 中停留了几个月:https : //github.com/grpc/grpc/pull/12656

Mar*_*one 6

您可能需要在单独的步骤中从站点获取证书。如果它是一次性的,只需使用您的浏览器并将证书保存在方便的地方。否则,请参阅如何使用 python 检索远程主机的 TLS/SSL 对等证书?

就我而言,我使用浏览器保存了证书并执行了以下操作(我需要使用证书中的目标名称覆盖目标名称,因为它是自签名的且域名不匹配):

with open(cert_path, 'rb') as f:
    cert_bytes = f.read()

credentials = grpc.ssl_channel_credentials(cert_bytes)
# Deal with cert being self-signed:
cert_cn = "cn.from.cert.com" # or parse it out of the cert data
options = (('grpc.ssl_target_name_override', cert_cn,),)

channnel = grpc.secure_channel(target, credentials, options)
Run Code Online (Sandbox Code Playgroud)

  • 这对我不起作用,因为网络包含具有不同域名的代理服务器。我更喜欢一个允许忽略 ssl 证书的选项,就像在 Java 中一样。 (2认同)