如何在没有客户端SSL证书的情况下在Python GRPC客户端打开安全频道

发布于 2025-01-28 13:21:54 字数 1326 浏览 5 评论 0 原文

我有一个具有有效TLS证书的GRPC服务器(在GO中),并且不需要客户端TLS。由于某种原因,即使我可以在Golang中这样做,我也无法在Python中实现客户端。

In Python I have

os.environ["GRPC_VERBOSITY"] = "DEBUG"
# os.environ["GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"] = "/etc/ssl/certs/ca-bundle.crt"

channel = grpc.secure_channel(ADDR, grpc.ssl_channel_credentials())
grpc.channel_ready_future(channel).result(timeout=10)

This gives me the following error

D0513 08:02:08.147319164   21092 security_handshaker.cc:181] Security handshake failed: {"created":"@1652446928.147311309","description":"Handshake failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":377,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}

I can get this to work if I use SSL certificates by uncommenting the commented out line.我知道我的服务器不要求,要求或验证客户端证书,因为以下GO代码完美工作

conn, err := grpc.DialContext(
    ctx,
    gRPCAddr,
    grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
)
dummyClient := dummy.NewDummyServiceClient(conn)
if _, err := dummyClient.Ping(context.Background(), &dummy.PingRequest{
    Ping: "go client ping",
}); err != nil {
    return fmt.Errorf("failed to ping: %w", err)
}

I have a grpc server (in Go) that has a valid TLS certificate and does not require client side TLS. For some reason I can not implement the client without mTLS in Python, even though I can do so in Golang.

In Python I have

os.environ["GRPC_VERBOSITY"] = "DEBUG"
# os.environ["GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"] = "/etc/ssl/certs/ca-bundle.crt"

channel = grpc.secure_channel(ADDR, grpc.ssl_channel_credentials())
grpc.channel_ready_future(channel).result(timeout=10)

This gives me the following error

D0513 08:02:08.147319164   21092 security_handshaker.cc:181] Security handshake failed: {"created":"@1652446928.147311309","description":"Handshake failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":377,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}

I can get this to work if I use SSL certificates by uncommenting the commented out line. I know for a fact that my server does not request, require or verify client certificates as The following Go code work perfectly

conn, err := grpc.DialContext(
    ctx,
    gRPCAddr,
    grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
)
dummyClient := dummy.NewDummyServiceClient(conn)
if _, err := dummyClient.Ping(context.Background(), &dummy.PingRequest{
    Ping: "go client ping",
}); err != nil {
    return fmt.Errorf("failed to ping: %w", err)
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

凉宸 2025-02-04 13:21:54

如果服务器端上的证书已公开签名,则可以使用:

grpc.secure_channel(ADDR, grpc.ssl_channel_credentials())

但这似乎对您不起作用,因此我想服务器证书由您拥有的根证书签名。您可以将根证书传递到 root_certificates 字段[1]中,然后将其他两个字段留为空。该用例记录在我们的身份验证指南[2]中。

with open(os.environ["GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"], 'rb') as f:
    creds = grpc.ssl_channel_credentials(f.read())

channel = grpc.secure_channel(ADDR, creds)

[1]

[2]

If the certificate on the server-side is publicly signed, you can use:

grpc.secure_channel(ADDR, grpc.ssl_channel_credentials())

But that doesn't seem to work for you, so I guess the server certificate is signed by a root cert owned by you. You can pass in the root cert into the root_certificates field [1], and leave the other two fields empty. This use case is documented in our Authentication guide [2].

with open(os.environ["GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"], 'rb') as f:
    creds = grpc.ssl_channel_credentials(f.read())

channel = grpc.secure_channel(ADDR, creds)

[1] https://grpc.github.io/grpc/python/grpc.html#grpc.ssl_channel_credentials

[2] https://grpc.io/docs/guides/auth/

小草泠泠 2025-02-04 13:21:54

httpps:> https:/ grpc.html#secure_channel 具有 channel = grpc.secure_channel(orbium_addr,grpc.ssl_channel_credentials())的文档。此功能依赖于类通道,请参见Docs https:/// grpc.github.io/grpc/python/_modules/grpc/aio/_channel.html

基本上,类通道包装C代码以提供安全的通道。包裹的C代码期望证书。如果您可以在C中实现,则最容易更改C代码。

https://grpc.github.io/grpc/python/_modules/grpc.html#secure_channel has the docs for channel = grpc.secure_channel(ORBIUM_ADDR, grpc.ssl_channel_credentials()). This function relies on the class channel, see docs https://grpc.github.io/grpc/python/_modules/grpc/aio/_channel.html.

Basically, class Channel wraps C code to provide a secure channel. That wrapped C code expects the certificate. If you can implement in C, it might be easiest to just change the C code.

愿与i 2025-02-04 13:21:54

@former_epsilon给出的答案回答了我的问题,但是我为这个问题提出的解决方案是不同的,最终我使用了 secure_channel ,所以我也想为此发布答案。

import os
import grpc

# configure this dict for your systems
system_certs_map = {
    "Windows": "<Path to system cert>",
    "Darwin": "$REQUESTS_CA_BUNDLE",
    "Linux": "/etc/ssl/certs/ca-bundle.crt",
}

os.environ["GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"] = system_certs_map[platform.system()]
channel_credentials = grpc.ssl_channel_credentials()

The answer given by @former_Epsilon answered my question, however the solution I came up with for the problem was different and I ended up using a secure_channel so I wanted to post an answer for that as well.

import os
import grpc

# configure this dict for your systems
system_certs_map = {
    "Windows": "<Path to system cert>",
    "Darwin": "$REQUESTS_CA_BUNDLE",
    "Linux": "/etc/ssl/certs/ca-bundle.crt",
}

os.environ["GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"] = system_certs_map[platform.system()]
channel_credentials = grpc.ssl_channel_credentials()
染火枫林 2025-02-04 13:21:54

我的猜测基于Python grpc doc https://grpc.github.github.io/grpc/pypc/python /grpc.html

channel = grpc.insecure_channel(ORBIUM_ADDR)

而不是:

channel = grpc.secure_channel(ORBIUM_ADDR, grpc.ssl_channel_credentials())

My guess based on Python GRPC doc https://grpc.github.io/grpc/python/grpc.html

channel = grpc.insecure_channel(ORBIUM_ADDR)

instead of:

channel = grpc.secure_channel(ORBIUM_ADDR, grpc.ssl_channel_credentials())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文