From 12d9e48bb5ea848e6c1aa31520a576eec42c3205 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 15 Nov 2023 15:05:47 -0500 Subject: [PATCH] Wiring through Tracing.TLSCertPath from TOML config (#237) * feature/tracing-credentials: wiring through Tracing.TLSCertPath from TOML config * feature/tracing-credentials: removing parse of TLSCertPath before SetupTracing * feature/tracing-credentials: adding ErrIncluded to pkg/config/error.go * feature/tracing-credentials: lint * feature/tracing-credentials: removing ErrIncluded to match core --- pkg/loop/config.go | 9 ++++++ pkg/loop/config_test.go | 8 +++++ pkg/loop/internal/test/fixtures/client.pem | 21 +++++++++++++ pkg/loop/server.go | 3 +- pkg/loop/telem.go | 34 +++++++++++++--------- 5 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 pkg/loop/internal/test/fixtures/client.pem diff --git a/pkg/loop/config.go b/pkg/loop/config.go index 6179f3759..180c3d7a2 100644 --- a/pkg/loop/config.go +++ b/pkg/loop/config.go @@ -14,6 +14,7 @@ const ( envTracingCollectorTarget = "CL_TRACING_COLLECTOR_TARGET" envTracingSamplingRatio = "CL_TRACING_SAMPLING_RATIO" envTracingAttribute = "CL_TRACING_ATTRIBUTE_" + envTracingTLSCertPath = "CL_TRACING_TLS_CERT_PATH" ) // EnvConfig is the configuration between the application and the LOOP executable. The values @@ -24,6 +25,7 @@ type EnvConfig struct { TracingEnabled bool TracingCollectorTarget string TracingSamplingRatio float64 + TracingTLSCertPath string TracingAttributes map[string]string } @@ -34,6 +36,7 @@ func (e *EnvConfig) AsCmdEnv() (env []string) { envTracingEnabled: strconv.FormatBool(e.TracingEnabled), envTracingCollectorTarget: e.TracingCollectorTarget, envTracingSamplingRatio: strconv.FormatFloat(e.TracingSamplingRatio, 'f', -1, 64), + envTracingTLSCertPath: e.TracingTLSCertPath, } for k, v := range e.TracingAttributes { @@ -67,6 +70,7 @@ func (e *EnvConfig) parse() error { } e.TracingAttributes = getTracingAttributes() e.TracingSamplingRatio = getTracingSamplingRatio() + e.TracingTLSCertPath = getTLSCertPath() } return nil } @@ -114,3 +118,8 @@ func getTracingSamplingRatio() float64 { } return samplingRatio } + +// getTLSCertPath parses the CL_TRACING_TLS_CERT_PATH environment variable. +func getTLSCertPath() string { + return os.Getenv(envTracingTLSCertPath) +} diff --git a/pkg/loop/config_test.go b/pkg/loop/config_test.go index 2f6f5edf9..46bd8e5b1 100644 --- a/pkg/loop/config_test.go +++ b/pkg/loop/config_test.go @@ -18,6 +18,7 @@ func TestEnvConfig_parse(t *testing.T) { expectedTracingEnabled bool expectedTracingCollectorTarget string expectedTracingSamplingRatio float64 + expectedTracingTLSCertPath string }{ { name: "All variables set correctly", @@ -26,6 +27,7 @@ func TestEnvConfig_parse(t *testing.T) { envTracingEnabled: "true", envTracingCollectorTarget: "some:target", envTracingSamplingRatio: "1.0", + envTracingTLSCertPath: "internal/test/fixtures/client.pem", envTracingAttribute + "XYZ": "value", }, expectError: false, @@ -33,6 +35,7 @@ func TestEnvConfig_parse(t *testing.T) { expectedTracingEnabled: true, expectedTracingCollectorTarget: "some:target", expectedTracingSamplingRatio: 1.0, + expectedTracingTLSCertPath: "internal/test/fixtures/client.pem", }, { name: "CL_PROMETHEUS_PORT parse error", @@ -80,6 +83,9 @@ func TestEnvConfig_parse(t *testing.T) { if config.TracingSamplingRatio != tc.expectedTracingSamplingRatio { t.Errorf("Expected tracingSamplingRatio %f, got %f", tc.expectedTracingSamplingRatio, config.TracingSamplingRatio) } + if config.TracingTLSCertPath != tc.expectedTracingTLSCertPath { + t.Errorf("Expected tracingTLSCertPath %s, got %s", tc.expectedTracingTLSCertPath, config.TracingTLSCertPath) + } } } }) @@ -92,6 +98,7 @@ func TestEnvConfig_AsCmdEnv(t *testing.T) { TracingEnabled: true, TracingCollectorTarget: "http://localhost:9000", TracingSamplingRatio: 0.1, + TracingTLSCertPath: "some/path", TracingAttributes: map[string]string{"key": "value"}, } got := map[string]string{} @@ -105,5 +112,6 @@ func TestEnvConfig_AsCmdEnv(t *testing.T) { assert.Equal(t, "true", got[envTracingEnabled]) assert.Equal(t, "http://localhost:9000", got[envTracingCollectorTarget]) assert.Equal(t, "0.1", got[envTracingSamplingRatio]) + assert.Equal(t, "some/path", got[envTracingTLSCertPath]) assert.Equal(t, "value", got[envTracingAttribute+"key"]) } diff --git a/pkg/loop/internal/test/fixtures/client.pem b/pkg/loop/internal/test/fixtures/client.pem new file mode 100644 index 000000000..ffaf109d6 --- /dev/null +++ b/pkg/loop/internal/test/fixtures/client.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkUCFBWaCxtTkzg5N8q3l5UnhP1jhTwJMA0GCSqGSIb3DQEBCwUAMGsx +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTELMAkGA1UEBwwCTlkxEjAQBgNVBAoM +CUNoYWlubGluazEUMBIGA1UECwwLRm91bmRhdGlvbnMxGDAWBgNVBAMMD3JlbGF5 +LXVuaXQtdGVzdDAeFw0yMzExMTQwNjQ5MThaFw0zMzExMTEwNjQ5MThaMGsxCzAJ +BgNVBAYTAlVTMQswCQYDVQQIDAJOWTELMAkGA1UEBwwCTlkxEjAQBgNVBAoMCUNo +YWlubGluazEUMBIGA1UECwwLRm91bmRhdGlvbnMxGDAWBgNVBAMMD3JlbGF5LXVu +aXQtdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRrqwBi+MiR +ORHbef25DPrbpnE/pjDIs/2xov7F2BQLKQectBfkhJHn5A0sWo5xgAD+bdOThlMv +T1cE1PEoODKxXVEW1c5otNjwzOc7O4WAed1ObgaQbZ1Fd9U8aZqVZ4Ncebd7Lahm +Vh3yDuB3wu9GLOijXWKicPpKR8iIqh/ScOAvWZ9pJhUn/27U5rz953Lu7p8zwzQp +FjvuJXFZuv3gHeMi8DHoF0WF7+brgMpIdUb832jS8jL1A3s5D4gqAcBWJXdsaSi2 +yBf1gMNfC06XEcpcDrT8R6oko8F4pnY04mSbv4kOYrrJQ/Y8EmadAxHOdTQLBzBg +sX3c6BCFFT0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAKu5NxM7EpqoYmngMGp0z +u8RLketLZ2wNCZYy2As2zyrK1HGaJnPAywvn1ACLDl89lHJWp5swrd7H9YcXr3GN +rz/eIrpJD/9/wx3Rt8srjxFbeUt5a24NzoJ8obZJ4MJ1sEqMjl5Ngi+R2WMKdEiF +MMJ2USxHvm1R+vSkAjrM9NEPESMv0x42TciM7QagqWA+J2Tp/CUHiWczneLq/y1g +Cd3rzT3QCeEtlPe+OOOkmz01ZPzT0z6tTa20r8a4mE5/cxAIK2VaRviJw/Goupl8 +MXVKxpcIf1eKfULnQLvMwIKhSP9Y6EKK0aVqmOZSSyhXAgdPZmdP14UxfVVDPzmZ +hQ== +-----END CERTIFICATE----- diff --git a/pkg/loop/server.go b/pkg/loop/server.go index 667ae684b..f2c9e9787 100644 --- a/pkg/loop/server.go +++ b/pkg/loop/server.go @@ -71,8 +71,9 @@ func (s *Server) start() error { if err := SetupTracing(TracingConfig{ Enabled: envCfg.TracingEnabled, CollectorTarget: envCfg.TracingCollectorTarget, - NodeAttributes: envCfg.TracingAttributes, SamplingRatio: envCfg.TracingSamplingRatio, + TLSCertPath: envCfg.TracingTLSCertPath, + NodeAttributes: envCfg.TracingAttributes, OnDialError: func(err error) { s.Logger.Errorw("Failed to dial", "err", err) }, }); err != nil { // non blocking to server start diff --git a/pkg/loop/telem.go b/pkg/loop/telem.go index 110256f25..ae11c362c 100644 --- a/pkg/loop/telem.go +++ b/pkg/loop/telem.go @@ -5,7 +5,6 @@ import ( "net" "os" "runtime/debug" - "time" grpcprom "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus" "github.com/prometheus/client_golang/prometheus" @@ -19,6 +18,7 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.17.0" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "github.com/smartcontractkit/chainlink-relay/pkg/loop/internal" @@ -39,6 +39,9 @@ type TracingConfig struct { // SamplingRatio is the ratio of traces to sample. 1.0 means sample all traces. SamplingRatio float64 + // TLSCertPath is the path to the TLS certificate to use when connecting to the collector. + TLSCertPath string + // OnDialError is called when the dialer fails, providing an opportunity to log. OnDialError func(error) } @@ -54,27 +57,32 @@ func NewGRPCOpts(registerer prometheus.Registerer) GRPCOpts { // SetupTracing initializes open telemetry with the provided config. // It sets the global trace provider and opens a connection to the configured collector. -// There is no transport security between the node and OTEL collector. -// While this is the case, it is recommended to only deploy nodes and the OTEL collector on the same network. -// TODO: BCF-2703 -func SetupTracing(config TracingConfig) error { +func SetupTracing(config TracingConfig) (err error) { if !config.Enabled { return nil } ctx := context.Background() - ctx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() + + var creds credentials.TransportCredentials + if config.TLSCertPath != "" { + creds, err = credentials.NewClientTLSFromFile(config.TLSCertPath, "") + if err != nil { + return err + } + } else { + creds = insecure.NewCredentials() + } conn, err := grpc.DialContext(ctx, config.CollectorTarget, - // Note the use of insecure transport here. TLS is recommended in production. - grpc.WithTransportCredentials(insecure.NewCredentials()), + // Note the potential use of insecure transport here. TLS is recommended in production. + grpc.WithTransportCredentials(creds), grpc.WithContextDialer(func(ctx context.Context, s string) (net.Conn, error) { - conn, err := net.Dial("tcp", s) - if err != nil { - config.OnDialError(err) + conn, err2 := net.Dial("tcp", s) + if err2 != nil { + config.OnDialError(err2) } - return conn, err + return conn, err2 })) if err != nil { return err