简体   繁体   English

在grpc服务器端调用时检索SSL证书

[英]Retrieve SSL certificate on call at grpc server side

I have a gRPC client/server combination which uses the SSLCredentials method for encrypting the communication. 我有一个gRPC客户端/服务器组合,该组合使用SSLCredentials方法对通信进行加密。 I'm trying to retrieve the client's SSL certificate on the server' side (which is written in C++) so I can distinguish between different clients calling the server. 我正在尝试在服务器端(用C ++编写)检索客户端的SSL证书,以便区分在调用服务器的不同客户端之间。

So far I've only been able to find an example for Go which seems to do roughly that, but on the C++ side I was only able to find the AuthMetadataProcessor overloading which only provides the information below, which isn't what I need. 到目前为止,我仅能找到一个Go的示例,该示例似乎大致可以做到这一点,但是在C ++方面,我只能找到AuthMetadataProcessor重载 ,该重载仅提供以下信息,这不是我所需要的。

:authority  =  localhost:50051
:path  =  /API.GameDatabase/saveData
grpc-accept-encoding  =  identity,deflate,gzip
grpc-encoding  =  identity
user-agent  =  grpc-csharp/1.0.1 grpc-c/1.0.1 (linux; chttp2)
Dispatch value:  "/API.GameDatabase/saveData"

Would this be possible or would I have to send this kind of metadata myself? 这是可能的还是我必须自己发送这种元数据?

You can retrieve the client's SSL cert using the AuthContext either in your response handler from the ServerContext or from the AuthMetadataProcessor if you decide to use such an interceptor in order to factor out the authentication/authorization logic from the business logic of your handler. 如果您决定使用这样的拦截器以便从处理程序的业务逻辑中排除身份验证/授权逻辑,则可以在ServerContext或AuthMetadataProcessor的响应处理程序中使用AuthContext检索客户端的SSL证书。 http://www.grpc.io/grpc/cpp/classgrpc_1_1_auth_context.html http://www.grpc.io/grpc/cpp/classgrpc_1_1_auth_context.html

The peer identity property for X509 is set to the SANs if present or CN otherwise. X509的对等身份属性设置为SAN(如果存在),否则设置为CN。 However you have access to the full cert by using the http://www.grpc.io/grpc/core/grpc__security__constants_8h.html#ad46c3fd565d6a24eeb25d1fdc342cb28 property which is populated in the AuthContext. 但是,您可以使用AuthContext中填充的http://www.grpc.io/grpc/core/grpc__security__constants_8h.html#ad46c3fd565d6a24eeb25d1fdc342cb28属性来访问完整证书。

With the help of Julien's answer I was able to get it to work, I'm accepting his answer but giving a code example below: 借助Julien的答案,我能够使其正常工作,我接受他的答案,但在下面给出了代码示例:

grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp =
{"<key>", "<cert>"};

// The client must be force to present a cert every time a call is made,
// else it will only happen once when the first connection is made.
// The other options can be found here:
// http://www.grpc.io/grpc/core/grpc__security__constants_8h.html#a29ffe63a8bb3b4945ecab42d82758f09
grpc::SslServerCredentialsOptions 
ssl_opts(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);

ssl_opts.pem_root_certs = "<CA cert>";
ssl_opts.pem_key_cert_pairs.push_back(pkcp);

std::shared_ptr<grpc::ServerCredentials> sslCredentials = 
grpc::SslServerCredentials(ssl_opts);

builder.AddListeningPort("<server address>", sslCredentials);

There are two options to retrieve the ssl certificate: 有两个选项可检索ssl证书:

  1. Subclass AuthMetaDataProcessor ( refer to this post for more info ), this way you will be able to get the ssl cert in a central place every time a call is made: 子类AuthMetaDataProcessor( 有关更多信息请参阅此帖子 ),这样,每次调用时,您都可以在中央位置获取ssl证书:

     std::shared_ptr<AuthMetaDataProcessor> auth_processor = std::make_shared<AuthMetaDataProcessor>(); // Add the meta data processor to the ssl credentials before building the server sslCredentials->SetAuthMetadataProcessor(auth_processor); 

    and then in the overriden Process function: 然后在覆盖的Process函数中:

     grpc::Status Process(const InputMetadata& auth_metadata, grpc::AuthContext* context, OutputMetadata* consumed_auth_metadata, OutputMetadata* response_metadata) override { std::string cert = context->FindPropertyValues("x509_pem_cert").front().data(); return grpc::Status::OK; } 
  2. Get it from the ServerContext which is provided for every call 从为每个调用提供的ServerContext中获取它

     std::string cert = context->auth_context()->FindPropertyValues("x509_pem_cert").front().data(); 

I hope this helps. 我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM