Any examples of gRPC server using TLS in CPP??
I am trying to build a gRPC application. The server should provide TLS support if client wants to connect over TLS instead of TCP.
This is my server
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
ServerBuilder builder;
std::shared_ptr<ServerCredentials> creds;
if(enable_ssl)
{
grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp ={"a","b"};
grpc::SslServerCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs="";
ssl_opts.pem_key_cert_pairs.push_back(pkcp);
creds = grpc::SslServerCredentials(ssl_opts);
}
else
creds=grpc::InsecureServerCredentials();
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, creds);
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
Error:
undefined reference to grpc::SslServerCredetials(grpc::ssl_opts)
I have included all the necessary files..
You code looks right. If you are adapting from examples/cpp/helloworld, you need to change -lgrpc++_unsecure to -lgrpc++ in the Makefile.
For the benefits of others, an example of using the tls/ssl code can be found at https://github.com/grpc/grpc/blob/master/test/cpp/interop/server_helper.cc#L50
Related
I am creating a static library out of my grpc c++ client and I am able to successfully call the API in the grpc static library using a test application.
But when I integrate the static library with a different service and call the API in the grpc static lib from that service, it fails with the error below
Handshaker factory creation failed with TSI_INVALID_ARGUMENT.
Failed to create secure subchannel for secure name 'xx.xx.xx.xx:xx'
Failed to create channel args during subchannel creation.
On the same VM where I see the above error when I copy and run the test application that calls the grpc client, it works fine.
Here is the client code, based on(https://www.programmersought.com/article/7290364277/):
int main(int argc, char** argv) {
grpc::SslCredentialsOptions ssl_options;
ssl_options.pem_root_certs = SERVER_CRT;
// Create a default SSL ChannelCredentials object.
auto channel_creds = grpc::SslCredentials(ssl_options);
grpc::ChannelArguments cargs;
cargs.SetSslTargetNameOverride("xxx.xxx.com"); // If you add DNS, you don't need this.
// Create a channel using the credentials created in the previous step.
auto channel = grpc::CreateCustomChannel("1.2.3.4:8000", channel_creds , cargs);
// Instantiate the client.
MailClient tester(channel);
}
ssl_options.pem_root_certs = SERVER_CRT;
// The contents of server.crt
const char SERVER_CRT[] = R"(
-----BEGIN CERTIFICATE-----
TjERMA8GA1UECAwIU2hhbmdoYWkxEjAQBgNVBAcMCVNvbmdqaWFuZzEPMA0GA1UE
...
E6v50RCQgtWGmna+oy1I2UTVABdjBFnyKPEuz106mBfOhT6cg80hBHVgrV7sLHq8
76QolJm8yzZPL1qpiO4dKHHsCP6R
-----END CERTIFICATE-----
)";
Probably some issue with the way I have provided the cert?
why does the rpc call in the grpc client work from the test application but not from a different service
on the same VM?
Any suggestions appreciated.
The application that I was trying to integrate was using libssl 1.0.2 which doesn't support TLS1.3 but grpc 1.35 by default uses TLS1.3 and openssl 1.1.1. So built gRPC with gRPC_SSL_PROVIDER=package and it picked up libssl 1.0.2 and that fixed the issue. Hope this helps anyone.
I'm trying to build a gRPC server on Ubuntu and it keeps failing at std::unique_ptr<Server> server(builder.BuildAndStart());
The whole code snippet is
string async_port(":6150");
grpc::EnableDefaultHealthCheckService(true);
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(sync_port.substr(1,4), grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(this);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
printf("reached here\n");
server->Wait();
and the error is
E0722 19:54:28.324066366 257369 server_chttp2.cc:40]
{"created":"#1595465668.324006753","description":
"No address added out of total 1 resolved","file":"src/core/ext/transport/chttp2/server
/chttp2_server.cc","file_line":397,"referenced_errors":
[{"created":"#1595465668.324002966","description":"Unable to configure socket","fd":7,"file":"src/core/lib/iomgr
/tcp_server_utils_posix_common.cc","file_line":216,
"referenced_errors":[{"created":"#1595465668.323994409","
description":"Permission denied","errno":13,"file":"src/core/lib/iomgr
/tcp_server_utils_posix_common.cc","file_line":190,"os_error":"Permission denied","syscall":"bind"}]}]}
I am writing a service discovery application which will register web applications on a zookeeper node. One of the attribute is the port number on which service is available. In code I got the handle of jetty server instance but how can I find the port number from a Jetty Server instance ?
Walk the connectors, and ask them for their registered host names (so you know what network interfaces they are listening on) and local ports (that they are bound to).
Here's a template you can start with.
for (Connector connector : server.getConnectors())
{
if (connector instanceof NetworkConnector)
{
// we have a network capable connector
NetworkConnector networkConnector = (NetworkConnector) connector;
// What interface?
String interfaceName = networkConnector.getHost();
// What local port is it bound to?
int localPort = networkConnector.getLocalPort();
// What is the declared protocol default for this connector?
String defaultProtocol = networkConnector.getDefaultConnectionFactory().getProtocol();
// What other features does this connector handle?
for (ConnectionFactory connectionFactory : networkConnector.getConnectionFactories())
{
// List of protocols handled by this specific connection factory for this specific connector
connectionFactory.getProtocols();
if (connectionFactory instanceof SslConnectionFactory)
{
// this can handle TLS/SSL based connections
}
if (connectionFactory instanceof HttpConnectionFactory)
{
// this can handle http protocols
// get the http specific configuration
HttpConfiguration httpConfig = ((HttpConnectionFactory) connectionFactory).getHttpConfiguration();
// what port is recognized as secure
httpConfig.getSecurePort();
// what scheme is recognized as secure
httpConfig.getSecureScheme();
}
if (connectionFactory instanceof HTTP2ServerConnectionFactory)
{
// can handle encrypted http/2 protocols (and alpn features)
}
if (connectionFactory instanceof HTTP2CServerConnectionFactory)
{
// this can handle http/2's special clear-text "h2c" protocol (no alpn features)
}
}
}
}
i am using embedded Jetty to implement HTTP/2. At the moment i am trying to add a ServerSessionListener (from: org.eclipse.jetty.http2.api.Session.Listener.Adapter) to my Server.
i tried to add it to the Context and Server via: addEventListener with no success.
Maybe someone can give me a hint about what i am doing wrong..
I want to add a session Listener to my HTTP2 Connection to track the connected Sessions (Clients) and their connection duration.
Regards!
You can add an implementation of Connection.Listener as a bean to the connector itself, for example:
http2Connector.addBean(new Connection.Listener()
{
public void onOpened(Connection connection) { ... }
public void onClosed(Connection connection) { ... }
});
Alternatively you can add the Connection.Listener as a bean to the ConnectionFactory.
In both cases, every time a connection is created, the listener is added to the connection and will be invoked when the connection opens and when it closes.
You can use Jetty's ConnectorStatistics class that already gathers a number of statistics about connections and already implements Connection.Listener.
I'm using pion network library to write a HTTP(s) server, pion is a wrapper for boost::asio. I need the server support both HTTP and HTTPS, the HTTP is done with:
#include "pion/http/server.hpp"
#include "pion/http/response_writer.hpp"
using namespace pion;
using namespace pion::http;
struct fake_server {
void start() {
m_server = pion::http::server_ptr(new pion::http::server(80));
m_server->add_resource("/", boost::bind(&fake_server::handle_request, this, _1, _2));
m_server->start();
}
void handle_request(http::request_ptr& _httpRequest, tcp::connection_ptr& _tcpConn) {
http::response_writer_ptr writer(
http::response_writer::create(
_tcpConn,
*_httpRequest,
boost::bind(&tcp::connection::finish, _tcpConn)));
http::response& r = writer->get_response();
writer->write("hello world");
writer->send();
}
pion::http::server_ptr m_server;
};
int main() {
fake_server svr;
svr.start();
while(1) {
Sleep(0);
}
}
But I don't know how to handle the HTTPS, I tried to set the port to 443, and set the ssl flag with:
void start() {
m_server = pion::http::server_ptr(new pion::http::server(443)); // 443
m_server->set_ssl_flag(true); // ssl flag
m_server->add_resource("/", boost::bind(&fake_server::handle_request, this, _1, _2));
m_server->start();
}
It doesn't work, I got an error "no shared cipher", I googled for this error and found some solution that uses openssl to generate cert pairs and then load these cert pairs in the server/client, but my client application is web browser, the browser won't use these generated certifications.
Any idea?
Thanks.
You need to provide an SSL certificate and key the server will use to negotiate the secure connection. This would be done with:
m_server->set_ssl_key_file(pem_filename);
where pem_filename is the name of a PEM formatted file containing both an SSL certificate and key. The key must not be encrypted. There are numerous internet tutorials that tell you how to create a self-signed certificate if you don't already have one from a trusted certificate authority. If you have a key and certificate in separate files then simply concatenate them into a single file.
No prior certificate/key configuration is necessary on the client side (in this case), but note that using a self-signed certificate (or any certificate not signed by a trusted certificate authority) will generate a security warning on most web browsers.