@@ -5,14 +5,34 @@ import (
55 "crypto/tls"
66 "crypto/x509"
77 "fmt"
8+ "strings"
89
910 "github.com/rancher-sandbox/runtime-enforcer/internal/tlsutil"
1011 "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
12+ "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
1113 otellog "go.opentelemetry.io/otel/log"
1214 sdklog "go.opentelemetry.io/otel/sdk/log"
1315 "google.golang.org/grpc/credentials"
1416)
1517
18+ type protocol string
19+
20+ const (
21+ protocolGRPC protocol = "grpc"
22+ protocolHTTPProtobuf protocol = "http/protobuf"
23+ )
24+
25+ func stringToProtocol (s string ) (protocol , error ) {
26+ switch s {
27+ case "grpc" :
28+ return protocolGRPC , nil
29+ case "http/protobuf" :
30+ return protocolHTTPProtobuf , nil
31+ default :
32+ return "" , fmt .Errorf ("unsupported protocol: %s" , s )
33+ }
34+ }
35+
1636func buildTLSConfig (caCertPath , clientCertPath , clientKeyPath string ) (* tls.Config , error ) {
1737 // Validate that the CA certificate is readable at startup.
1838 if _ , err := tlsutil .LoadCACertPool (caCertPath ); err != nil {
@@ -50,28 +70,72 @@ func buildTLSConfig(caCertPath, clientCertPath, clientKeyPath string) (*tls.Conf
5070 return cfg , nil
5171}
5272
53- // Init creates an OTEL log provider that exports violation events to the given
54- // gRPC endpoint over TLS. When caCertPath is non-empty, the connection verifies
55- // the collector's certificate against the provided CA; otherwise the system
56- // certificate pool is used. When clientCertPath and clientKeyPath are both
57- // non-empty, the client presents a TLS certificate for mTLS authentication.
58- func Init (
59- ctx context.Context ,
73+ func createGRPCExporter (ctx context.Context ,
6074 endpoint , caCertPath , clientCertPath , clientKeyPath string ,
61- ) (otellog.Logger , func (context.Context ) error , error ) {
75+ ) (sdklog.Exporter , error ) {
76+ // if the user specified the correct path we shouldn't receive the http prefix here, but just to be sure.
77+ gRPCEndpoint := strings .TrimPrefix (strings .TrimPrefix (endpoint , "https://" ), "http://" )
78+ insecure := caCertPath == ""
6279 opts := []otlploggrpc.Option {
63- otlploggrpc .WithEndpointURL ( endpoint ),
80+ otlploggrpc .WithEndpoint ( gRPCEndpoint ),
6481 }
65-
66- if caCertPath != "" {
82+ if insecure {
83+ opts = append (opts , otlploggrpc .WithInsecure ())
84+ } else {
6785 tlsConfig , err := buildTLSConfig (caCertPath , clientCertPath , clientKeyPath )
6886 if err != nil {
69- return nil , nil , err
87+ return nil , err
7088 }
7189 opts = append (opts , otlploggrpc .WithTLSCredentials (credentials .NewTLS (tlsConfig )))
7290 }
91+ return otlploggrpc .New (ctx , opts ... )
92+ }
93+
94+ func createHTTPExporter (ctx context.Context ,
95+ endpoint , caCertPath , clientCertPath , clientKeyPath string ,
96+ ) (sdklog.Exporter , error ) {
97+ // first we check if we are in insecure mode
98+ insecure := strings .HasPrefix (endpoint , "http://" )
99+ // Strip the scheme from the endpoint: WithEndpoint expects "host:port".
100+ httpEndpoint := strings .TrimPrefix (strings .TrimPrefix (endpoint , "https://" ), "http://" )
73101
74- exporter , err := otlploggrpc .New (ctx , opts ... )
102+ opts := []otlploghttp.Option {
103+ otlploghttp .WithEndpoint (httpEndpoint ),
104+ }
105+
106+ if insecure {
107+ opts = append (opts , otlploghttp .WithInsecure ())
108+ } else if caCertPath != "" {
109+ tlsConfig , err := buildTLSConfig (caCertPath , clientCertPath , clientKeyPath )
110+ if err != nil {
111+ return nil , err
112+ }
113+ opts = append (opts , otlploghttp .WithTLSClientConfig (tlsConfig ))
114+ }
115+ return otlploghttp .New (ctx , opts ... )
116+ }
117+
118+ // Init creates an OTEL log provider that exports violation events to the given
119+ // endpoint. The protocol can be either "grpc" or "http/protobuf".
120+ // When caCertPath is non-empty, the connection verifies the collector's
121+ // certificate against the provided CA; otherwise insecure mode is used.
122+ // When clientCertPath and clientKeyPath are both non-empty, the client
123+ // presents a TLS certificate for mTLS authentication.
124+ func Init (
125+ ctx context.Context ,
126+ endpoint , caCertPath , clientCertPath , clientKeyPath , protocol string ,
127+ ) (otellog.Logger , func (context.Context ) error , error ) {
128+ var exporter sdklog.Exporter
129+ proto , err := stringToProtocol (protocol )
130+ if err != nil {
131+ return nil , nil , err
132+ }
133+ switch proto {
134+ case protocolGRPC :
135+ exporter , err = createGRPCExporter (ctx , endpoint , caCertPath , clientCertPath , clientKeyPath )
136+ case protocolHTTPProtobuf :
137+ exporter , err = createHTTPExporter (ctx , endpoint , caCertPath , clientCertPath , clientKeyPath )
138+ }
75139 if err != nil {
76140 return nil , nil , fmt .Errorf ("failed to create OTLP log exporter: %w" , err )
77141 }
0 commit comments