@@ -18,6 +18,7 @@ import (
18
18
19
19
"github.com/elastic/elastic-agent-libs/logp"
20
20
"github.com/elastic/elastic-agent-libs/transport/httpcommon"
21
+ "github.com/elastic/elastic-agent-libs/transport/tlscommon"
21
22
"github.com/elastic/elastic-agent/internal/pkg/agent/application/actions"
22
23
"github.com/elastic/elastic-agent/internal/pkg/agent/application/coordinator"
23
24
"github.com/elastic/elastic-agent/internal/pkg/agent/application/info"
@@ -122,23 +123,33 @@ func (h *PolicyChangeHandler) Watch() <-chan coordinator.ConfigChange {
122
123
return h .ch
123
124
}
124
125
125
- func (h * PolicyChangeHandler ) validateFleetServerHosts (ctx context.Context , cfg * configuration. Configuration ) (* remote.Config , error ) {
126
+ func (h * PolicyChangeHandler ) validateFleetServerHosts (ctx context.Context , cfg * config. Config ) (* remote.Config , error ) {
126
127
// do not update fleet-server host from policy; no setters provided with local Fleet Server
127
128
if len (h .setters ) == 0 {
128
129
return nil , nil
129
130
}
130
131
131
- if clientEqual (h .config .Fleet .Client , cfg .Fleet .Client ) {
132
+ parsedConfig , err := configuration .NewPartialFromConfigNoDefaults (cfg )
133
+ if err != nil {
134
+ return nil , fmt .Errorf ("parsing fleet config: %w" , err )
135
+ }
136
+
137
+ if parsedConfig .Fleet == nil {
138
+ // there is no client config (weird)
139
+ return nil , nil
140
+ }
141
+
142
+ if clientEqual (h .config .Fleet .Client , parsedConfig .Fleet .Client ) {
132
143
// already the same hosts
133
144
return nil , nil
134
145
}
135
146
136
- // make a copy the current client config and apply the changes in place on this copy
147
+ // make a copy the current client config and apply the changes on this copy
137
148
newFleetClientConfig := h .config .Fleet .Client
138
- updateFleetConfig (h .log , cfg .Fleet .Client , & newFleetClientConfig )
149
+ updateFleetConfig (h .log , parsedConfig .Fleet .Client , & newFleetClientConfig )
139
150
140
151
// Test new config
141
- err : = testFleetConfig (ctx , h .log , newFleetClientConfig , h .config .Fleet .AccessAPIKey )
152
+ err = testFleetConfig (ctx , h .log , newFleetClientConfig , h .config .Fleet .AccessAPIKey )
142
153
if err != nil {
143
154
return nil , fmt .Errorf ("validating fleet client config: %w" , err )
144
155
}
@@ -175,52 +186,82 @@ func testFleetConfig(ctx context.Context, log *logger.Logger, clientConfig remot
175
186
return nil
176
187
}
177
188
178
- // updateFleetConfig copies the relevant Fleet client settings from src on dst. The destination struct is modified in-place
179
- func updateFleetConfig (log * logger.Logger , src remote.Config , dst * remote.Config ) {
180
- dst .Protocol = src .Protocol
181
- dst .Path = src .Path
182
- dst .Host = src .Host
183
- dst .Hosts = src .Hosts
189
+ // updateFleetConfig copies the relevant Fleet client settings from policyConfig on agentConfig. The destination struct is modified in-place
190
+ func updateFleetConfig (log * logger.Logger , policyConfig remote.Config , agentConfig * remote.Config ) {
191
+
192
+ // Hosts is the only connectivity field sent Fleet, let's clear everything else aside from Hosts
193
+ if len (policyConfig .Hosts ) > 0 {
194
+ agentConfig .Hosts = make ([]string , len (policyConfig .Hosts ))
195
+ copy (agentConfig .Hosts , policyConfig .Hosts )
196
+
197
+ agentConfig .Host = ""
198
+ agentConfig .Protocol = ""
199
+ agentConfig .Path = ""
200
+ }
184
201
185
202
// Empty proxies from fleet are ignored. That way a proxy set by --proxy-url
186
203
// it won't be overridden by an absent or empty proxy from fleet-server.
187
204
// However, if there is a proxy sent by fleet-server, it'll take precedence.
188
205
// Therefore, it's not possible to remove a proxy once it's set.
189
206
190
- if src .Transport .Proxy .URL == nil ||
191
- src .Transport .Proxy .URL .String () == "" {
192
- log .Debug ("proxy from fleet is empty or null, the proxy will not be changed" )
207
+ if policyConfig .Transport .Proxy .URL == nil ||
208
+ policyConfig .Transport .Proxy .URL .String () == "" {
209
+ log .Debugw ("proxy from fleet is empty or null, the proxy will not be changed" , "current_proxy" , agentConfig . Transport . Proxy . URL )
193
210
} else {
211
+ log .Debugw ("received proxy from fleet, applying it" , "old_proxy" , agentConfig .Transport .Proxy .URL , "new_proxy" , policyConfig .Transport .Proxy .URL )
194
212
// copy the proxy struct
195
- dst .Transport .Proxy = src .Transport .Proxy
213
+ agentConfig .Transport .Proxy = policyConfig .Transport .Proxy
196
214
197
- // replace in dst the attributes that are passed by reference within the proxy struct
215
+ // replace in agentConfig the attributes that are passed by reference within the proxy struct
198
216
199
217
// Headers map
200
- dst .Transport .Proxy .Headers = map [string ]string {}
201
- for k , v := range src .Transport .Proxy .Headers {
202
- dst .Transport .Proxy .Headers [k ] = v
218
+ agentConfig .Transport .Proxy .Headers = map [string ]string {}
219
+ for k , v := range policyConfig .Transport .Proxy .Headers {
220
+ agentConfig .Transport .Proxy .Headers [k ] = v
203
221
}
204
222
205
223
// Proxy URL
206
- urlCopy := * src .Transport .Proxy .URL
207
- dst .Transport .Proxy .URL = & urlCopy
224
+ urlCopy := * policyConfig .Transport .Proxy .URL
225
+ agentConfig .Transport .Proxy .URL = & urlCopy
226
+ }
227
+
228
+ if policyConfig .Transport .TLS != nil {
229
+
230
+ tlsCopy := tlscommon.Config {}
231
+ if agentConfig .Transport .TLS != nil {
232
+ // copy the TLS struct
233
+ tlsCopy = * agentConfig .Transport .TLS
234
+ }
235
+
236
+ if policyConfig .Transport .TLS .Certificate == emptyCertificateConfig () {
237
+ log .Debug ("TLS certificates from fleet are empty or null, the TLS config will not be changed" )
238
+ } else {
239
+ tlsCopy .Certificate = policyConfig .Transport .TLS .Certificate
240
+ log .Debug ("received TLS certificate/key from fleet, applying it" )
241
+ }
208
242
209
- log .Debug ("received proxy from fleet, applying it" )
243
+ if len (policyConfig .Transport .TLS .CAs ) == 0 {
244
+ log .Debug ("TLS CAs from fleet are empty or null, the TLS config will not be changed" )
245
+ } else {
246
+ tlsCopy .CAs = make ([]string , len (policyConfig .Transport .TLS .CAs ))
247
+ copy (tlsCopy .CAs , policyConfig .Transport .TLS .CAs )
248
+ log .Debug ("received TLS CAs from fleet, applying it" )
249
+ }
250
+
251
+ agentConfig .Transport .TLS = & tlsCopy
210
252
}
211
253
}
212
254
213
- func (h * PolicyChangeHandler ) handlePolicyChange (ctx context.Context , c * config.Config ) (err error ) {
214
- cfg , err := configuration .NewFromConfig (c )
215
- if err != nil {
216
- return errors .New (err , "could not parse the configuration from the policy" , errors .TypeConfig )
217
- }
255
+ func emptyCertificateConfig () tlscommon.CertificateConfig {
256
+ return tlscommon.CertificateConfig {}
257
+ }
218
258
259
+ func (h * PolicyChangeHandler ) handlePolicyChange (ctx context.Context , c * config.Config ) (err error ) {
219
260
var validationErr error
220
261
221
262
// validate Fleet connectivity with the new configuration
222
263
var validatedConfig * remote.Config
223
- validatedConfig , err = h .validateFleetServerHosts (ctx , cfg )
264
+ validatedConfig , err = h .validateFleetServerHosts (ctx , c )
224
265
if err != nil {
225
266
validationErr = goerrors .Join (validationErr , fmt .Errorf ("validating Fleet client config: %w" , err ))
226
267
}
@@ -355,6 +396,10 @@ func clientEqual(k1 remote.Config, k2 remote.Config) bool {
355
396
return false
356
397
}
357
398
399
+ if k1 .Host != k2 .Host {
400
+ return false
401
+ }
402
+
358
403
sort .Strings (k1 .Hosts )
359
404
sort .Strings (k2 .Hosts )
360
405
if len (k1 .Hosts ) != len (k2 .Hosts ) {
0 commit comments