Skip to content

Commit

Permalink
Enable tls authentication for otlp grpc exporter (#635)
Browse files Browse the repository at this point in the history
  • Loading branch information
padmaja-nadkarni authored Mar 30, 2021
1 parent 3ddda3c commit 62c6b13
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 5 deletions.
5 changes: 5 additions & 0 deletions examples/otlp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ SDK](https://github.com/open-telemetry/opentelemetry-cpp). The application then
calls a `foo_library` which has been instrumented using the [OpenTelemetry
API](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/api).

To enable TLS authentication for OTLP grpc exporter, SslCredentials can be used by
specifying the path to client certificate pem file, or the string containing this certificate via OtlpExporterOptions. The path to such a
.pem file can be provided as a command-line argument alongwith the collector endpoint
to the main binary invocation above.

Resulting spans are exported to the **OpenTelemetry Collector** using the OTLP
exporter. The OpenTelemetry Collector can be configured to export to other
backends (see list of [supported
Expand Down
8 changes: 6 additions & 2 deletions examples/otlp/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ opentelemetry::exporter::otlp::OtlpExporterOptions opts;
void InitTracer()
{
// Create OTLP exporter instance
auto exporter = std::unique_ptr<sdktrace::SpanExporter>(new otlp::OtlpExporter(opts));

auto exporter = std::unique_ptr<sdktrace::SpanExporter>(new otlp::OtlpExporter(opts));
auto processor = std::shared_ptr<sdktrace::SpanProcessor>(
new sdktrace::SimpleSpanProcessor(std::move(exporter)));
auto provider = nostd::shared_ptr<trace::TracerProvider>(new sdktrace::TracerProvider(processor));
Expand All @@ -31,6 +30,11 @@ int main(int argc, char *argv[])
if (argc > 1)
{
opts.endpoint = argv[1];
if (argc > 2)
{
opts.use_ssl_credentials = true;
opts.ssl_credentials_cacert_path = argv[2];
}
}
// Removing this line will leave the default noop TracerProvider in place.
InitTracer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ struct OtlpExporterOptions
{
// The endpoint to export to. By default the OpenTelemetry Collector's default endpoint.
std::string endpoint = "localhost:4317";
// By default when false, uses grpc::InsecureChannelCredentials(); If true,
// uses ssl_credentials_cacert_path if non-empty, else uses ssl_credentials_cacert_as_string
bool use_ssl_credentials = false;
// ssl_credentials_cacert_path specifies path to .pem file to be used for SSL encryption.
std::string ssl_credentials_cacert_path = "";
// 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 = "";
};

/**
Expand Down
33 changes: 30 additions & 3 deletions exporters/otlp/src/otlp_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "opentelemetry/exporters/otlp/recordable.h"

#include <grpcpp/grpcpp.h>
#include <fstream>
#include <iostream>

OPENTELEMETRY_BEGIN_NAMESPACE
Expand Down Expand Up @@ -30,13 +31,39 @@ void PopulateRequest(const nostd::span<std::unique_ptr<sdk::trace::Recordable>>
}
}

static std::string get_file_contents(const char *fpath)
{
std::ifstream finstream(fpath);
std::string contents;
contents.assign((std::istreambuf_iterator<char>(finstream)), std::istreambuf_iterator<char>());
finstream.close();
return contents;
}

/**
* Create service stub to communicate with the OpenTelemetry Collector.
*/
std::unique_ptr<proto::collector::trace::v1::TraceService::Stub> MakeServiceStub(
std::string endpoint)
const OtlpExporterOptions &options)
{
auto channel = grpc::CreateChannel(endpoint, grpc::InsecureChannelCredentials());
std::shared_ptr<grpc::Channel> channel;
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 = get_file_contents((options.ssl_credentials_cacert_path).c_str());
}
channel = grpc::CreateChannel(options.endpoint, grpc::SslCredentials(ssl_opts));
}
else
{
channel = grpc::CreateChannel(options.endpoint, grpc::InsecureChannelCredentials());
}
return proto::collector::trace::v1::TraceService::NewStub(channel);
}

Expand All @@ -45,7 +72,7 @@ std::unique_ptr<proto::collector::trace::v1::TraceService::Stub> MakeServiceStub
OtlpExporter::OtlpExporter() : OtlpExporter(OtlpExporterOptions()) {}

OtlpExporter::OtlpExporter(const OtlpExporterOptions &options)
: options_(options), trace_service_stub_(MakeServiceStub(options.endpoint))
: options_(options), trace_service_stub_(MakeServiceStub(options))
{}

OtlpExporter::OtlpExporter(
Expand Down
12 changes: 12 additions & 0 deletions exporters/otlp/test/otlp_exporter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ TEST_F(OtlpExporterTestPeer, ConfigTest)
std::unique_ptr<OtlpExporter> exporter(new OtlpExporter(opts));
EXPECT_EQ(GetOptions(exporter).endpoint, "localhost:45454");
}

// Test exporter configuration options with use_ssl_credentials
TEST_F(OtlpExporterTestPeer, ConfigSslCredentialsTest)
{
std::string cacert_str = "--begin and end fake cert--";
OtlpExporterOptions opts;
opts.use_ssl_credentials = true;
opts.ssl_credentials_cacert_as_string = cacert_str;
std::unique_ptr<OtlpExporter> exporter(new OtlpExporter(opts));
EXPECT_EQ(GetOptions(exporter).ssl_credentials_cacert_as_string, cacert_str);
EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true);
}
} // namespace otlp
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE

0 comments on commit 62c6b13

Please sign in to comment.