[VOL-3386] Add support for secure gRPC in openolt-agent
The init script of the openolt service may start with '--enable-tls <TLS_OPTION>' argument for the gRPC server.
Default is insecure with no '--enable-tls' argument.
The TLS capability depends upon the certificates stored at the keystore/ directory: 1. root.crt (CA public key), 2. server.crt (public key), 3.server.key (private key).
Four unit tests are added for the secure gRPC server which work with the keystore-test/ directory.
The certificates stored at the keystore-test/ directory are self-signed certificates, valid until Apr 11 23:16:58 2031 GMT.
Change-Id: I4d18a98a0193f501f922360c79f54b0fcedf14a5
diff --git a/agent/common/server.cc b/agent/common/server.cc
index 2b7a915..68cce10 100644
--- a/agent/common/server.cc
+++ b/agent/common/server.cc
@@ -27,6 +27,7 @@
#include "server.h"
#include "core.h"
#include "state.h"
+#include "../src/core_utils.h"
#include <grpc++/grpc++.h>
#include <voltha_protos/openolt.grpc.pb.h>
@@ -348,8 +349,11 @@
}
};
-void RunServer(int argc, char** argv) {
+bool RunServer(int argc, char** argv) {
std::string ipAddress = "0.0.0.0";
+ bool tls_enabled = false;
+ std::pair<grpc_ssl_client_certificate_request_type, bool> grpc_security;
+ std::shared_ptr<grpc::ServerCredentials> credentials;
for (int i = 1; i < argc; ++i) {
if(strcmp(argv[i-1], "--interface") == 0 || (strcmp(argv[i-1], "--intf") == 0)) {
@@ -358,6 +362,47 @@
}
}
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp(argv[i-1], "--enable-tls") == 0) {
+ grpc_security = get_grpc_tls_option(argv[i]);
+ if (grpc_security.second) {
+ tls_enabled = true;
+ } else {
+ std::cerr << "unknown security option: \"" << argv[i-1] << " " << argv[i] << "\"\n";
+ return false;
+ };
+ break;
+ }
+ }
+
+ if (tls_enabled) {
+ std::string dir_cert{"./keystore"};
+ auto read_root_crt = read_from_txt_file(dir_cert + "/root.crt");
+ auto read_server_key = read_from_txt_file(dir_cert + "/server.key");
+ auto read_server_crt = read_from_txt_file(dir_cert + "/server.crt");
+
+ if (read_root_crt.second && read_server_key.second && read_server_crt.second) {
+ std::cout << "certificate files read successfully\n";
+ } else {
+ std::cerr << std::boolalpha << "certificate files read failed - root.crt: " << read_root_crt.second
+ << ", server.key: " << read_server_key.second
+ << ", server.crt: " << read_server_crt.second << '\n';
+ return false;
+ }
+
+ std::string root_crt = read_root_crt.first;
+ std::string server_key = read_server_key.first;
+ std::string server_crt = read_server_crt.first;
+
+ grpc::SslServerCredentialsOptions ssl_opts{grpc_security.first};
+ ssl_opts.pem_root_certs = root_crt;
+ grpc::SslServerCredentialsOptions::PemKeyCertPair keycert = {server_key, server_crt};
+ ssl_opts.pem_key_cert_pairs.push_back(keycert);
+ credentials = grpc::SslServerCredentials(ssl_opts);
+ } else {
+ credentials = grpc::InsecureServerCredentials();
+ }
+
serverPort = ipAddress.append(":9191").c_str();
OpenoltService service;
std::string server_address(serverPort);
@@ -365,7 +410,7 @@
::ResourceQuota quota;
quota.SetMaxThreads(GRPC_THREAD_POOL_SIZE);
builder.SetResourceQuota(quota);
- builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
+ builder.AddListeningPort(server_address, credentials);
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
@@ -377,5 +422,11 @@
std::cout << "Server listening on " << server_address
<< ", connection signature : " << signature << std::endl;
+#ifdef TEST_MODE
+ server->Shutdown();
+#else
server->Wait();
+#endif
+
+ return true;
}