Skip to content

Commit aa210f8

Browse files
authored
Add watcher for upstreams TLS certificates (observatorium#716)
* Add watcher to TLS certificates Signed-off-by: Ruben Vargas <[email protected]> * Fix CA loading logic Signed-off-by: Ruben Vargas <[email protected]> * Add some comments, change parameters order Signed-off-by: Ruben Vargas <[email protected]> * Fix some comments and clarify some names Signed-off-by: Ruben Vargas <[email protected]> --------- Signed-off-by: Ruben Vargas <[email protected]>
1 parent f50a799 commit aa210f8

File tree

13 files changed

+772
-121
lines changed

13 files changed

+772
-121
lines changed

Diff for: README.md

+6
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ Usage of ./observatorium-api:
113113
File containing the TLS client certificates to authenticate against upstream logs servers. Leave blank to disable mTLS.
114114
-logs.tls.key-file string
115115
File containing the TLS client key to authenticate against upstream logs servers. Leave blank to disable mTLS.
116+
-logs.tls.watch-certs
117+
Watch for certificate changes and reload
116118
-logs.write-timeout duration
117119
The HTTP write timeout for proxied requests to the logs endpoint. (default 10m0s)
118120
-logs.write.endpoint string
@@ -133,6 +135,8 @@ Usage of ./observatorium-api:
133135
File containing the TLS client certificates to authenticate against upstream logs servers. Leave blank to disable mTLS.
134136
-metrics.tls.key-file string
135137
File containing the TLS client key to authenticate against upstream metrics servers. Leave blank to disable mTLS.
138+
-metrics.tls.watch-certs
139+
Watch for certificate changes and reload
136140
-metrics.write-timeout duration
137141
The HTTP write timeout for proxied requests to the metrics endpoint. (default 2m0s)
138142
-metrics.write.endpoint string
@@ -193,6 +197,8 @@ Usage of ./observatorium-api:
193197
File containing the TLS client certificates to authenticate against upstream logs servers. Leave blank to disable mTLS.
194198
-traces.tls.key-file string
195199
File containing the TLS client key to authenticate against upstream traces servers. Leave blank to disable mTLS.
200+
-traces.tls.watch-certs
201+
Watch for certificate changes and reload
196202
-traces.write-timeout duration
197203
The HTTP write timeout for proxied requests to the traces endpoint. (default 2m0s)
198204
-traces.write.otlpgrpc.endpoint string

Diff for: api/logs/v1/http.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
package http
33

44
import (
5-
stdtls "crypto/tls"
65
"net"
76
"net/http"
87
"net/http/httputil"
@@ -147,7 +146,7 @@ func (n nopInstrumentHandler) NewHandler(labels prometheus.Labels, handler http.
147146
return handler.ServeHTTP
148147
}
149148

150-
func NewHandler(read, tail, write, rules *url.URL, rulesReadOnly bool, upstreamCA []byte, upstreamCert *stdtls.Certificate, opts ...HandlerOption) http.Handler {
149+
func NewHandler(read, tail, write, rules *url.URL, rulesReadOnly bool, tlsOptions *tls.UpstreamOptions, opts ...HandlerOption) http.Handler {
151150
c := &handlerConfiguration{
152151
logger: log.NewNopLogger(),
153152
registry: prometheus.NewRegistry(),
@@ -174,7 +173,7 @@ func NewHandler(read, tail, write, rules *url.URL, rulesReadOnly bool, upstreamC
174173
DialContext: (&net.Dialer{
175174
Timeout: dialTimeout,
176175
}).DialContext,
177-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
176+
TLSClientConfig: tlsOptions.NewClientConfig(),
178177
}
179178

180179
proxyRead = &httputil.ReverseProxy{
@@ -250,7 +249,7 @@ func NewHandler(read, tail, write, rules *url.URL, rulesReadOnly bool, upstreamC
250249
DialContext: (&net.Dialer{
251250
Timeout: dialTimeout,
252251
}).DialContext,
253-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
252+
TLSClientConfig: tlsOptions.NewClientConfig(),
254253
}
255254

256255
proxyReadRules = &httputil.ReverseProxy{
@@ -350,7 +349,7 @@ func NewHandler(read, tail, write, rules *url.URL, rulesReadOnly bool, upstreamC
350349
DialContext: (&net.Dialer{
351350
Timeout: dialTimeout,
352351
}).DialContext,
353-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
352+
TLSClientConfig: tlsOptions.NewClientConfig(),
354353
}
355354

356355
tailRead = &httputil.ReverseProxy{
@@ -386,7 +385,7 @@ func NewHandler(read, tail, write, rules *url.URL, rulesReadOnly bool, upstreamC
386385
DialContext: (&net.Dialer{
387386
Timeout: dialTimeout,
388387
}).DialContext,
389-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
388+
TLSClientConfig: tlsOptions.NewClientConfig(),
390389
}
391390

392391
proxyWrite = &httputil.ReverseProxy{

Diff for: api/metrics/legacy/http.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package legacy
22

33
import (
4-
stdtls "crypto/tls"
54
"net"
65
"net/http"
76
"net/http/httputil"
@@ -102,7 +101,7 @@ func (n nopInstrumentHandler) NewHandler(_ prometheus.Labels, handler http.Handl
102101
return handler.ServeHTTP
103102
}
104103

105-
func NewHandler(url *url.URL, upstreamCA []byte, upstreamCert *stdtls.Certificate, opts ...HandlerOption) http.Handler {
104+
func NewHandler(url *url.URL, tlsOptions *tls.UpstreamOptions, opts ...HandlerOption) http.Handler {
106105
c := &handlerConfiguration{
107106
logger: log.NewNopLogger(),
108107
registry: prometheus.NewRegistry(),
@@ -130,7 +129,7 @@ func NewHandler(url *url.URL, upstreamCA []byte, upstreamCert *stdtls.Certificat
130129
DialContext: (&net.Dialer{
131130
Timeout: dialTimeout,
132131
}).DialContext,
133-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
132+
TLSClientConfig: tlsOptions.NewClientConfig(),
134133
}
135134

136135
legacyProxy = &httputil.ReverseProxy{

Diff for: api/metrics/v1/http.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package v1
22

33
import (
4-
stdtls "crypto/tls"
54
"net"
65
"net/http"
76
"net/http/httputil"
@@ -174,7 +173,7 @@ type Endpoints struct {
174173

175174
// NewHandler creates the new metrics v1 handler.
176175
// nolint:funlen
177-
func NewHandler(endpoints Endpoints, upstreamCA []byte, upstreamCert *stdtls.Certificate, opts ...HandlerOption) http.Handler {
176+
func NewHandler(endpoints Endpoints, tlsOptions *tls.UpstreamOptions, opts ...HandlerOption) http.Handler {
178177
c := &handlerConfiguration{
179178
logger: log.NewNopLogger(),
180179
registry: prometheus.NewRegistry(),
@@ -258,7 +257,7 @@ func NewHandler(endpoints Endpoints, upstreamCA []byte, upstreamCert *stdtls.Cer
258257
DialContext: (&net.Dialer{
259258
Timeout: dialTimeout,
260259
}).DialContext,
261-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
260+
TLSClientConfig: tlsOptions.NewClientConfig(),
262261
}
263262

264263
proxyRead = &httputil.ReverseProxy{
@@ -345,7 +344,7 @@ func NewHandler(endpoints Endpoints, upstreamCA []byte, upstreamCert *stdtls.Cer
345344
)
346345

347346
t := http.DefaultTransport.(*http.Transport)
348-
t.TLSClientConfig = tls.NewClientConfig(upstreamCA, upstreamCert)
347+
t.TLSClientConfig = tlsOptions.NewClientConfig()
349348

350349
uiProxy = &httputil.ReverseProxy{
351350
Director: middlewares,
@@ -384,7 +383,7 @@ func NewHandler(endpoints Endpoints, upstreamCA []byte, upstreamCert *stdtls.Cer
384383
DialContext: (&net.Dialer{
385384
Timeout: dialTimeout,
386385
}).DialContext,
387-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
386+
TLSClientConfig: tlsOptions.NewClientConfig(),
388387
}
389388

390389
proxyWrite = &httputil.ReverseProxy{
@@ -469,7 +468,7 @@ func NewHandler(endpoints Endpoints, upstreamCA []byte, upstreamCert *stdtls.Cer
469468
DialContext: (&net.Dialer{
470469
Timeout: dialTimeout,
471470
}).DialContext,
472-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
471+
TLSClientConfig: tlsOptions.NewClientConfig(),
473472
}
474473

475474
proxyAlertmanager = &httputil.ReverseProxy{

Diff for: api/traces/v1/api.go

+7-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package v1
22

33
import (
44
"context"
5-
stdtls "crypto/tls"
65
"time"
76

87
"github.com/go-kit/log"
@@ -18,9 +17,8 @@ import (
1817
const TraceRoute = "/opentelemetry.proto.collector.trace.v1.TraceService/Export"
1918

2019
type connOptions struct {
21-
logger log.Logger
22-
tracesUpstreamCert *stdtls.Certificate
23-
tracesUpstreamCA []byte
20+
logger log.Logger
21+
tlsOptions *tls.UpstreamOptions
2422
}
2523

2624
// ClientOption modifies the connection's configuration.
@@ -33,15 +31,14 @@ func WithLogger(logger log.Logger) ClientOption {
3331
}
3432
}
3533

36-
func WithUpstreamTLS(tracesUpstreamCA []byte, tracesUpstreamCert *stdtls.Certificate) ClientOption {
34+
func WithUpstreamTLSOptions(tlsOptions *tls.UpstreamOptions) ClientOption {
3735
return func(h *connOptions) {
38-
h.tracesUpstreamCA = tracesUpstreamCA
39-
h.tracesUpstreamCert = tracesUpstreamCert
36+
h.tlsOptions = tlsOptions
4037
}
4138
}
4239

43-
func newCredentials(upstreamCA []byte, upstreamCert *stdtls.Certificate) credentials.TransportCredentials {
44-
tlsConfig := tls.NewClientConfig(upstreamCA, upstreamCert)
40+
func newCredentials(tlsOptions *tls.UpstreamOptions) credentials.TransportCredentials {
41+
tlsConfig := tlsOptions.NewClientConfig()
4542
if tlsConfig == nil {
4643
return insecure.NewCredentials()
4744
}
@@ -70,5 +67,5 @@ func NewOTelConnection(write string, opts ...ClientOption) (*grpc.ClientConn, er
7067
// because the codec we need to register is also deprecated. A better fix, is the newer
7168
// version of mwitkow/grpc-proxy, but that version doesn't (currently) work with OTel protocol.
7269
grpc.WithCodec(grpcproxy.Codec()), // nolint: staticcheck
73-
grpc.WithTransportCredentials(newCredentials(c.tracesUpstreamCA, c.tracesUpstreamCert)))
70+
grpc.WithTransportCredentials(newCredentials(c.tlsOptions)))
7471
}

Diff for: api/traces/v1/http.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"compress/flate"
66
"compress/gzip"
7-
stdtls "crypto/tls"
87
"fmt"
98
"io"
109
"net"
@@ -109,7 +108,7 @@ func (n nopInstrumentHandler) NewHandler(labels prometheus.Labels, handler http.
109108
// The web UI handler is able to rewrite
110109
// HTML to change the <base> attribute so that it works with the Observatorium-style
111110
// "/api/v1/traces/{tenant}/" URLs.
112-
func NewV2Handler(read *url.URL, readTemplate string, tempo *url.URL, writeOTLPHttp *url.URL, upstreamCA []byte, upstreamCert *stdtls.Certificate, opts ...HandlerOption) http.Handler {
111+
func NewV2Handler(read *url.URL, readTemplate string, tempo *url.URL, writeOTLPHttp *url.URL, tlsOptions *tls.UpstreamOptions, opts ...HandlerOption) http.Handler {
113112

114113
if read == nil && readTemplate == "" && tempo == nil {
115114
panic("missing Jaeger read url")
@@ -152,7 +151,7 @@ func NewV2Handler(read *url.URL, readTemplate string, tempo *url.URL, writeOTLPH
152151
DialContext: (&net.Dialer{
153152
Timeout: dialTimeout,
154153
}).DialContext,
155-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
154+
TLSClientConfig: tlsOptions.NewClientConfig(),
156155
}
157156

158157
proxyRead = &httputil.ReverseProxy{
@@ -203,7 +202,7 @@ func NewV2Handler(read *url.URL, readTemplate string, tempo *url.URL, writeOTLPH
203202
DialContext: (&net.Dialer{
204203
Timeout: dialTimeout,
205204
}).DialContext,
206-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
205+
TLSClientConfig: tlsOptions.NewClientConfig(),
207206
}
208207

209208
proxyOTLP := &httputil.ReverseProxy{
@@ -229,7 +228,7 @@ func NewV2Handler(read *url.URL, readTemplate string, tempo *url.URL, writeOTLPH
229228
DialContext: (&net.Dialer{
230229
Timeout: dialTimeout,
231230
}).DialContext,
232-
TLSClientConfig: tls.NewClientConfig(upstreamCA, upstreamCert),
231+
TLSClientConfig: tlsOptions.NewClientConfig(),
233232
}
234233

235234
middlewares := proxy.Middlewares(

Diff for: go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ require (
3535
github.com/prometheus/common v0.53.0
3636
github.com/prometheus/prometheus v0.50.1
3737
github.com/redis/rueidis v1.0.37
38+
github.com/stretchr/testify v1.9.0
3839
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0
3940
go.opentelemetry.io/contrib/propagators/jaeger v1.28.0
4041
go.opentelemetry.io/otel v1.28.0
@@ -159,7 +160,6 @@ require (
159160
github.com/schollz/closestmatch v2.1.0+incompatible // indirect
160161
github.com/sirupsen/logrus v1.9.3 // indirect
161162
github.com/spf13/pflag v1.0.5 // indirect
162-
github.com/stretchr/testify v1.9.0 // indirect
163163
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
164164
github.com/tdewolff/minify/v2 v2.12.9 // indirect
165165
github.com/tdewolff/parse/v2 v2.6.8 // indirect

0 commit comments

Comments
 (0)