【问题标题】:grpc python client authentication throwing SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILEDgrpc python客户端身份验证抛出SSL_ERROR_SSL:错误:1000007d:SSL例程:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
【发布时间】:2021-10-30 22:41:42
【问题描述】:

我正在构建一个具有安全身份验证的基于 grpc 的应用程序,grpc python 客户端是否有任何问题,或者我遗漏了什么?因为在文档上它并没有说太多。

我的环境如下:

OS: "Ubuntu 18.04.5 LTS"
python 3.7
openssl V 1.1.1-1ubuntu2.1~18.04.13
grpcio==1.39.0
grpcio-tools==1.39.0
protobuf==3.17.3

我总是收到 SSL_ERROR_SSL: CERTIFICATE_VERIFY_FAILED

E0901 13:16:05.996420843   13512 ssl_transport_security.cc:1468] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.
E0901 13:16:06.495380631   13512 ssl_transport_security.cc:1468] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.
E0901 13:16:06.953751870   13512 ssl_transport_security.cc:1468] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.
E0901 13:16:07.407166253   13512 ssl_transport_security.cc:1468] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.
Traceback (most recent call last):
  File "grpc-client.py", line 21, in <module>
    main()
  File "grpc-client.py", line 11, in main
    response = stub.ApiEndpoint(request)
  File "/home/ggarg/.local/lib/python3.7/site-packages/grpc/_channel.py", line 946, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/home/ggarg/.local/lib/python3.7/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
    status = StatusCode.UNAVAILABLE
    details = "failed to connect to all addresses"

我的原型文件是:

syntax = "proto3";

service Api{
    rpc ApiEndpoint(ApiRequest)  returns (ApiResponse);   
}

message ApiRequest{
    string name = 1;
    string message = 2;
}

message ApiResponse{
    string reply = 1;
}

服务器代码是:

import grpc
from concurrent import futures
import time
import api_pb2
import api_pb2_grpc
import os


class ChatBox(api_pb2_grpc.ApiServicer):

    def ApiEndpoint(self, request, context):
        response = api_pb2.ApiResponse()
        response.reply = "Hi {}, myself {} , Thanks for this message : {}".format(
            request.name, os.getenv("POD_NAME"), request.message)
        return response


if __name__ == '__main__':
    # create a gRPC server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    with open('cert/server.key', 'rb') as f:
        private_key = f.read()
    with open('cert/server.crt', 'rb') as f:
        certificate_chain = f.read()
    server_credentials = grpc.ssl_server_credentials(
        ((private_key, certificate_chain), ))

    # add the servier created above tp the server
    api_pb2_grpc.add_ApiServicer_to_server(ChatBox(), server)

    # listen on port 50051
    print('Starting server. Listening on port 50051.')
    server.add_secure_port('[::]:50051', server_credentials)
    server.start()
    # since server.start() will not block,
    # a sleep-loop is added to keep alive
    try:
        while True:
            time.sleep(86400)
    except KeyboardInterrupt:
        server.stop(0)

客户端代码是:

import grpc
import api_pb2_grpc
import api_pb2
import time

def main():
    request = api_pb2.ApiRequest(
        name="timus",
        message="You are awesome")

    response = stub.ApiEndpoint(request)
    print(response)

if __name__ == '__main__':
    with open('cert/server.crt', 'rb') as f:
        creds = grpc.ssl_channel_credentials(f.read())
    #channel = grpc.secure_channel('www.timus.com:443', creds)
    channel = grpc.secure_channel('0.0.0.0:50051', creds)
    stub = api_pb2_grpc.ApiStub(channel)
    while True:
        main()
        time.sleep(2)

我使用以下 openssl 命令生成 crt。

openssl req -newkey rsa:4096 -nodes -sha512 -x509 -days 3650 -nodes -out server.crt -keyout server.key

我粘贴了上面的代码作为示例。为简单起见,我在客户端和服务器上使用相同的证书。最初我以不同的方式使用 ca/server/client 证书,但我遇到了这个问题,只是为了测试我在客户端和服务器端都使用了服务器证书。但仍然遇到同样的问题?有没有人遇到过类似的问题?提前致谢。

【问题讨论】:

    标签: python ssl grpc grpc-python


    【解决方案1】:

    您似乎正在尝试将服务器证书分配为客户端的信任证书。这将要求证书为self-signed certificate。你必须检查一下。

    即使是自签名的,也不是我们建立TLS连接的常用方式。这可能会使您的应用程序遭受中间人攻击。您需要让您的客户端设置一个由 CA 颁发的信任证书,并让 CA 签署服务器的证书。这可以确保有一个值得信赖的第三方来确保身份验证良好。

    您还将确保语法正确(抱歉,我对 Python 语法不太熟悉)。我们允许客户端和服务器中的证书、根证书用于双向 TLS,但对于单 TLS,您只需为服务器设置证书,为客户端设置根证书。

    【讨论】:

    • 感谢@Zhen Lian,问题是自签名证书,现在可以正常使用了。
    猜你喜欢
    • 2022-10-01
    • 1970-01-01
    • 2021-01-16
    • 2019-03-28
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 2018-06-17
    相关资源
    最近更新 更多