当前位置: 首页 > 工具软件 > python-grpc > 使用案例 >

Python-gRPC传输加密

郜联
2023-12-01

本文是关于 gRPC 内置安全验证的概述。这里非常感谢 Thomas French ,在阅读完官方文档之后,感到了晦涩且非常 toy,而他写的博客则较为全面,降低了对于 gRPC 安全认证这个功能学习的门槛。

首先我们来讲下大致的一个流程:

1. 生成认证文件和一个私有密钥

2. 定义一个 RPC 服务

3. 书写服务端代码

4. 书写客户端代码

这里不知道为啥,通过命令行生成的 ssl 生成的证书有点问题。命令行如下:

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt

此时确实生成了 ssl 相关的证书,但是并不能使用,抛出了如下的异常:

details = "failed to connect to all addresses"
debug_error_string = 
	"{"created":"@1619071291.415000000","description":"Failed to pick subchannel"

此时就直接使用了官网示例当中的密钥文件。

下面我们来看下 RPC 的服务定义,也就是说写一个 .proto 文件:

syntax = "proto3";

message Empty {
}

service Server {
  rpc Foo (Empty) returns (Empty) {}
}

server:

from concurrent import futures

import grpc
import service_pb2
import service_pb2_grpc

# 这里需要对抽象方法进行实现
class ServerServicer(service_pb2_grpc.ServerServicer):
    def Foo(self, request, context):
        return service_pb2.Empty()


def main():
    port = '50051'

    with open('localhost.key', 'rb') as f:
        private_key = f.read()
    with open('localhost.crt', 'rb') as f:
        certificate_chain = f.read()

    server_credentials = grpc.ssl_server_credentials(
      ((private_key, certificate_chain,),))

    server = grpc.server(futures.ThreadPoolExecutor(max_workers=1))
    service_pb2_grpc.add_ServerServicer_to_server(ServerServicer(), server)

    server.add_secure_port('[::]:'+port, server_credentials)

    server.start()
    print('server started')
    server.wait_for_termination()

if __name__ == '__main__':
    main()

这里对服务端的代码进行一个简单的说明:

  • 首先我们需要把两个密钥文件的内容都都取出来

    • 需要注意的是这里需要用元组把它给包裹起来:

    • ((private_key, certificate_chain,),)
      
  • 然后开启一个服务,并将对应的服务类添加到服务端当中。

  • 再后面就是绑定安全接口。

client:

import grpc
import service_pb2
import service_pb2_grpc


def main():
    host = 'localhost'
    port = '50051'

    with open('localhost.crt', 'rb') as f:
        trusted_certs = f.read()
    credentials = grpc.ssl_channel_credentials(root_certificates=trusted_certs)
    
    channel = grpc.secure_channel('{}:{}'.format(host, port), credentials)

    stub = service_pb2_grpc.ServerStub(channel)
    print(f'connecting to {port}')
    stub.Foo(service_pb2.Empty())
    print('invoked ok')
    channel.close()

if __name__ == '__main__':
    main()
  • 在客户端这里,我们首先也是读取了安全证书,然后建立连接的时候将证书传入。

  • 然后通过stub 对服务端的方法进行调用。

参考文档:Using SSL with gRPC in Python

下一章:gRPC 传输 metadata

 类似资料: