Skip to content

Commit

Permalink
Add support for client-side cert/key to gRPC exports.
Browse files Browse the repository at this point in the history
TODO: Add tests.

I have not run or written any tests, other than verifying it worked once
in my production system.
  • Loading branch information
kylepl committed Jun 21, 2023
1 parent cfcda57 commit 355def3
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 11 deletions.
5 changes: 5 additions & 0 deletions api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ if(WITH_OTLP_HTTP_SSL_PREVIEW)
endif()
endif()

if (WITH_OTLP_GRPC_MTLS_PREVIEW)
target_compile_definitions(opentelemetry_api
INTERFACE ENABLE_OTLP_GRPC_MTLS_PREVIEW)
endif()

if(WITH_METRICS_EXEMPLAR_PREVIEW)
target_compile_definitions(opentelemetry_api
INTERFACE ENABLE_METRICS_EXEMPLAR_PREVIEW)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#pragma once

#include "absl/types/optional.h"
#include "absl/types/variant.h"
#include "opentelemetry/exporters/otlp/otlp_environment.h"

#include <memory>
Expand All @@ -28,6 +30,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_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
Expand Down
35 changes: 24 additions & 11 deletions exporters/otlp/src/otlp_grpc_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ 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<grpc::Channel> OtlpGrpcClient::MakeChannel(const OtlpGrpcExporterOptions &options)
Expand All @@ -58,17 +68,20 @@ std::shared_ptr<grpc::Channel> OtlpGrpcClient::MakeChannel(const OtlpGrpcExporte
grpc::ChannelArguments grpc_arguments;
grpc_arguments.SetUserAgentPrefix(options.user_agent);

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());
}
if (options.use_ssl_credentials) {
grpc::SslCredentialsOptions ssl_opts = {
.pem_root_certs = GetFileContentsOrInMemoryContents(
options.ssl_credentials_cacert_path,
options.ssl_credentials_cacert_as_string),
#if ENABLE_OTLP_GRPC_MTLS_PREVIEW
.pem_private_key = GetFileContentsOrInMemoryContents(
options.ssl_client_key_path,
options.ssl_client_key_string),
.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);
}
Expand Down

0 comments on commit 355def3

Please sign in to comment.