gRPC remote connection with/without credentials (c++)

Hi,
We are trying to write a c++ application which is run on a remote host (running linux) and uses gRPC (https://github.com/grpc/grpc) (remote) to exchange data with an AXC F 3152. We have tested and verified with grpcurl (following the guide) that everything works and are able to read data perfectly fine with that utility in insecure mode. We then tried the following code on our remote machine (same local network, very similar to the grpc c++ plcnext example except from a remote host (https://github.com/PLCnext/plcnext-grpc-example-cpp) ) :

std::shared_ptr<Channel> channel = grpc::CreateChannel("192.168.0.1:50051", grpc::InsecureChannelCredentials());
auto dataAccessService = IDataAccessService();
auto dataAccessStub    = dataAccessService.NewStub(channel);
 auto ctx               = grpc::ClientContext();
auto request           = IDataAccessServiceReadRequest();
auto portName          = "MyComponent/Item1.Config";
request.add_portnames(portName);
auto response = IDataAccessServiceReadResponse();
auto status   = dataAccessStub->Read(&ctx, request, &response);
if (status.ok())
{
  Logging::info("Portname: {0}
Output: {1}", portName, response.SerializeAsString());
}
else
{
  Logging::error("gRPC failed: {0}", status.error_message());
}

When we run this however, it fails to connect , with the following error : „gRPC failed: failed to connect to all addresses; last error: UNAVAILABLE: ipv4:192.168.0.1:50051: Socket closed“ So we tried using the CA certificate from the controller (similar process to here https://www.plcnext-community.net/makersblog/secure-remote-grpc-using-grpcurl/, user authentication disabled however on the PLC) , and got a different authentication error. We did this since even with „InsecureChannelCredentials“ above, it still appeared to be using a TLS socket. Hence :

auto CA = fileToString("src/machines/plt/server/bin/CA.crt");
auto credentials                 = grpc::SslCredentials(grpc::SslCredentialsOptions());
std::shared_ptr<Channel> channel = grpc::CreateChannel("192.168.0.1:50051", credentials);

Hence : " gRPC failed: failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.0.1:50051: Ssl handshake failed: SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED"

Questions :
* Has anyone tried to use gRPC (specifically using the c++ api) to communicate with a PLCNext controller from a remote device ? If so, do they have any advice ?
* Are there any other tips/settings that might be applicable on the PLC relative to gRPC that might be useful for us to explore ?

Cheers,
Lindsay

  1. Did you get the example C++ application (from Github) working on the same device as the gRPC server (i.e. the PLC)?
    2. The example in Github uses the gRPC channel unix:/run/plcnext/grpc.sock, i.e. a Unix domain socket. If that example works on the PLC, then that very same example should also work on the same PLC if the gRPC channel is changed to 192.168.0.1:50051 (or perhaps even localhost:50051), i.e. an IP socket. Does that work?
    3. If that works, then can you build the same example for your remote Linux machine, and try to connect from there? If (2) works, then I would also expect this to work.

I have not yet attempted to use the C++ api remotely, I did for Python, had issues with insecure channels as well.
Had to regenerate a certificate via the wbm (because of alternate IPs)
With python I managed to get it to work like this:

with open("server.crt", "rb") as f:
    ca_cert = f.read()
#channel = grpc.insecure_channel('10.0.21.111:50051')
channel = grpc.secure_channel('10.0.21.111:50051', grpc.ssl_channel_credentials(ca_cert))
(more details in a forum post around here)
I have used the C++ using the unix domain socket as well, the linked example worked fine, running on the controller.
I don't see how the CA-cert is passed to the SSLOptions in your code snippet (CA is unused?), should be something like this:
  // Create a SslCredentialsOptions object.
  grpc::SslCredentialsOptions ssl_options;
  // Set the pem_root_certs option to the string containing the CA cert.
  ssl_options.pem_root_certs = ca_cert;
  // Create a SslCredentials object.
  grpc::SslCredentials* ssl_credentials = grpc::SslCredentials(ssl_options);
  // Create a gRPC client.
  grpc::Channel* channel = grpc::CreateChannel("localhost:50051", ssl_credentials);

Hi Martin & RXQ,
Thanks for the prompt responses and sorry for the delay in responding (we were under time pressure, so ended up switching to a vanilla TCP socket implementation with binary serialization). In response to the questions above :

                              1. No, we never tried the example C++ GRPC application on the PLC. In hindsight, this is probably the way to go (and gradually work your way to a remote host). 
                              2. Yep, we tried regenerating the CA via WBM for the changed IP address, and passed it in in much the same manner as the python script above, but still got the same response when remote. 

When we get time to revisit this, we will update about what we find. Thanks again for the responses and apologies that we have not taken action w.r.t some of the proposed solutions.
Cheers,
Lindsay