@@ -6,6 +6,9 @@ package targetallocator // import "github.com/open-telemetry/opentelemetry-colle
6
6
import (
7
7
"bytes"
8
8
"context"
9
+ "crypto/tls"
10
+ "crypto/x509"
11
+ "errors"
9
12
"fmt"
10
13
"hash/fnv"
11
14
"io"
@@ -66,6 +69,16 @@ func (m *Manager) Start(ctx context.Context, host component.Host, sm *scrape.Man
66
69
m .settings .Logger .Error ("Failed to create http client" , zap .Error (err ))
67
70
return err
68
71
}
72
+
73
+ if base , ok := httpClient .Transport .(* http.Transport ); ok {
74
+ httpClient .Transport = & dynamicTLSRoundTripper {
75
+ base : base ,
76
+ cfg : m .cfg ,
77
+ }
78
+ } else {
79
+ return errors .New ("unexpected transport type" )
80
+ }
81
+
69
82
m .settings .Logger .Info ("Starting target allocator discovery" )
70
83
// immediately sync jobs, not waiting for the first tick
71
84
savedHash , err := m .sync (uint64 (0 ), httpClient )
@@ -97,8 +110,65 @@ func (m *Manager) Shutdown() {
97
110
close (m .shutdown )
98
111
}
99
112
100
- // sync request jobs from targetAllocator and update underlying receiver, if the response does not match the provided compareHash.
101
- // baseDiscoveryCfg can be used to provide additional ScrapeConfigs which will be added to the retrieved jobs.
113
+ type dynamicTLSRoundTripper struct {
114
+ base * http.Transport
115
+ cfg * Config
116
+ }
117
+
118
+ func (d * dynamicTLSRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
119
+ tlsCfg , err := createDynamicTLSConfig (d .cfg )
120
+ if err != nil {
121
+ return nil , fmt .Errorf ("failed to create dynamic TLS config: %w" , err )
122
+ }
123
+ clone := d .base .Clone ()
124
+ clone .TLSClientConfig = tlsCfg
125
+ return clone .RoundTrip (req )
126
+ }
127
+
128
+ func createDynamicTLSConfig (cfg * Config ) (* tls.Config , error ) {
129
+ tlsCfg := & tls.Config {
130
+ InsecureSkipVerify : cfg .TLSSetting .InsecureSkipVerify ,
131
+ ServerName : cfg .TLSSetting .ServerName ,
132
+ }
133
+
134
+ tlsCfg .GetCertificate = func (clientHello * tls.ClientHelloInfo ) (* tls.Certificate , error ) {
135
+ cert , err := tls .LoadX509KeyPair (cfg .TLSSetting .CertFile , cfg .TLSSetting .KeyFile )
136
+ if err != nil {
137
+ return nil , fmt .Errorf ("failed to load client certificate and key: %w" , err )
138
+ }
139
+ return & cert , nil
140
+ }
141
+
142
+ if cfg .TLSSetting .CAFile != "" {
143
+ caBytes , err := os .ReadFile (cfg .TLSSetting .CAFile )
144
+ if err != nil {
145
+ return nil , fmt .Errorf ("failed to read CA file: %w" , err )
146
+ }
147
+ caPool := x509 .NewCertPool ()
148
+ if ok := caPool .AppendCertsFromPEM (caBytes ); ! ok {
149
+ return nil , fmt .Errorf ("failed to append CA certs from %s" , cfg .TLSSetting .CAFile )
150
+ }
151
+ tlsCfg .RootCAs = caPool
152
+ }
153
+
154
+ if cfg .TLSSetting .MinVersion != "" {
155
+ minVersion , err := convertTLSVersion (cfg .TLSSetting .MinVersion )
156
+ if err != nil {
157
+ return nil , err
158
+ }
159
+ tlsCfg .MinVersion = uint16 (minVersion )
160
+ }
161
+ if cfg .TLSSetting .MaxVersion != "" {
162
+ maxVersion , err := convertTLSVersion (cfg .TLSSetting .MaxVersion )
163
+ if err != nil {
164
+ return nil , err
165
+ }
166
+ tlsCfg .MaxVersion = uint16 (maxVersion )
167
+ }
168
+
169
+ return tlsCfg , nil
170
+ }
171
+
102
172
func (m * Manager ) sync (compareHash uint64 , httpClient * http.Client ) (uint64 , error ) {
103
173
m .settings .Logger .Debug ("Syncing target allocator jobs" )
104
174
m .settings .Logger .Debug ("endpoint" , zap .String ("endpoint" , m .cfg .Endpoint ))
0 commit comments