From 4dbb03cd34b42e4d032ac1374bac6cc2c726f52c Mon Sep 17 00:00:00 2001 From: Alex Boten <223565+codeboten@users.noreply.github.com> Date: Wed, 27 Nov 2024 10:23:53 -0800 Subject: [PATCH] config: add support for certificate configuration Fixes https://github.com/open-telemetry/opentelemetry-go-contrib/issues/6351 Signed-off-by: Alex Boten <223565+codeboten@users.noreply.github.com> --- config/log.go | 8 ++++++++ config/log_test.go | 36 ++++++++++++++++++++++++++++++++++++ config/metric.go | 8 ++++++++ config/metric_test.go | 35 +++++++++++++++++++++++++++++++++++ config/testdata/bad_cert.crt | 1 + config/testdata/ca.crt | 20 ++++++++++++++++++++ config/trace.go | 9 +++++++++ config/trace_test.go | 36 ++++++++++++++++++++++++++++++++++++ 8 files changed, 153 insertions(+) create mode 100644 config/testdata/bad_cert.crt create mode 100644 config/testdata/ca.crt diff --git a/config/log.go b/config/log.go index 81a769238cd..abc60e83645 100644 --- a/config/log.go +++ b/config/log.go @@ -17,6 +17,7 @@ import ( "go.opentelemetry.io/otel/log/noop" sdklog "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/resource" + "google.golang.org/grpc/credentials" ) func loggerProvider(cfg configOptions, res *resource.Resource) (log.LoggerProvider, shutdownFunc, error) { @@ -178,6 +179,13 @@ func otlpGRPCLogExporter(ctx context.Context, otlpConfig *OTLP) (sdklog.Exporter if u.Scheme == "http" { opts = append(opts, otlploggrpc.WithInsecure()) } + if otlpConfig.Certificate != nil { + creds, err := credentials.NewClientTLSFromFile(*otlpConfig.Certificate, "") + if err != nil { + return nil, fmt.Errorf("could not create client tls credentials: %w", err) + } + opts = append(opts, otlploggrpc.WithTLSCredentials(creds)) + } } if otlpConfig.Compression != nil { switch *otlpConfig.Compression { diff --git a/config/log_test.go b/config/log_test.go index 3e1efe11b3a..984f06b50b8 100644 --- a/config/log_test.go +++ b/config/log_test.go @@ -6,7 +6,9 @@ package config // import "go.opentelemetry.io/contrib/config" import ( "context" "errors" + "fmt" "net/url" + "path/filepath" "reflect" "testing" @@ -221,6 +223,40 @@ func TestLogProcessor(t *testing.T) { }, wantProcessor: sdklog.NewBatchProcessor(otlpGRPCExporter), }, + { + name: "batch/otlp-grpc-good-ca-certificate", + processor: LogRecordProcessor{ + Batch: &BatchLogRecordProcessor{ + Exporter: LogRecordExporter{ + OTLP: &OTLP{ + Protocol: ptr("grpc"), + Endpoint: ptr("localhost:4317"), + Compression: ptr("gzip"), + Timeout: ptr(1000), + Certificate: ptr(filepath.Join("testdata", "ca.crt")), + }, + }, + }, + }, + wantProcessor: sdklog.NewBatchProcessor(otlpGRPCExporter), + }, + { + name: "batch/otlp-grpc-bad-ca-certificate", + processor: LogRecordProcessor{ + Batch: &BatchLogRecordProcessor{ + Exporter: LogRecordExporter{ + OTLP: &OTLP{ + Protocol: ptr("grpc"), + Endpoint: ptr("localhost:4317"), + Compression: ptr("gzip"), + Timeout: ptr(1000), + Certificate: ptr(filepath.Join("testdata", "bad_cert.crt")), + }, + }, + }, + }, + wantErr: fmt.Errorf("could not create client tls credentials: %w", errors.New("credentials: failed to append certificates")), + }, { name: "batch/otlp-grpc-exporter-no-scheme", processor: LogRecordProcessor{ diff --git a/config/metric.go b/config/metric.go index de5629a7edb..91edf15eb3c 100644 --- a/config/metric.go +++ b/config/metric.go @@ -17,6 +17,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" + "google.golang.org/grpc/credentials" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -205,6 +206,13 @@ func otlpGRPCMetricExporter(ctx context.Context, otlpConfig *OTLPMetric) (sdkmet if u.Scheme == "http" { opts = append(opts, otlpmetricgrpc.WithInsecure()) } + if otlpConfig.Certificate != nil { + creds, err := credentials.NewClientTLSFromFile(*otlpConfig.Certificate, "") + if err != nil { + return nil, fmt.Errorf("could not create client tls credentials: %w", err) + } + opts = append(opts, otlpmetricgrpc.WithTLSCredentials(creds)) + } } if otlpConfig.Compression != nil { diff --git a/config/metric_test.go b/config/metric_test.go index 07defc008bb..fac9b6c4a60 100644 --- a/config/metric_test.go +++ b/config/metric_test.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "net/url" + "path/filepath" "reflect" "testing" "time" @@ -215,6 +216,40 @@ func TestReader(t *testing.T) { }, wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), }, + { + name: "periodic/otlp-grpc-good-ca-certificate", + reader: MetricReader{ + Periodic: &PeriodicMetricReader{ + Exporter: PushMetricExporter{ + OTLP: &OTLPMetric{ + Protocol: ptr("grpc"), + Endpoint: ptr("https://localhost:4317"), + Compression: ptr("gzip"), + Timeout: ptr(1000), + Certificate: ptr(filepath.Join("testdata", "ca.crt")), + }, + }, + }, + }, + wantReader: sdkmetric.NewPeriodicReader(otlpGRPCExporter), + }, + { + name: "periodic/otlp-grpc-bad-ca-certificate", + reader: MetricReader{ + Periodic: &PeriodicMetricReader{ + Exporter: PushMetricExporter{ + OTLP: &OTLPMetric{ + Protocol: ptr("grpc"), + Endpoint: ptr("https://localhost:4317"), + Compression: ptr("gzip"), + Timeout: ptr(1000), + Certificate: ptr(filepath.Join("testdata", "bad_cert.crt")), + }, + }, + }, + }, + wantErr: fmt.Errorf("could not create client tls credentials: %w", errors.New("credentials: failed to append certificates")), + }, { name: "periodic/otlp-grpc-exporter-no-endpoint", reader: MetricReader{ diff --git a/config/testdata/bad_cert.crt b/config/testdata/bad_cert.crt new file mode 100644 index 00000000000..dbbd2b8576f --- /dev/null +++ b/config/testdata/bad_cert.crt @@ -0,0 +1 @@ +This is intentionally not a PEM formatted cert file. diff --git a/config/testdata/ca.crt b/config/testdata/ca.crt new file mode 100644 index 00000000000..2272f84e64d --- /dev/null +++ b/config/testdata/ca.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNjCCAh4CCQC0I5IQT7eziDANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJB +VTESMBAGA1UECAwJQXVzdHJhbGlhMQ8wDQYDVQQHDAZTeWRuZXkxEjAQBgNVBAoM +CU15T3JnTmFtZTEVMBMGA1UEAwwMTXlDb21tb25OYW1lMB4XDTIyMDgwMzA0MTky +MVoXDTMyMDczMTA0MTkyMVowXTELMAkGA1UEBhMCQVUxEjAQBgNVBAgMCUF1c3Ry +YWxpYTEPMA0GA1UEBwwGU3lkbmV5MRIwEAYDVQQKDAlNeU9yZ05hbWUxFTATBgNV +BAMMDE15Q29tbW9uTmFtZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMhGP0dy3zvkdx9zI+/XVjPOWlER0OUp7Sgzidc3nLOk42+bH4ofIVNtOFVqlNKi +O1bImu238VdBhd6R5IZZ1ZdIMcCeDgSJYu2X9wA3m4PKz8IdXo5ly2OHghhmCvqG +WxgqDj5wPXiczQwuf1EcDMtRWbXJ6Z/XH1U68R/kRdNLkiZ2LwtjoQpis5XYckLL +CrdF+AL6GeDIe0Mh9QGs26Vux+2kvaOGNUWRPE6Wt4GkqyKqmzYfR9HbflJ4xHT2 +I+jE1lg+jMBeom7z8Z90RE4GGcHjO+Vens/88r5EAjTnFj1Kb5gL2deSHY1m/++R +Z/kRyg+zQJyw4fAzlAA4+VkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAM3gRdTKX +eGwGYVmmKqA2vTxeigQYLHml7OSopcWj2wJfxfp49HXPRuvgpQn9iubxO3Zmhd83 +2X1E+T0A8oy5CfxgpAhHb3lY0jm3TjKXm6m+dSODwL3uND8tX+SqR8sRTFxPvPuo +pmvhdTZoRI3EzIiHLTgCuSU25JNP/vrVoKk0JvCkDYTU/WcVfj0v95DTMoWR4JGz +mtBwrgD0EM2XRw5ZMc7sMPli1gqmCbCQUrDZ+rPB78WDCBILBd8Cz75qYTUp98BY +akJyBckdJHAdyEQYDKa9HpmpexOO7IhSXCTEN1DEBgpZgEi/lBDRG/b0OzenUUgt +LUABtWt3pNQ9HA== +-----END CERTIFICATE----- diff --git a/config/trace.go b/config/trace.go index 1b08b2c56ae..38e77f0dc5e 100644 --- a/config/trace.go +++ b/config/trace.go @@ -17,6 +17,7 @@ import ( sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace/noop" + "google.golang.org/grpc/credentials" ) func tracerProvider(cfg configOptions, res *resource.Resource) (trace.TracerProvider, shutdownFunc, error) { @@ -108,6 +109,14 @@ func otlpGRPCSpanExporter(ctx context.Context, otlpConfig *OTLP) (sdktrace.SpanE if u.Scheme == "http" { opts = append(opts, otlptracegrpc.WithInsecure()) } + + if otlpConfig.Certificate != nil { + creds, err := credentials.NewClientTLSFromFile(*otlpConfig.Certificate, "") + if err != nil { + return nil, fmt.Errorf("could not create client tls credentials: %w", err) + } + opts = append(opts, otlptracegrpc.WithTLSCredentials(creds)) + } } if otlpConfig.Compression != nil { diff --git a/config/trace_test.go b/config/trace_test.go index fb6e9b14cdc..80c3a91ac41 100644 --- a/config/trace_test.go +++ b/config/trace_test.go @@ -6,7 +6,9 @@ package config import ( "context" "errors" + "fmt" "net/url" + "path/filepath" "reflect" "testing" @@ -261,6 +263,40 @@ func TestSpanProcessor(t *testing.T) { }, wantProcessor: sdktrace.NewBatchSpanProcessor(otlpGRPCExporter), }, + { + name: "batch/otlp-grpc-good-ca-certificate", + processor: SpanProcessor{ + Batch: &BatchSpanProcessor{ + Exporter: SpanExporter{ + OTLP: &OTLP{ + Protocol: ptr("grpc"), + Endpoint: ptr("localhost:4317"), + Compression: ptr("gzip"), + Timeout: ptr(1000), + Certificate: ptr(filepath.Join("testdata", "ca.crt")), + }, + }, + }, + }, + wantProcessor: sdktrace.NewBatchProcessor(otlpGRPCExporter), + }, + { + name: "batch/otlp-grpc-bad-ca-certificate", + processor: SpanProcessor{ + Batch: &BatchSpanProcessor{ + Exporter: SpanExporter{ + OTLP: &OTLP{ + Protocol: ptr("grpc"), + Endpoint: ptr("localhost:4317"), + Compression: ptr("gzip"), + Timeout: ptr(1000), + Certificate: ptr(filepath.Join("testdata", "bad_cert.crt")), + }, + }, + }, + }, + wantErr: fmt.Errorf("could not create client tls credentials: %w", errors.New("credentials: failed to append certificates")), + }, { name: "batch/otlp-grpc-exporter-no-scheme", processor: SpanProcessor{