From 049ab63103b2ede02c6f58c85927e7d4e1834807 Mon Sep 17 00:00:00 2001 From: Kyle L Date: Thu, 29 Jun 2023 04:50:12 -0400 Subject: [PATCH] [EXPORTER] OTLP GRPC mTLS support (#2120) --- api/CMakeLists.txt | 5 ++++ ci/do_ci.sh | 1 + .../otlp/otlp_grpc_exporter_options.h | 13 +++++++++ exporters/otlp/src/otlp_grpc_client.cc | 28 +++++++++++++------ 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/api/CMakeLists.txt b/api/CMakeLists.txt index 31863b25e3..91d129e179 100644 --- a/api/CMakeLists.txt +++ b/api/CMakeLists.txt @@ -113,6 +113,11 @@ if(WITH_OTLP_HTTP_SSL_PREVIEW) endif() endif() +if(WITH_OTLP_GRPC_SSL_MTLS_PREVIEW) + target_compile_definitions(opentelemetry_api + INTERFACE ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW) +endif() + if(WITH_METRICS_EXEMPLAR_PREVIEW) target_compile_definitions(opentelemetry_api INTERFACE ENABLE_METRICS_EXEMPLAR_PREVIEW) diff --git a/ci/do_ci.sh b/ci/do_ci.sh index d504b33ae8..6020d22a04 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -258,6 +258,7 @@ elif [[ "$1" == "cmake.exporter.otprotocol.test" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug \ -DWITH_OTLP_GRPC=ON \ -DWITH_OTLP_HTTP=ON \ + -DWITH_OTLP_GRPC_SSL_MTLS_PREVIEW=ON \ "${SRC_DIR}" grpc_cpp_plugin=`which grpc_cpp_plugin` proto_make_file="CMakeFiles/opentelemetry_proto.dir/build.make" diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h index f5a2b9d295..01ac5b43f2 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h @@ -28,6 +28,19 @@ struct OtlpGrpcExporterOptions // ssl_credentials_cacert_as_string in-memory string representation of .pem file to be used for // SSL encryption. std::string ssl_credentials_cacert_as_string = GetOtlpDefaultSslCertificateString(); + +#ifdef ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW + // At most one of ssl_client_key_* should be non-empty. If use_ssl_credentials, they will + // be read to allow for mTLS. + std::string ssl_client_key_path = GetOtlpDefaultTracesSslClientKeyPath(); + std::string ssl_client_key_string = GetOtlpDefaultTracesSslClientKeyString(); + + // At most one of ssl_client_cert_* should be non-empty. If use_ssl_credentials, they will + // be read to allow for mTLS. + std::string ssl_client_cert_path = GetOtlpDefaultTracesSslClientCertificatePath(); + std::string ssl_client_cert_string = GetOtlpDefaultTracesSslClientCertificateString(); +#endif + // Timeout for grpc deadline std::chrono::system_clock::duration timeout = GetOtlpDefaultTimeout(); // Additional HTTP headers diff --git a/exporters/otlp/src/otlp_grpc_client.cc b/exporters/otlp/src/otlp_grpc_client.cc index 9250f87cc4..5a94c66b59 100644 --- a/exporters/otlp/src/otlp_grpc_client.cc +++ b/exporters/otlp/src/otlp_grpc_client.cc @@ -34,6 +34,18 @@ static std::string GetFileContents(const char *fpath) finstream.close(); return contents; } + +// If the file path is non-empty, returns the contents of the file. Otherwise returns contents. +static std::string GetFileContentsOrInMemoryContents(const std::string &file_path, + const std::string &contents) +{ + if (!file_path.empty()) + { + return GetFileContents(file_path.c_str()); + } + return contents; +} + } // namespace std::shared_ptr OtlpGrpcClient::MakeChannel(const OtlpGrpcExporterOptions &options) @@ -61,14 +73,14 @@ std::shared_ptr OtlpGrpcClient::MakeChannel(const OtlpGrpcExporte if (options.use_ssl_credentials) { grpc::SslCredentialsOptions ssl_opts; - if (options.ssl_credentials_cacert_path.empty()) - { - ssl_opts.pem_root_certs = options.ssl_credentials_cacert_as_string; - } - else - { - ssl_opts.pem_root_certs = GetFileContents((options.ssl_credentials_cacert_path).c_str()); - } + ssl_opts.pem_root_certs = GetFileContentsOrInMemoryContents( + options.ssl_credentials_cacert_path, options.ssl_credentials_cacert_as_string); +#if ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW + ssl_opts.pem_private_key = GetFileContentsOrInMemoryContents(options.ssl_client_key_path, + options.ssl_client_key_string); + ssl_opts.pem_cert_chain = GetFileContentsOrInMemoryContents(options.ssl_client_cert_path, + options.ssl_client_cert_string); +#endif channel = grpc::CreateCustomChannel(grpc_target, grpc::SslCredentials(ssl_opts), grpc_arguments); }