/proc/self/cwd/test/config/utility.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "test/config/utility.h" |
2 | | |
3 | | #include "envoy/config/bootstrap/v3/bootstrap.pb.h" |
4 | | #include "envoy/config/cluster/v3/cluster.pb.h" |
5 | | #include "envoy/config/core/v3/base.pb.h" |
6 | | #include "envoy/config/endpoint/v3/endpoint.pb.h" |
7 | | #include "envoy/config/listener/v3/listener_components.pb.h" |
8 | | #include "envoy/config/route/v3/route_components.pb.h" |
9 | | #include "envoy/extensions/access_loggers/file/v3/file.pb.h" |
10 | | #include "envoy/extensions/filters/http/upstream_codec/v3/upstream_codec.pb.h" |
11 | | #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h" |
12 | | #include "envoy/extensions/transport_sockets/quic/v3/quic_transport.pb.h" |
13 | | #include "envoy/extensions/transport_sockets/tls/v3/cert.pb.h" |
14 | | #include "envoy/extensions/transport_sockets/tls/v3/common.pb.h" |
15 | | #include "envoy/http/codec.h" |
16 | | #include "envoy/service/discovery/v3/discovery.pb.h" |
17 | | |
18 | | #include "source/common/common/assert.h" |
19 | | #include "source/common/http/utility.h" |
20 | | #include "source/common/protobuf/utility.h" |
21 | | |
22 | | #include "test/config/integration/certs/client2cert_hash.h" |
23 | | #include "test/config/integration/certs/client_ecdsacert_hash.h" |
24 | | #include "test/config/integration/certs/clientcert_hash.h" |
25 | | #include "test/test_common/environment.h" |
26 | | #include "test/test_common/network_utility.h" |
27 | | #include "test/test_common/resources.h" |
28 | | #include "test/test_common/utility.h" |
29 | | |
30 | | #include "absl/strings/str_replace.h" |
31 | | #include "gtest/gtest.h" |
32 | | |
33 | | namespace Envoy { |
34 | | namespace { |
35 | | envoy::config::bootstrap::v3::Bootstrap& |
36 | 0 | basicBootstrap(envoy::config::bootstrap::v3::Bootstrap& bootstrap, const std::string& config) { |
37 | 0 | #ifdef ENVOY_ENABLE_YAML |
38 | 0 | TestUtility::loadFromYaml(config, bootstrap); |
39 | | #else |
40 | | UNREFERENCED_PARAMETER(config); |
41 | | UNREFERENCED_PARAMETER(bootstrap); |
42 | | PANIC("JSON compiled out: can't load config"); |
43 | | #endif |
44 | 0 | return bootstrap; |
45 | 0 | } |
46 | | } // namespace |
47 | | |
48 | 1.96k | std::string ConfigHelper::baseConfigNoListeners() { |
49 | 1.96k | return fmt::format(R"EOF( |
50 | 1.96k | admin: |
51 | 1.96k | access_log: |
52 | 1.96k | - name: envoy.access_loggers.file |
53 | 1.96k | typed_config: |
54 | 1.96k | "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog |
55 | 1.96k | path: "{}" |
56 | 1.96k | address: |
57 | 1.96k | socket_address: |
58 | 1.96k | address: 127.0.0.1 |
59 | 1.96k | port_value: 0 |
60 | 1.96k | dynamic_resources: |
61 | 1.96k | lds_config: |
62 | 1.96k | path_config_source: |
63 | 1.96k | path: {} |
64 | 1.96k | static_resources: |
65 | 1.96k | secrets: |
66 | 1.96k | - name: "secret_static_0" |
67 | 1.96k | tls_certificate: |
68 | 1.96k | certificate_chain: |
69 | 1.96k | inline_string: "DUMMY_INLINE_BYTES" |
70 | 1.96k | private_key: |
71 | 1.96k | inline_string: "DUMMY_INLINE_BYTES" |
72 | 1.96k | password: |
73 | 1.96k | inline_string: "DUMMY_INLINE_BYTES" |
74 | 1.96k | clusters: |
75 | 1.96k | name: cluster_0 |
76 | 1.96k | load_assignment: |
77 | 1.96k | cluster_name: cluster_0 |
78 | 1.96k | endpoints: |
79 | 1.96k | - lb_endpoints: |
80 | 1.96k | - endpoint: |
81 | 1.96k | address: |
82 | 1.96k | socket_address: |
83 | 1.96k | address: 127.0.0.1 |
84 | 1.96k | port_value: 0 |
85 | 1.96k | )EOF", |
86 | 1.96k | Platform::null_device_path, Platform::null_device_path); |
87 | 1.96k | } |
88 | | |
89 | 1.96k | std::string ConfigHelper::baseConfig(bool multiple_addresses) { |
90 | 1.96k | if (multiple_addresses) { |
91 | 0 | return absl::StrCat(baseConfigNoListeners(), R"EOF( |
92 | 0 | listeners: |
93 | 0 | - name: listener_0 |
94 | 0 | address: |
95 | 0 | socket_address: |
96 | 0 | address: 127.0.0.1 |
97 | 0 | port_value: 0 |
98 | 0 | additional_addresses: |
99 | 0 | - address: |
100 | 0 | socket_address: |
101 | 0 | address: 127.0.0.1 |
102 | 0 | port_value: 0 |
103 | 0 | )EOF"); |
104 | 0 | } |
105 | 1.96k | return absl::StrCat(baseConfigNoListeners(), R"EOF( |
106 | 1.96k | listeners: |
107 | 1.96k | - name: listener_0 |
108 | 1.96k | address: |
109 | 1.96k | socket_address: |
110 | 1.96k | address: 127.0.0.1 |
111 | 1.96k | port_value: 0 |
112 | 1.96k | )EOF"); |
113 | 1.96k | } |
114 | | |
115 | | std::string ConfigHelper::baseUdpListenerConfig(std::string listen_address, |
116 | 0 | bool multiple_addresses) { |
117 | 0 | std::string config = fmt::format(R"EOF( |
118 | 0 | admin: |
119 | 0 | access_log: |
120 | 0 | - name: envoy.access_loggers.file |
121 | 0 | typed_config: |
122 | 0 | "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog |
123 | 0 | path: "{}" |
124 | 0 | address: |
125 | 0 | socket_address: |
126 | 0 | address: 127.0.0.1 |
127 | 0 | port_value: 0 |
128 | 0 | static_resources: |
129 | 0 | clusters: |
130 | 0 | name: cluster_0 |
131 | 0 | load_assignment: |
132 | 0 | cluster_name: cluster_0 |
133 | 0 | endpoints: |
134 | 0 | - lb_endpoints: |
135 | 0 | - endpoint: |
136 | 0 | address: |
137 | 0 | socket_address: |
138 | 0 | address: 127.0.0.1 |
139 | 0 | port_value: 0 |
140 | 0 | )EOF", |
141 | 0 | Platform::null_device_path); |
142 | |
|
143 | 0 | if (multiple_addresses) { |
144 | 0 | return absl::StrCat(config, fmt::format(R"EOF( |
145 | 0 | listeners: |
146 | 0 | name: listener_0 |
147 | 0 | address: |
148 | 0 | socket_address: |
149 | 0 | address: {} |
150 | 0 | port_value: 0 |
151 | 0 | protocol: udp |
152 | 0 | additional_addresses: |
153 | 0 | - address: |
154 | 0 | socket_address: |
155 | 0 | address: {} |
156 | 0 | port_value: 0 |
157 | 0 | protocol: udp |
158 | 0 | )EOF", |
159 | 0 | listen_address, listen_address)); |
160 | 0 | } |
161 | 0 | return absl::StrCat(config, fmt::format(R"EOF( |
162 | 0 | listeners: |
163 | 0 | name: listener_0 |
164 | 0 | address: |
165 | 0 | socket_address: |
166 | 0 | address: {} |
167 | 0 | port_value: 0 |
168 | 0 | protocol: udp |
169 | 0 | )EOF", |
170 | 0 | listen_address)); |
171 | 0 | } |
172 | | |
173 | 0 | std::string ConfigHelper::tcpProxyConfig() { |
174 | 0 | return absl::StrCat(baseConfig(), R"EOF( |
175 | 0 | filter_chains: |
176 | 0 | filters: |
177 | 0 | name: tcp |
178 | 0 | typed_config: |
179 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy |
180 | 0 | stat_prefix: tcpproxy_stats |
181 | 0 | cluster: cluster_0 |
182 | 0 | )EOF"); |
183 | 0 | } |
184 | | |
185 | 0 | std::string ConfigHelper::startTlsConfig() { |
186 | 0 | return absl::StrCat( |
187 | 0 | tcpProxyConfig(), |
188 | 0 | fmt::format(R"EOF( |
189 | 0 | transport_socket: |
190 | 0 | name: "starttls" |
191 | 0 | typed_config: |
192 | 0 | "@type": type.googleapis.com/envoy.extensions.transport_sockets.starttls.v3.StartTlsConfig |
193 | 0 | cleartext_socket_config: |
194 | 0 | tls_socket_config: |
195 | 0 | common_tls_context: |
196 | 0 | tls_certificates: |
197 | 0 | certificate_chain: |
198 | 0 | filename: {} |
199 | 0 | private_key: |
200 | 0 | filename: {} |
201 | 0 | )EOF", |
202 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/servercert.pem"), |
203 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/serverkey.pem"))); |
204 | 0 | } |
205 | | |
206 | 0 | std::string ConfigHelper::testInspectorFilter() { |
207 | 0 | return R"EOF( |
208 | 0 | name: "envoy.filters.listener.test" |
209 | 0 | typed_config: |
210 | 0 | "@type": type.googleapis.com/test.integration.filters.TestInspectorFilterConfig |
211 | 0 | )EOF"; |
212 | 0 | } |
213 | | |
214 | 0 | std::string ConfigHelper::tlsInspectorFilter(bool enable_ja3_fingerprinting) { |
215 | 0 | if (!enable_ja3_fingerprinting) { |
216 | 0 | return R"EOF( |
217 | 0 | name: "envoy.filters.listener.tls_inspector" |
218 | 0 | typed_config: |
219 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector |
220 | 0 | )EOF"; |
221 | 0 | } |
222 | | |
223 | 0 | return R"EOF( |
224 | 0 | name: "envoy.filters.listener.tls_inspector" |
225 | 0 | typed_config: |
226 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector |
227 | 0 | enable_ja3_fingerprinting: true |
228 | 0 | )EOF"; |
229 | 0 | } |
230 | | |
231 | 1.96k | std::string ConfigHelper::httpProxyConfig(bool downstream_use_quic, bool multiple_addresses) { |
232 | 1.96k | if (downstream_use_quic) { |
233 | 0 | return quicHttpProxyConfig(multiple_addresses); |
234 | 0 | } |
235 | 1.96k | return absl::StrCat(baseConfig(multiple_addresses), fmt::format(R"EOF( |
236 | 1.96k | filter_chains: |
237 | 1.96k | filters: |
238 | 1.96k | name: http |
239 | 1.96k | typed_config: |
240 | 1.96k | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager |
241 | 1.96k | stat_prefix: config_test |
242 | 1.96k | delayed_close_timeout: |
243 | 1.96k | nanos: 10000000 |
244 | 1.96k | http_filters: |
245 | 1.96k | - name: envoy.filters.http.router |
246 | 1.96k | typed_config: |
247 | 1.96k | "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router |
248 | 1.96k | codec_type: HTTP1 |
249 | 1.96k | access_log: |
250 | 1.96k | name: accesslog |
251 | 1.96k | filter: |
252 | 1.96k | not_health_check_filter: {{}} |
253 | 1.96k | typed_config: |
254 | 1.96k | "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog |
255 | 1.96k | path: {} |
256 | 1.96k | route_config: |
257 | 1.96k | virtual_hosts: |
258 | 1.96k | name: integration |
259 | 1.96k | routes: |
260 | 1.96k | route: |
261 | 1.96k | cluster: cluster_0 |
262 | 1.96k | match: |
263 | 1.96k | prefix: "/" |
264 | 1.96k | domains: "*" |
265 | 1.96k | name: route_config_0 |
266 | 1.96k | )EOF", |
267 | 1.96k | Platform::null_device_path)); |
268 | 1.96k | } |
269 | | |
270 | | // TODO(danzh): For better compatibility with HTTP integration test framework, |
271 | | // it's better to combine with HTTP_PROXY_CONFIG, and use config modifiers to |
272 | | // specify quic specific things. |
273 | 0 | std::string ConfigHelper::quicHttpProxyConfig(bool multiple_addresses) { |
274 | 0 | return absl::StrCat(baseUdpListenerConfig("127.0.0.1", multiple_addresses), |
275 | 0 | fmt::format(R"EOF( |
276 | 0 | filter_chains: |
277 | 0 | transport_socket: |
278 | 0 | name: envoy.transport_sockets.quic |
279 | 0 | typed_config: |
280 | 0 | "@type": type.googleapis.com/envoy.extensions.transport_sockets.quic.v3.QuicDownstreamTransport |
281 | 0 | filters: |
282 | 0 | name: http |
283 | 0 | typed_config: |
284 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager |
285 | 0 | stat_prefix: config_test |
286 | 0 | http_filters: |
287 | 0 | - name: envoy.filters.http.router |
288 | 0 | typed_config: |
289 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router |
290 | 0 | codec_type: HTTP3 |
291 | 0 | access_log: |
292 | 0 | name: file_access_log |
293 | 0 | filter: |
294 | 0 | not_health_check_filter: {{}} |
295 | 0 | typed_config: |
296 | 0 | "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog |
297 | 0 | path: {} |
298 | 0 | route_config: |
299 | 0 | virtual_hosts: |
300 | 0 | name: integration |
301 | 0 | routes: |
302 | 0 | route: |
303 | 0 | cluster: cluster_0 |
304 | 0 | match: |
305 | 0 | prefix: "/" |
306 | 0 | domains: "*" |
307 | 0 | name: route_config_0 |
308 | 0 | udp_listener_config: |
309 | 0 | quic_options: {{}} |
310 | 0 | )EOF", |
311 | 0 | Platform::null_device_path)); |
312 | 0 | } |
313 | | |
314 | 0 | std::string ConfigHelper::defaultBufferFilter() { |
315 | 0 | return R"EOF( |
316 | 0 | name: buffer |
317 | 0 | typed_config: |
318 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer |
319 | 0 | max_request_bytes : 5242880 |
320 | 0 | )EOF"; |
321 | 0 | } |
322 | | |
323 | 0 | std::string ConfigHelper::smallBufferFilter() { |
324 | 0 | return R"EOF( |
325 | 0 | name: buffer |
326 | 0 | typed_config: |
327 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer |
328 | 0 | max_request_bytes : 1024 |
329 | 0 | )EOF"; |
330 | 0 | } |
331 | | |
332 | 0 | std::string ConfigHelper::defaultHealthCheckFilter() { |
333 | 0 | return R"EOF( |
334 | 0 | name: health_check |
335 | 0 | typed_config: |
336 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck |
337 | 0 | pass_through_mode: false |
338 | 0 | )EOF"; |
339 | 0 | } |
340 | | |
341 | 0 | std::string ConfigHelper::defaultSquashFilter() { |
342 | 0 | return R"EOF( |
343 | 0 | name: squash |
344 | 0 | typed_config: |
345 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.http.squash.v3.Squash |
346 | 0 | cluster: squash |
347 | 0 | attachment_template: |
348 | 0 | spec: |
349 | 0 | attachment: |
350 | 0 | env: "{{ SQUASH_ENV_TEST }}" |
351 | 0 | match_request: true |
352 | 0 | attachment_timeout: |
353 | 0 | seconds: 1 |
354 | 0 | nanos: 0 |
355 | 0 | attachment_poll_period: |
356 | 0 | seconds: 2 |
357 | 0 | nanos: 0 |
358 | 0 | request_timeout: |
359 | 0 | seconds: 1 |
360 | 0 | nanos: 0 |
361 | 0 | )EOF"; |
362 | 0 | } |
363 | | |
364 | 0 | std::string ConfigHelper::clustersNoListenerBootstrap(const std::string& api_type) { |
365 | 0 | return fmt::format( |
366 | 0 | R"EOF( |
367 | 0 | admin: |
368 | 0 | access_log: |
369 | 0 | - name: envoy.access_loggers.file |
370 | 0 | typed_config: |
371 | 0 | "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog |
372 | 0 | path: "{}" |
373 | 0 | address: |
374 | 0 | socket_address: |
375 | 0 | address: 127.0.0.1 |
376 | 0 | port_value: 0 |
377 | 0 | dynamic_resources: |
378 | 0 | cds_config: |
379 | 0 | api_config_source: |
380 | 0 | api_type: {} |
381 | 0 | grpc_services: |
382 | 0 | envoy_grpc: |
383 | 0 | cluster_name: my_cds_cluster |
384 | 0 | set_node_on_first_message_only: true |
385 | 0 | static_resources: |
386 | 0 | clusters: |
387 | 0 | - name: my_cds_cluster |
388 | 0 | typed_extension_protocol_options: |
389 | 0 | envoy.extensions.upstreams.http.v3.HttpProtocolOptions: |
390 | 0 | "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions |
391 | 0 | explicit_http_config: |
392 | 0 | http2_protocol_options: {{}} |
393 | 0 | load_assignment: |
394 | 0 | cluster_name: my_cds_cluster |
395 | 0 | endpoints: |
396 | 0 | - lb_endpoints: |
397 | 0 | - endpoint: |
398 | 0 | address: |
399 | 0 | socket_address: |
400 | 0 | address: 127.0.0.1 |
401 | 0 | port_value: 0 |
402 | 0 | )EOF", |
403 | 0 | Platform::null_device_path, api_type); |
404 | 0 | } |
405 | | |
406 | | // TODO(#6327) cleaner approach to testing with static config. |
407 | 0 | std::string ConfigHelper::discoveredClustersBootstrap(const std::string& api_type) { |
408 | 0 | return absl::StrCat(clustersNoListenerBootstrap(api_type), |
409 | 0 | R"EOF( |
410 | 0 | listeners: |
411 | 0 | name: http |
412 | 0 | address: |
413 | 0 | socket_address: |
414 | 0 | address: 127.0.0.1 |
415 | 0 | port_value: 0 |
416 | 0 | filter_chains: |
417 | 0 | filters: |
418 | 0 | name: http |
419 | 0 | typed_config: |
420 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager |
421 | 0 | stat_prefix: config_test |
422 | 0 | http_filters: |
423 | 0 | - name: envoy.filters.http.router |
424 | 0 | typed_config: |
425 | 0 | "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router |
426 | 0 | codec_type: HTTP2 |
427 | 0 | route_config: |
428 | 0 | name: route_config_0 |
429 | 0 | validate_clusters: false |
430 | 0 | virtual_hosts: |
431 | 0 | name: integration |
432 | 0 | routes: |
433 | 0 | - route: |
434 | 0 | cluster: cluster_1 |
435 | 0 | match: |
436 | 0 | prefix: "/cluster1" |
437 | 0 | - route: |
438 | 0 | cluster: cluster_2 |
439 | 0 | match: |
440 | 0 | prefix: "/cluster2" |
441 | 0 | domains: "*" |
442 | 0 | )EOF"); |
443 | 0 | } |
444 | | |
445 | | // TODO(#6327) cleaner approach to testing with static config. |
446 | 14 | std::string ConfigHelper::adsBootstrap(const std::string& api_type) { |
447 | | // We use this to allow tests to default to having a single API version but override and make |
448 | | // the transport/resource API version distinction when needed. |
449 | 14 | return fmt::format(R"EOF( |
450 | 14 | dynamic_resources: |
451 | 14 | lds_config: |
452 | 14 | ads: {{}} |
453 | 14 | cds_config: |
454 | 14 | ads: {{}} |
455 | 14 | ads_config: |
456 | 14 | api_type: {0} |
457 | 14 | set_node_on_first_message_only: true |
458 | 14 | static_resources: |
459 | 14 | clusters: |
460 | 14 | name: dummy_cluster |
461 | 14 | connect_timeout: |
462 | 14 | seconds: 5 |
463 | 14 | type: STATIC |
464 | 14 | load_assignment: |
465 | 14 | cluster_name: dummy_cluster |
466 | 14 | endpoints: |
467 | 14 | - lb_endpoints: |
468 | 14 | - endpoint: |
469 | 14 | address: |
470 | 14 | socket_address: |
471 | 14 | address: 127.0.0.1 |
472 | 14 | port_value: 0 |
473 | 14 | lb_policy: ROUND_ROBIN |
474 | 14 | typed_extension_protocol_options: |
475 | 14 | envoy.extensions.upstreams.http.v3.HttpProtocolOptions: |
476 | 14 | "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions |
477 | 14 | explicit_http_config: |
478 | 14 | http2_protocol_options: {{}} |
479 | 14 | admin: |
480 | 14 | access_log: |
481 | 14 | - name: envoy.access_loggers.file |
482 | 14 | typed_config: |
483 | 14 | "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog |
484 | 14 | path: "{1}" |
485 | 14 | address: |
486 | 14 | socket_address: |
487 | 14 | address: 127.0.0.1 |
488 | 14 | port_value: 0 |
489 | 14 | )EOF", |
490 | 14 | api_type, Platform::null_device_path); |
491 | 14 | } |
492 | | |
493 | | // TODO(samflattery): bundle this up with buildCluster |
494 | | envoy::config::cluster::v3::Cluster |
495 | | ConfigHelper::buildStaticCluster(const std::string& name, int port, const std::string& address, |
496 | 0 | const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { |
497 | 0 | envoy::config::cluster::v3::Cluster cluster; |
498 | 0 | cluster.mutable_connect_timeout()->set_seconds(5); |
499 | 0 | cluster.set_type(envoy::config::cluster::v3::Cluster::STATIC); |
500 | 0 | cluster.set_name(name); |
501 | 0 | cluster.mutable_load_assignment()->set_cluster_name(name); |
502 | 0 | auto* endpoint = |
503 | 0 | cluster.mutable_load_assignment()->add_endpoints()->add_lb_endpoints()->mutable_endpoint(); |
504 | 0 | auto* addr = endpoint->mutable_address(); |
505 | 0 | addr->mutable_socket_address()->set_address(address); |
506 | 0 | addr->mutable_socket_address()->set_port_value(port); |
507 | 0 | addr = endpoint->mutable_health_check_config()->mutable_address(); |
508 | 0 | addr->mutable_socket_address()->set_address(address); |
509 | 0 | addr->mutable_socket_address()->set_port_value(port); |
510 | 0 | cluster.set_lb_policy(lb_policy); |
511 | 0 | envoy::extensions::upstreams::http::v3::HttpProtocolOptions protocol_options; |
512 | 0 | protocol_options.mutable_explicit_http_config()->mutable_http2_protocol_options(); |
513 | |
|
514 | 0 | (*cluster.mutable_typed_extension_protocol_options()) |
515 | 0 | ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] |
516 | 0 | .PackFrom(protocol_options); |
517 | 0 | return cluster; |
518 | 0 | } |
519 | | |
520 | | envoy::config::cluster::v3::Cluster ConfigHelper::buildH1ClusterWithHighCircuitBreakersLimits( |
521 | | const std::string& name, int port, const std::string& address, |
522 | 0 | const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { |
523 | 0 | envoy::config::cluster::v3::Cluster cluster; |
524 | 0 | cluster.set_name(name); |
525 | 0 | cluster.mutable_connect_timeout()->set_seconds(50); |
526 | 0 | cluster.set_type(envoy::config::cluster::v3::Cluster::STATIC); |
527 | 0 | auto* threshold = cluster.mutable_circuit_breakers()->mutable_thresholds()->Add(); |
528 | 0 | threshold->set_priority(envoy::config::core::v3::RoutingPriority::DEFAULT); |
529 | 0 | threshold->mutable_max_connections()->set_value(10000); |
530 | 0 | threshold->mutable_max_pending_requests()->set_value(10000); |
531 | 0 | threshold->mutable_max_requests()->set_value(10000); |
532 | 0 | threshold->mutable_max_retries()->set_value(10000); |
533 | 0 | cluster.mutable_load_assignment()->set_cluster_name(name); |
534 | 0 | auto* endpoint = |
535 | 0 | cluster.mutable_load_assignment()->add_endpoints()->add_lb_endpoints()->mutable_endpoint(); |
536 | 0 | cluster.set_lb_policy(lb_policy); |
537 | 0 | auto* addr = endpoint->mutable_address(); |
538 | 0 | addr->mutable_socket_address()->set_address(address); |
539 | 0 | addr->mutable_socket_address()->set_port_value(port); |
540 | 0 | return cluster; |
541 | 0 | } |
542 | | |
543 | | envoy::config::cluster::v3::Cluster |
544 | | ConfigHelper::buildCluster(const std::string& name, |
545 | 28 | const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { |
546 | 28 | envoy::config::cluster::v3::Cluster cluster; |
547 | 28 | cluster.mutable_connect_timeout()->set_seconds(5); |
548 | 28 | cluster.set_type(envoy::config::cluster::v3::Cluster::EDS); |
549 | 28 | cluster.set_name(name); |
550 | 28 | cluster.set_lb_policy(lb_policy); |
551 | | |
552 | 28 | auto* eds = cluster.mutable_eds_cluster_config()->mutable_eds_config(); |
553 | 28 | eds->set_resource_api_version(envoy::config::core::v3::ApiVersion::V3); |
554 | 28 | eds->mutable_ads(); |
555 | | |
556 | 28 | envoy::extensions::upstreams::http::v3::HttpProtocolOptions protocol_options; |
557 | 28 | protocol_options.mutable_explicit_http_config()->mutable_http2_protocol_options(); |
558 | 28 | (*cluster.mutable_typed_extension_protocol_options()) |
559 | 28 | ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] |
560 | 28 | .PackFrom(protocol_options); |
561 | | |
562 | 28 | return cluster; |
563 | 28 | } |
564 | | |
565 | | envoy::config::cluster::v3::Cluster |
566 | | ConfigHelper::buildTlsCluster(const std::string& name, |
567 | 0 | const envoy::config::cluster::v3::Cluster::LbPolicy lb_policy) { |
568 | 0 | envoy::config::cluster::v3::Cluster cluster = buildCluster(name, lb_policy); |
569 | |
|
570 | 0 | auto* socket = cluster.mutable_transport_socket(); |
571 | 0 | envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext tls_socket; |
572 | 0 | tls_socket.mutable_common_tls_context() |
573 | 0 | ->mutable_validation_context() |
574 | 0 | ->mutable_trusted_ca() |
575 | 0 | ->set_filename( |
576 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcacert.pem")); |
577 | 0 | socket->set_name("envoy.transport_sockets.tls"); |
578 | 0 | socket->mutable_typed_config()->PackFrom(tls_socket); |
579 | 0 | return cluster; |
580 | 0 | } |
581 | | |
582 | | envoy::config::endpoint::v3::ClusterLoadAssignment |
583 | | ConfigHelper::buildClusterLoadAssignment(const std::string& name, const std::string& address_str, |
584 | 28 | uint32_t port) { |
585 | 28 | API_NO_BOOST(envoy::config::endpoint::v3::ClusterLoadAssignment) cluster_load_assignment; |
586 | 28 | cluster_load_assignment.set_cluster_name(name); |
587 | 28 | auto* address = cluster_load_assignment.add_endpoints() |
588 | 28 | ->add_lb_endpoints() |
589 | 28 | ->mutable_endpoint() |
590 | 28 | ->mutable_address() |
591 | 28 | ->mutable_socket_address(); |
592 | 28 | address->set_address(address_str); |
593 | 28 | address->set_port_value(port); |
594 | | |
595 | 28 | return cluster_load_assignment; |
596 | 28 | } |
597 | | |
598 | | envoy::config::endpoint::v3::ClusterLoadAssignment |
599 | | ConfigHelper::buildClusterLoadAssignmentWithLeds(const std::string& name, |
600 | 0 | const std::string& leds_collection_name) { |
601 | 0 | API_NO_BOOST(envoy::config::endpoint::v3::ClusterLoadAssignment) cluster_load_assignment; |
602 | |
|
603 | 0 | cluster_load_assignment.set_cluster_name(name); |
604 | 0 | auto* lclc = cluster_load_assignment.add_endpoints()->mutable_leds_cluster_locality_config(); |
605 | 0 | auto* leds = lclc->mutable_leds_config(); |
606 | 0 | leds->set_resource_api_version(envoy::config::core::v3::ApiVersion::V3); |
607 | 0 | leds->mutable_ads(); |
608 | 0 | lclc->set_leds_collection_name(leds_collection_name); |
609 | 0 | return cluster_load_assignment; |
610 | 0 | } |
611 | | |
612 | | envoy::config::endpoint::v3::LbEndpoint |
613 | 0 | ConfigHelper::buildLbEndpoint(const std::string& address_str, uint32_t port) { |
614 | 0 | API_NO_BOOST(envoy::config::endpoint::v3::LbEndpoint) lb_endpoint; |
615 | 0 | auto* address = lb_endpoint.mutable_endpoint()->mutable_address()->mutable_socket_address(); |
616 | 0 | address->set_address(address_str); |
617 | 0 | address->set_port_value(port); |
618 | 0 | return lb_endpoint; |
619 | 0 | } |
620 | | |
621 | | envoy::config::listener::v3::Listener |
622 | | ConfigHelper::buildBaseListener(const std::string& name, const std::string& address, |
623 | 90 | const std::string& filter_chains) { |
624 | 90 | API_NO_BOOST(envoy::config::listener::v3::Listener) listener; |
625 | 90 | #ifdef ENVOY_ENABLE_YAML |
626 | 90 | TestUtility::loadFromYaml(fmt::format( |
627 | 90 | R"EOF( |
628 | 90 | name: {} |
629 | 90 | address: |
630 | 90 | socket_address: |
631 | 90 | address: {} |
632 | 90 | port_value: 0 |
633 | 90 | filter_chains: |
634 | 90 | {} |
635 | 90 | )EOF", |
636 | 90 | name, address, filter_chains), |
637 | 90 | listener); |
638 | 90 | return listener; |
639 | | #else |
640 | | UNREFERENCED_PARAMETER(name); |
641 | | UNREFERENCED_PARAMETER(address); |
642 | | UNREFERENCED_PARAMETER(filter_chains); |
643 | | PANIC("YAML support compiled out"); |
644 | | #endif |
645 | 90 | } |
646 | | |
647 | | envoy::config::listener::v3::Listener ConfigHelper::buildListener(const std::string& name, |
648 | | const std::string& route_config, |
649 | | const std::string& address, |
650 | 90 | const std::string& stat_prefix) { |
651 | 90 | std::string hcm = fmt::format( |
652 | 90 | R"EOF( |
653 | 90 | filters: |
654 | 90 | - name: http |
655 | 90 | typed_config: |
656 | 90 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager |
657 | 90 | stat_prefix: {} |
658 | 90 | codec_type: HTTP2 |
659 | 90 | rds: |
660 | 90 | route_config_name: {} |
661 | 90 | config_source: |
662 | 90 | ads: {{}} |
663 | 90 | http_filters: |
664 | 90 | - name: envoy.filters.http.router |
665 | 90 | typed_config: |
666 | 90 | "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router |
667 | 90 | )EOF", |
668 | 90 | stat_prefix, route_config); |
669 | 90 | return buildBaseListener(name, address, hcm); |
670 | 90 | } |
671 | | |
672 | | envoy::config::route::v3::RouteConfiguration |
673 | 46 | ConfigHelper::buildRouteConfig(const std::string& name, const std::string& cluster) { |
674 | 46 | API_NO_BOOST(envoy::config::route::v3::RouteConfiguration) route; |
675 | 46 | #ifdef ENVOY_ENABLE_YAML |
676 | 46 | TestUtility::loadFromYaml(fmt::format(R"EOF( |
677 | 46 | name: "{}" |
678 | 46 | virtual_hosts: |
679 | 46 | - name: integration |
680 | 46 | domains: ["*"] |
681 | 46 | routes: |
682 | 46 | - match: {{ prefix: "/" }} |
683 | 46 | route: {{ cluster: "{}" }} |
684 | 46 | )EOF", |
685 | 46 | name, cluster), |
686 | 46 | route); |
687 | 46 | return route; |
688 | | #else |
689 | | UNREFERENCED_PARAMETER(name); |
690 | | UNREFERENCED_PARAMETER(cluster); |
691 | | PANIC("YAML support compiled out"); |
692 | | #endif |
693 | 46 | } |
694 | | |
695 | 0 | envoy::config::endpoint::v3::Endpoint ConfigHelper::buildEndpoint(const std::string& address) { |
696 | 0 | envoy::config::endpoint::v3::Endpoint endpoint; |
697 | 0 | endpoint.mutable_address()->mutable_socket_address()->set_address(address); |
698 | 0 | return endpoint; |
699 | 0 | } |
700 | | |
701 | | ConfigHelper::ConfigHelper(const Network::Address::IpVersion version, Api::Api&, |
702 | | const std::string& config) |
703 | 0 | : ConfigHelper(version, basicBootstrap(bootstrap_, config)) {} |
704 | | |
705 | | ConfigHelper::ConfigHelper(const Network::Address::IpVersion version, |
706 | 1.97k | const envoy::config::bootstrap::v3::Bootstrap& bootstrap) { |
707 | 1.97k | RELEASE_ASSERT(!finalized_, ""); |
708 | 1.97k | bootstrap_ = bootstrap; |
709 | | |
710 | | // Fix up all the socket addresses with the correct version. |
711 | 1.97k | auto* admin = bootstrap_.mutable_admin(); |
712 | 1.97k | auto* admin_socket_addr = admin->mutable_address()->mutable_socket_address(); |
713 | 1.97k | admin_socket_addr->set_address(Network::Test::getLoopbackAddressString(version)); |
714 | | |
715 | 1.97k | auto* static_resources = bootstrap_.mutable_static_resources(); |
716 | 3.93k | for (int i = 0; i < static_resources->listeners_size(); ++i) { |
717 | 1.96k | auto* listener = static_resources->mutable_listeners(i); |
718 | 1.96k | if (listener->mutable_address()->has_envoy_internal_address()) { |
719 | 0 | ENVOY_LOG_MISC( |
720 | 0 | debug, "Listener {} has internal address {}. Will not reset to loop back socket address.", |
721 | 0 | i, listener->mutable_address()->envoy_internal_address().server_listener_name()); |
722 | 0 | continue; |
723 | 0 | } |
724 | 1.96k | if (listener->mutable_address()->has_pipe()) { |
725 | 0 | ENVOY_LOG_MISC(debug, |
726 | 0 | "Listener {} has pipe address {}. Will not reset to loop back socket address.", |
727 | 0 | i, listener->mutable_address()->pipe().path()); |
728 | 0 | continue; |
729 | 0 | } |
730 | 1.96k | auto* listener_socket_addr = listener->mutable_address()->mutable_socket_address(); |
731 | 1.96k | if (listener_socket_addr->address() == "0.0.0.0" || listener_socket_addr->address() == "::") { |
732 | 0 | listener_socket_addr->set_address(Network::Test::getAnyAddressString(version)); |
733 | 1.96k | } else { |
734 | 1.96k | listener_socket_addr->set_address(Network::Test::getLoopbackAddressString(version)); |
735 | 1.96k | } |
736 | | |
737 | 1.96k | for (int i = 0; i < listener->additional_addresses_size(); i++) { |
738 | 0 | auto* listener_socket_addr = |
739 | 0 | listener->mutable_additional_addresses(i)->mutable_address()->mutable_socket_address(); |
740 | 0 | if (listener_socket_addr->address() == "0.0.0.0" || listener_socket_addr->address() == "::") { |
741 | 0 | listener_socket_addr->set_address(Network::Test::getAnyAddressString(version)); |
742 | 0 | } else { |
743 | 0 | listener_socket_addr->set_address(Network::Test::getLoopbackAddressString(version)); |
744 | 0 | } |
745 | 0 | } |
746 | 1.96k | } |
747 | | |
748 | 3.95k | for (int i = 0; i < static_resources->clusters_size(); ++i) { |
749 | 1.97k | auto* cluster = static_resources->mutable_clusters(i); |
750 | 3.95k | for (int j = 0; j < cluster->load_assignment().endpoints_size(); ++j) { |
751 | 1.97k | auto* locality_lb = cluster->mutable_load_assignment()->mutable_endpoints(j); |
752 | 3.95k | for (int k = 0; k < locality_lb->lb_endpoints_size(); ++k) { |
753 | 1.97k | auto* lb_endpoint = locality_lb->mutable_lb_endpoints(k); |
754 | 1.97k | if (lb_endpoint->endpoint().address().has_socket_address()) { |
755 | 1.97k | lb_endpoint->mutable_endpoint()->mutable_address()->mutable_socket_address()->set_address( |
756 | 1.97k | Network::Test::getLoopbackAddressString(version)); |
757 | 1.97k | } |
758 | 1.97k | } |
759 | 1.97k | } |
760 | 1.97k | } |
761 | | |
762 | | // Ensure we have a basic admin-capable runtime layer. |
763 | 1.97k | if (bootstrap_.mutable_layered_runtime()->layers_size() == 0) { |
764 | 1.97k | auto* static_layer = bootstrap_.mutable_layered_runtime()->add_layers(); |
765 | 1.97k | static_layer->set_name("static_layer"); |
766 | 1.97k | static_layer->mutable_static_layer(); |
767 | 1.97k | auto* admin_layer = bootstrap_.mutable_layered_runtime()->add_layers(); |
768 | 1.97k | admin_layer->set_name("admin"); |
769 | 1.97k | admin_layer->mutable_admin_layer(); |
770 | 1.97k | } |
771 | 1.97k | } |
772 | | |
773 | 0 | void ConfigHelper::addListenerTypedMetadata(absl::string_view key, ProtobufWkt::Any& packed_value) { |
774 | 0 | RELEASE_ASSERT(!finalized_, ""); |
775 | 0 | auto* static_resources = bootstrap_.mutable_static_resources(); |
776 | 0 | ASSERT_TRUE(static_resources->listeners_size() > 0); |
777 | 0 | auto* listener = static_resources->mutable_listeners(0); |
778 | 0 | auto* map = listener->mutable_metadata()->mutable_typed_filter_metadata(); |
779 | 0 | (*map)[std::string(key)] = packed_value; |
780 | 0 | }; |
781 | | |
782 | | void ConfigHelper::addClusterFilterMetadata(absl::string_view metadata_yaml, |
783 | 0 | absl::string_view cluster_name) { |
784 | 0 | #ifdef ENVOY_ENABLE_YAML |
785 | 0 | RELEASE_ASSERT(!finalized_, ""); |
786 | 0 | ProtobufWkt::Struct cluster_metadata; |
787 | 0 | TestUtility::loadFromYaml(std::string(metadata_yaml), cluster_metadata); |
788 | |
|
789 | 0 | auto* static_resources = bootstrap_.mutable_static_resources(); |
790 | 0 | for (int i = 0; i < static_resources->clusters_size(); ++i) { |
791 | 0 | auto* cluster = static_resources->mutable_clusters(i); |
792 | 0 | if (cluster->name() != cluster_name) { |
793 | 0 | continue; |
794 | 0 | } |
795 | 0 | for (const auto& kvp : cluster_metadata.fields()) { |
796 | 0 | ASSERT_TRUE(kvp.second.kind_case() == ProtobufWkt::Value::KindCase::kStructValue); |
797 | 0 | cluster->mutable_metadata()->mutable_filter_metadata()->insert( |
798 | 0 | {kvp.first, kvp.second.struct_value()}); |
799 | 0 | } |
800 | 0 | break; |
801 | 0 | } |
802 | | #else |
803 | | UNREFERENCED_PARAMETER(metadata_yaml); |
804 | | UNREFERENCED_PARAMETER(cluster_name); |
805 | | PANIC("YAML support compiled out"); |
806 | | #endif |
807 | 0 | } |
808 | | |
809 | | void ConfigHelper::setConnectConfig( |
810 | | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& hcm, |
811 | | bool terminate_connect, bool allow_post, bool http3, |
812 | 0 | absl::optional<envoy::config::core::v3::ProxyProtocolConfig::Version> proxy_protocol_version) { |
813 | 0 | auto* route_config = hcm.mutable_route_config(); |
814 | 0 | ASSERT_EQ(1, route_config->virtual_hosts_size()); |
815 | 0 | auto* route = route_config->mutable_virtual_hosts(0)->mutable_routes(0); |
816 | 0 | auto* match = route->mutable_match(); |
817 | 0 | match->Clear(); |
818 | |
|
819 | 0 | if (allow_post) { |
820 | 0 | match->set_prefix("/"); |
821 | |
|
822 | 0 | auto* header = match->add_headers(); |
823 | 0 | header->set_name(":method"); |
824 | 0 | header->mutable_string_match()->set_exact("POST"); |
825 | 0 | } else { |
826 | 0 | match->mutable_connect_matcher(); |
827 | 0 | } |
828 | |
|
829 | 0 | auto* upgrade = route->mutable_route()->add_upgrade_configs(); |
830 | 0 | upgrade->set_upgrade_type("CONNECT"); |
831 | |
|
832 | 0 | if (terminate_connect) { |
833 | 0 | auto* config = upgrade->mutable_connect_config(); |
834 | 0 | if (allow_post) { |
835 | 0 | config->set_allow_post(true); |
836 | 0 | } |
837 | |
|
838 | 0 | if (proxy_protocol_version.has_value()) { |
839 | 0 | config->mutable_proxy_protocol_config()->set_version(proxy_protocol_version.value()); |
840 | 0 | } |
841 | 0 | } |
842 | |
|
843 | 0 | hcm.add_upgrade_configs()->set_upgrade_type("CONNECT"); |
844 | 0 | hcm.mutable_http2_protocol_options()->set_allow_connect(true); |
845 | 0 | if (http3) { |
846 | 0 | hcm.mutable_http3_protocol_options()->set_allow_extended_connect(true); |
847 | 0 | } |
848 | 0 | } |
849 | | |
850 | | void ConfigHelper::setConnectUdpConfig( |
851 | | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& hcm, |
852 | 0 | bool terminate_connect, bool http3) { |
853 | 0 | auto* route_config = hcm.mutable_route_config(); |
854 | 0 | ASSERT_EQ(1, route_config->virtual_hosts_size()); |
855 | 0 | auto* route = route_config->mutable_virtual_hosts(0)->mutable_routes(0); |
856 | 0 | auto* match = route->mutable_match(); |
857 | 0 | match->Clear(); |
858 | 0 | match->mutable_connect_matcher(); |
859 | |
|
860 | 0 | auto* upgrade = route->mutable_route()->add_upgrade_configs(); |
861 | 0 | upgrade->set_upgrade_type("connect-udp"); |
862 | |
|
863 | 0 | if (terminate_connect) { |
864 | 0 | upgrade->mutable_connect_config(); |
865 | 0 | } |
866 | |
|
867 | 0 | hcm.add_upgrade_configs()->set_upgrade_type("connect-udp"); |
868 | 0 | hcm.mutable_http2_protocol_options()->set_allow_connect(true); |
869 | 0 | if (http3) { |
870 | 0 | hcm.mutable_http3_protocol_options()->set_allow_extended_connect(true); |
871 | 0 | } |
872 | 0 | } |
873 | | |
874 | 1.97k | void ConfigHelper::applyConfigModifiers() { |
875 | 5.01k | for (const auto& config_modifier : config_modifiers_) { |
876 | 5.01k | config_modifier(bootstrap_); |
877 | 5.01k | } |
878 | 1.97k | config_modifiers_.clear(); |
879 | 1.97k | } |
880 | | |
881 | | void ConfigHelper::configureUpstreamTls( |
882 | | bool use_alpn, bool http3, |
883 | | absl::optional<envoy::config::core::v3::AlternateProtocolsCacheOptions> |
884 | | alternate_protocol_cache_config, |
885 | | std::function<void(envoy::extensions::transport_sockets::tls::v3::CommonTlsContext&)> |
886 | 0 | configure_tls_context) { |
887 | 0 | addConfigModifier([use_alpn, http3, alternate_protocol_cache_config, |
888 | 0 | configure_tls_context](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { |
889 | 0 | auto* cluster = bootstrap.mutable_static_resources()->mutable_clusters(0); |
890 | |
|
891 | 0 | ConfigHelper::HttpProtocolOptions protocol_options; |
892 | 0 | protocol_options.mutable_upstream_http_protocol_options()->set_auto_sni(true); |
893 | 0 | ConfigHelper::setProtocolOptions(*cluster, protocol_options); |
894 | |
|
895 | 0 | if (use_alpn) { |
896 | 0 | ConfigHelper::HttpProtocolOptions new_protocol_options; |
897 | |
|
898 | 0 | HttpProtocolOptions old_protocol_options = |
899 | 0 | MessageUtil::anyConvert<ConfigHelper::HttpProtocolOptions>( |
900 | 0 | (*cluster->mutable_typed_extension_protocol_options()) |
901 | 0 | ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"]); |
902 | 0 | protocol_options.MergeFrom(old_protocol_options); |
903 | |
|
904 | 0 | new_protocol_options = old_protocol_options; |
905 | 0 | new_protocol_options.clear_explicit_http_config(); |
906 | 0 | new_protocol_options.mutable_auto_config(); |
907 | 0 | if (old_protocol_options.explicit_http_config().has_http_protocol_options()) { |
908 | 0 | new_protocol_options.mutable_auto_config()->mutable_http_protocol_options()->MergeFrom( |
909 | 0 | old_protocol_options.explicit_http_config().http_protocol_options()); |
910 | 0 | } else if (old_protocol_options.explicit_http_config().has_http2_protocol_options()) { |
911 | 0 | new_protocol_options.mutable_auto_config()->mutable_http2_protocol_options()->MergeFrom( |
912 | 0 | old_protocol_options.explicit_http_config().http2_protocol_options()); |
913 | 0 | } |
914 | 0 | if (http3 || old_protocol_options.explicit_http_config().has_http3_protocol_options()) { |
915 | 0 | new_protocol_options.mutable_auto_config()->mutable_http3_protocol_options()->MergeFrom( |
916 | 0 | old_protocol_options.explicit_http_config().http3_protocol_options()); |
917 | 0 | } |
918 | 0 | if (alternate_protocol_cache_config.has_value()) { |
919 | 0 | new_protocol_options.mutable_auto_config() |
920 | 0 | ->mutable_alternate_protocols_cache_options() |
921 | 0 | ->set_name("default_alternate_protocols_cache"); |
922 | 0 | new_protocol_options.mutable_auto_config() |
923 | 0 | ->mutable_alternate_protocols_cache_options() |
924 | 0 | ->CopyFrom(alternate_protocol_cache_config.value()); |
925 | 0 | } |
926 | 0 | (*cluster->mutable_typed_extension_protocol_options()) |
927 | 0 | ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] |
928 | 0 | .PackFrom(new_protocol_options); |
929 | 0 | } |
930 | 0 | envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext tls_context; |
931 | 0 | if (configure_tls_context != nullptr) { |
932 | 0 | configure_tls_context(*tls_context.mutable_common_tls_context()); |
933 | 0 | } |
934 | 0 | auto* validation_context = |
935 | 0 | tls_context.mutable_common_tls_context()->mutable_validation_context(); |
936 | 0 | validation_context->mutable_trusted_ca()->set_filename( |
937 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcacert.pem")); |
938 | | // The test certs are for *.lyft.com, so make sure SNI matches. |
939 | 0 | tls_context.set_sni("foo.lyft.com"); |
940 | 0 | if (http3) { |
941 | 0 | envoy::extensions::transport_sockets::quic::v3::QuicUpstreamTransport quic_context; |
942 | 0 | quic_context.mutable_upstream_tls_context()->CopyFrom(tls_context); |
943 | 0 | cluster->mutable_transport_socket()->set_name("envoy.transport_sockets.quic"); |
944 | 0 | cluster->mutable_transport_socket()->mutable_typed_config()->PackFrom(quic_context); |
945 | 0 | } else { |
946 | 0 | cluster->mutable_transport_socket()->set_name("envoy.transport_sockets.tls"); |
947 | 0 | cluster->mutable_transport_socket()->mutable_typed_config()->PackFrom(tls_context); |
948 | 0 | } |
949 | 0 | }); |
950 | 0 | } |
951 | | |
952 | 1.99k | void ConfigHelper::addRuntimeOverride(absl::string_view key, absl::string_view value) { |
953 | 1.99k | auto* static_layer = |
954 | 1.99k | bootstrap_.mutable_layered_runtime()->mutable_layers(0)->mutable_static_layer(); |
955 | | |
956 | 1.99k | if (value == "true") { |
957 | 7 | (*static_layer->mutable_fields())[std::string(key)] = ValueUtil::boolValue(true); |
958 | 1.98k | } else if (value == "false") { |
959 | 1.98k | (*static_layer->mutable_fields())[std::string(key)] = ValueUtil::boolValue(false); |
960 | 1.98k | } else { |
961 | 0 | (*static_layer->mutable_fields())[std::string(key)] = |
962 | 0 | ValueUtil::stringValue(std::string(value)); |
963 | 0 | } |
964 | 1.99k | } |
965 | | |
966 | | void ConfigHelper::setProtocolOptions(envoy::config::cluster::v3::Cluster& cluster, |
967 | 2.28k | HttpProtocolOptions& protocol_options) { |
968 | 2.28k | if (cluster.typed_extension_protocol_options().contains( |
969 | 2.28k | "envoy.extensions.upstreams.http.v3.HttpProtocolOptions")) { |
970 | 780 | HttpProtocolOptions old_options = MessageUtil::anyConvert<ConfigHelper::HttpProtocolOptions>( |
971 | 780 | (*cluster.mutable_typed_extension_protocol_options()) |
972 | 780 | ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"]); |
973 | 780 | bool auto_config = old_options.has_auto_config(); |
974 | 780 | old_options.MergeFrom(protocol_options); |
975 | 780 | protocol_options.CopyFrom(old_options); |
976 | 780 | if (auto_config) { |
977 | 0 | protocol_options.mutable_auto_config(); |
978 | 0 | } |
979 | 780 | } |
980 | 2.28k | (*cluster.mutable_typed_extension_protocol_options()) |
981 | 2.28k | ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] |
982 | 2.28k | .PackFrom(protocol_options); |
983 | 2.28k | } |
984 | | |
985 | 806 | void ConfigHelper::setHttp2(envoy::config::cluster::v3::Cluster& cluster) { |
986 | 806 | HttpProtocolOptions protocol_options; |
987 | 806 | protocol_options.mutable_explicit_http_config()->mutable_http2_protocol_options(); |
988 | 806 | setProtocolOptions(cluster, protocol_options); |
989 | 806 | } |
990 | | |
991 | 1.97k | void ConfigHelper::finalize(const std::vector<uint32_t>& ports) { |
992 | 1.97k | RELEASE_ASSERT(!finalized_, ""); |
993 | | |
994 | 1.97k | applyConfigModifiers(); |
995 | | |
996 | 1.97k | setPorts(ports); |
997 | | |
998 | 1.97k | if (!connect_timeout_set_) { |
999 | | #ifdef __APPLE__ |
1000 | | // Set a high default connect timeout. Under heavy load (and in particular in CI), macOS |
1001 | | // connections can take inordinately long to complete. |
1002 | | setConnectTimeout(std::chrono::seconds(30)); |
1003 | | #else |
1004 | | // Set a default connect timeout. |
1005 | 1.97k | setConnectTimeout(std::chrono::seconds(5)); |
1006 | 1.97k | #endif |
1007 | 1.97k | } |
1008 | | |
1009 | 1.97k | finalized_ = true; |
1010 | 1.97k | } |
1011 | | |
1012 | 1.97k | void ConfigHelper::setPorts(const std::vector<uint32_t>& ports, bool override_port_zero) { |
1013 | 1.97k | uint32_t port_idx = 0; |
1014 | 1.97k | bool eds_hosts = false; |
1015 | 1.97k | bool custom_cluster = false; |
1016 | 1.97k | bool original_dst_cluster = false; |
1017 | 1.97k | auto* static_resources = bootstrap_.mutable_static_resources(); |
1018 | 4.36k | for (int i = 0; i < bootstrap_.mutable_static_resources()->clusters_size(); ++i) { |
1019 | 2.39k | auto* cluster = static_resources->mutable_clusters(i); |
1020 | 2.39k | if (cluster->type() == envoy::config::cluster::v3::Cluster::EDS) { |
1021 | 0 | eds_hosts = true; |
1022 | 2.39k | } else if (cluster->type() == envoy::config::cluster::v3::Cluster::ORIGINAL_DST) { |
1023 | 0 | original_dst_cluster = true; |
1024 | 2.39k | } else if (cluster->has_cluster_type()) { |
1025 | 0 | custom_cluster = true; |
1026 | 2.39k | } else { |
1027 | | // Assign ports to statically defined load_assignment hosts. |
1028 | 4.78k | for (int j = 0; j < cluster->load_assignment().endpoints_size(); ++j) { |
1029 | 2.39k | auto locality_lb = cluster->mutable_load_assignment()->mutable_endpoints(j); |
1030 | 4.78k | for (int k = 0; k < locality_lb->lb_endpoints_size(); ++k) { |
1031 | 2.39k | auto lb_endpoint = locality_lb->mutable_lb_endpoints(k); |
1032 | 2.39k | if (lb_endpoint->endpoint().address().has_socket_address()) { |
1033 | 2.39k | if (lb_endpoint->endpoint().address().socket_address().port_value() == 0 || |
1034 | 2.39k | override_port_zero) { |
1035 | 1.99k | RELEASE_ASSERT(ports.size() > port_idx, ""); |
1036 | 1.99k | lb_endpoint->mutable_endpoint() |
1037 | 1.99k | ->mutable_address() |
1038 | 1.99k | ->mutable_socket_address() |
1039 | 1.99k | ->set_port_value(ports[port_idx++]); |
1040 | 1.99k | } else { |
1041 | 403 | ENVOY_LOG_MISC(debug, "Not overriding preset port", |
1042 | 403 | lb_endpoint->endpoint().address().socket_address().port_value()); |
1043 | 403 | } |
1044 | 2.39k | } |
1045 | 2.39k | } |
1046 | 2.39k | } |
1047 | 2.39k | } |
1048 | 2.39k | } |
1049 | 1.97k | ASSERT(skip_port_usage_validation_ || port_idx == ports.size() || eds_hosts || |
1050 | 1.97k | original_dst_cluster || custom_cluster || bootstrap_.dynamic_resources().has_cds_config()); |
1051 | 1.97k | } |
1052 | | |
1053 | 0 | void ConfigHelper::setSourceAddress(const std::string& address_string) { |
1054 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1055 | 0 | bootstrap_.mutable_cluster_manager() |
1056 | 0 | ->mutable_upstream_bind_config() |
1057 | 0 | ->mutable_source_address() |
1058 | 0 | ->set_address(address_string); |
1059 | | // We don't have the ability to bind to specific ports yet. |
1060 | 0 | bootstrap_.mutable_cluster_manager() |
1061 | 0 | ->mutable_upstream_bind_config() |
1062 | 0 | ->mutable_source_address() |
1063 | 0 | ->set_port_value(0); |
1064 | 0 | } |
1065 | | |
1066 | 0 | void ConfigHelper::setDefaultHostAndRoute(const std::string& domains, const std::string& prefix) { |
1067 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1068 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1069 | 0 | hcm_config; |
1070 | 0 | loadHttpConnectionManager(hcm_config); |
1071 | |
|
1072 | 0 | auto* virtual_host = hcm_config.mutable_route_config()->mutable_virtual_hosts(0); |
1073 | 0 | virtual_host->set_domains(0, domains); |
1074 | 0 | virtual_host->mutable_routes(0)->mutable_match()->set_prefix(prefix); |
1075 | |
|
1076 | 0 | storeHttpConnectionManager(hcm_config); |
1077 | 0 | } |
1078 | | |
1079 | | void ConfigHelper::setBufferLimits(uint32_t upstream_buffer_limit, |
1080 | 403 | uint32_t downstream_buffer_limit) { |
1081 | 403 | RELEASE_ASSERT(!finalized_, ""); |
1082 | 403 | auto* listener = bootstrap_.mutable_static_resources()->mutable_listeners(0); |
1083 | 403 | listener->mutable_per_connection_buffer_limit_bytes()->set_value(downstream_buffer_limit); |
1084 | 403 | const uint32_t stream_buffer_size = std::max( |
1085 | 403 | downstream_buffer_limit, Http2::Utility::OptionsLimits::MIN_INITIAL_STREAM_WINDOW_SIZE); |
1086 | 403 | if (Network::Utility::protobufAddressSocketType(listener->address()) == |
1087 | 403 | Network::Socket::Type::Datagram && |
1088 | 403 | listener->udp_listener_config().has_quic_options()) { |
1089 | | // QUIC stream's flow control window is configured in listener config. |
1090 | 0 | listener->mutable_udp_listener_config() |
1091 | 0 | ->mutable_quic_options() |
1092 | 0 | ->mutable_quic_protocol_options() |
1093 | 0 | ->mutable_initial_stream_window_size() |
1094 | | // The same as kStreamReceiveWindowLimit in QUICHE which only supports stream flow control |
1095 | | // window no larger than 16MB. |
1096 | 0 | ->set_value(std::min(16u * 1024 * 1024, stream_buffer_size)); |
1097 | 0 | } |
1098 | | |
1099 | 403 | auto* static_resources = bootstrap_.mutable_static_resources(); |
1100 | 806 | for (int i = 0; i < bootstrap_.mutable_static_resources()->clusters_size(); ++i) { |
1101 | 403 | auto* cluster = static_resources->mutable_clusters(i); |
1102 | 403 | cluster->mutable_per_connection_buffer_limit_bytes()->set_value(upstream_buffer_limit); |
1103 | 403 | } |
1104 | | |
1105 | 403 | auto filter = getFilterFromListener("http"); |
1106 | 403 | if (filter) { |
1107 | 403 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1108 | 403 | hcm_config; |
1109 | 403 | loadHttpConnectionManager(hcm_config); |
1110 | 403 | if (hcm_config.codec_type() == envoy::extensions::filters::network::http_connection_manager:: |
1111 | 403 | v3::HttpConnectionManager::HTTP2) { |
1112 | 403 | auto* options = hcm_config.mutable_http2_protocol_options(); |
1113 | 403 | options->mutable_initial_stream_window_size()->set_value(stream_buffer_size); |
1114 | 403 | storeHttpConnectionManager(hcm_config); |
1115 | 403 | } |
1116 | 403 | } |
1117 | 403 | } |
1118 | | |
1119 | 0 | void ConfigHelper::setListenerSendBufLimits(uint32_t limit) { |
1120 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1121 | 0 | RELEASE_ASSERT(bootstrap_.mutable_static_resources()->listeners_size() == 1, ""); |
1122 | 0 | auto* listener = bootstrap_.mutable_static_resources()->mutable_listeners(0); |
1123 | 0 | auto* options = listener->add_socket_options(); |
1124 | 0 | options->set_description("SO_SNDBUF"); |
1125 | 0 | options->set_level(SOL_SOCKET); |
1126 | 0 | options->set_int_value(limit); |
1127 | 0 | options->set_name(SO_SNDBUF); |
1128 | 0 | } |
1129 | | |
1130 | 0 | void ConfigHelper::setDownstreamHttpIdleTimeout(std::chrono::milliseconds timeout) { |
1131 | 0 | addConfigModifier( |
1132 | 0 | [timeout]( |
1133 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
1134 | 0 | hcm) { |
1135 | 0 | hcm.mutable_common_http_protocol_options()->mutable_idle_timeout()->MergeFrom( |
1136 | 0 | ProtobufUtil::TimeUtil::MillisecondsToDuration(timeout.count())); |
1137 | 0 | }); |
1138 | 0 | } |
1139 | | |
1140 | 0 | void ConfigHelper::setDownstreamMaxConnectionDuration(std::chrono::milliseconds timeout) { |
1141 | 0 | addConfigModifier( |
1142 | 0 | [timeout]( |
1143 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
1144 | 0 | hcm) { |
1145 | 0 | hcm.mutable_common_http_protocol_options()->mutable_max_connection_duration()->MergeFrom( |
1146 | 0 | ProtobufUtil::TimeUtil::MillisecondsToDuration(timeout.count())); |
1147 | 0 | }); |
1148 | 0 | } |
1149 | | |
1150 | 0 | void ConfigHelper::setDownstreamMaxStreamDuration(std::chrono::milliseconds timeout) { |
1151 | 0 | addConfigModifier( |
1152 | 0 | [timeout]( |
1153 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
1154 | 0 | hcm) { |
1155 | 0 | hcm.mutable_common_http_protocol_options()->mutable_max_stream_duration()->MergeFrom( |
1156 | 0 | ProtobufUtil::TimeUtil::MillisecondsToDuration(timeout.count())); |
1157 | 0 | }); |
1158 | 0 | } |
1159 | | |
1160 | 1.97k | void ConfigHelper::setConnectTimeout(std::chrono::milliseconds timeout) { |
1161 | 1.97k | RELEASE_ASSERT(!finalized_, ""); |
1162 | | |
1163 | 1.97k | auto* static_resources = bootstrap_.mutable_static_resources(); |
1164 | 4.36k | for (int i = 0; i < bootstrap_.mutable_static_resources()->clusters_size(); ++i) { |
1165 | 2.39k | auto* cluster = static_resources->mutable_clusters(i); |
1166 | 2.39k | cluster->mutable_connect_timeout()->MergeFrom( |
1167 | 2.39k | ProtobufUtil::TimeUtil::MillisecondsToDuration(timeout.count())); |
1168 | 2.39k | } |
1169 | 1.97k | connect_timeout_set_ = true; |
1170 | 1.97k | } |
1171 | | |
1172 | 0 | void ConfigHelper::disableDelayClose() { |
1173 | 0 | addConfigModifier( |
1174 | 0 | [](envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
1175 | 0 | hcm) { hcm.mutable_delayed_close_timeout()->set_nanos(0); }); |
1176 | 0 | } |
1177 | | |
1178 | 0 | void ConfigHelper::setDownstreamMaxRequestsPerConnection(uint64_t max_requests_per_connection) { |
1179 | 0 | addConfigModifier( |
1180 | 0 | [max_requests_per_connection]( |
1181 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
1182 | 0 | hcm) { |
1183 | 0 | hcm.mutable_common_http_protocol_options() |
1184 | 0 | ->mutable_max_requests_per_connection() |
1185 | 0 | ->set_value(max_requests_per_connection); |
1186 | 0 | }); |
1187 | 0 | } |
1188 | | |
1189 | | envoy::config::route::v3::VirtualHost |
1190 | 0 | ConfigHelper::createVirtualHost(const char* domain, const char* prefix, const char* cluster) { |
1191 | 0 | envoy::config::route::v3::VirtualHost virtual_host; |
1192 | 0 | virtual_host.set_name(domain); |
1193 | 0 | virtual_host.add_domains(domain); |
1194 | 0 | virtual_host.add_routes()->mutable_match()->set_prefix(prefix); |
1195 | 0 | auto* route = virtual_host.mutable_routes(0)->mutable_route(); |
1196 | 0 | route->set_cluster(cluster); |
1197 | 0 | return virtual_host; |
1198 | 0 | } |
1199 | | |
1200 | 0 | void ConfigHelper::addVirtualHost(const envoy::config::route::v3::VirtualHost& vhost) { |
1201 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1202 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1203 | 0 | hcm_config; |
1204 | 0 | loadHttpConnectionManager(hcm_config); |
1205 | 0 | auto route_config = hcm_config.mutable_route_config(); |
1206 | 0 | auto* virtual_host = route_config->add_virtual_hosts(); |
1207 | 0 | virtual_host->CopyFrom(vhost); |
1208 | 0 | storeHttpConnectionManager(hcm_config); |
1209 | 0 | } |
1210 | | |
1211 | 0 | void ConfigHelper::addFilter(const std::string& config) { prependFilter(config); } |
1212 | | |
1213 | 403 | void ConfigHelper::prependFilter(const std::string& config, bool downstream) { |
1214 | 403 | RELEASE_ASSERT(!finalized_, ""); |
1215 | 403 | if (downstream) { |
1216 | 403 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1217 | 403 | hcm_config; |
1218 | 403 | loadHttpConnectionManager(hcm_config); |
1219 | | |
1220 | 403 | auto* filter_list_back = hcm_config.add_http_filters(); |
1221 | 403 | #ifdef ENVOY_ENABLE_YAML |
1222 | 403 | TestUtility::loadFromYaml(config, *filter_list_back); |
1223 | | #else |
1224 | | UNREFERENCED_PARAMETER(config); |
1225 | | UNREFERENCED_PARAMETER(filter_list_back); |
1226 | | PANIC("YAML support compiled out"); |
1227 | | #endif |
1228 | | |
1229 | | // Now move it to the front. |
1230 | 806 | for (int i = hcm_config.http_filters_size() - 1; i > 0; --i) { |
1231 | 403 | hcm_config.mutable_http_filters()->SwapElements(i, i - 1); |
1232 | 403 | } |
1233 | 403 | storeHttpConnectionManager(hcm_config); |
1234 | 403 | return; |
1235 | 403 | } |
1236 | | |
1237 | 0 | auto* static_resources = bootstrap_.mutable_static_resources(); |
1238 | 0 | for (int i = 0; i < static_resources->clusters_size(); ++i) { |
1239 | 0 | auto* cluster = static_resources->mutable_clusters(i); |
1240 | |
|
1241 | 0 | HttpProtocolOptions old_protocol_options; |
1242 | 0 | if (cluster->typed_extension_protocol_options().contains( |
1243 | 0 | "envoy.extensions.upstreams.http.v3.HttpProtocolOptions")) { |
1244 | 0 | old_protocol_options = MessageUtil::anyConvert<ConfigHelper::HttpProtocolOptions>( |
1245 | 0 | (*cluster->mutable_typed_extension_protocol_options()) |
1246 | 0 | ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"]); |
1247 | 0 | } |
1248 | 0 | if (old_protocol_options.http_filters().empty()) { |
1249 | 0 | auto* codec_filter = old_protocol_options.add_http_filters(); |
1250 | 0 | codec_filter->set_name("envoy.filters.http.upstream_codec"); |
1251 | 0 | codec_filter->mutable_typed_config()->PackFrom( |
1252 | 0 | envoy::extensions::filters::http::upstream_codec::v3::UpstreamCodec::default_instance()); |
1253 | 0 | } |
1254 | 0 | auto* filter_list_back = old_protocol_options.add_http_filters(); |
1255 | 0 | #ifdef ENVOY_ENABLE_YAML |
1256 | 0 | TestUtility::loadFromYaml(config, *filter_list_back); |
1257 | | #else |
1258 | | UNREFERENCED_PARAMETER(filter_list_back); |
1259 | | PANIC("YAML support compiled out"); |
1260 | | #endif |
1261 | 0 | for (int i = old_protocol_options.http_filters_size() - 1; i > 0; --i) { |
1262 | 0 | old_protocol_options.mutable_http_filters()->SwapElements(i, i - 1); |
1263 | 0 | } |
1264 | 0 | (*cluster->mutable_typed_extension_protocol_options()) |
1265 | 0 | ["envoy.extensions.upstreams.http.v3.HttpProtocolOptions"] |
1266 | 0 | .PackFrom(old_protocol_options); |
1267 | 0 | } |
1268 | 0 | } |
1269 | | |
1270 | | void ConfigHelper::setClientCodec(envoy::extensions::filters::network::http_connection_manager::v3:: |
1271 | 3.07k | HttpConnectionManager::CodecType type) { |
1272 | 3.07k | RELEASE_ASSERT(!finalized_, ""); |
1273 | 3.07k | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1274 | 3.07k | hcm_config; |
1275 | 3.07k | if (loadHttpConnectionManager(hcm_config)) { |
1276 | 3.06k | hcm_config.set_codec_type(type); |
1277 | 3.06k | storeHttpConnectionManager(hcm_config); |
1278 | 3.06k | } |
1279 | 3.07k | } |
1280 | | |
1281 | | void ConfigHelper::configDownstreamTransportSocketWithTls( |
1282 | | envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
1283 | | std::function<void(envoy::extensions::transport_sockets::tls::v3::CommonTlsContext&)> |
1284 | | configure_tls_context, |
1285 | 0 | bool enable_quic_early_data) { |
1286 | 0 | for (auto& listener : *bootstrap.mutable_static_resources()->mutable_listeners()) { |
1287 | 0 | ASSERT(listener.filter_chains_size() > 0); |
1288 | 0 | auto* filter_chain = listener.mutable_filter_chains(0); |
1289 | 0 | auto* transport_socket = filter_chain->mutable_transport_socket(); |
1290 | 0 | if (listener.has_udp_listener_config() && listener.udp_listener_config().has_quic_options()) { |
1291 | 0 | transport_socket->set_name("envoy.transport_sockets.quic"); |
1292 | 0 | envoy::extensions::transport_sockets::quic::v3::QuicDownstreamTransport |
1293 | 0 | quic_transport_socket_config; |
1294 | 0 | configure_tls_context(*quic_transport_socket_config.mutable_downstream_tls_context() |
1295 | 0 | ->mutable_common_tls_context()); |
1296 | 0 | quic_transport_socket_config.mutable_enable_early_data()->set_value(enable_quic_early_data); |
1297 | 0 | transport_socket->mutable_typed_config()->PackFrom(quic_transport_socket_config); |
1298 | 0 | } else if (!listener.has_udp_listener_config()) { |
1299 | 0 | transport_socket->set_name("envoy.transport_sockets.tls"); |
1300 | 0 | envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext tls_context; |
1301 | 0 | configure_tls_context(*tls_context.mutable_common_tls_context()); |
1302 | 0 | transport_socket->mutable_typed_config()->PackFrom(tls_context); |
1303 | 0 | } |
1304 | 0 | } |
1305 | 0 | } |
1306 | | |
1307 | 0 | void ConfigHelper::addSslConfig(const ServerSslOptions& options) { |
1308 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1309 | | |
1310 | 0 | auto* filter_chain = |
1311 | 0 | bootstrap_.mutable_static_resources()->mutable_listeners(0)->mutable_filter_chains(0); |
1312 | 0 | envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext tls_context; |
1313 | 0 | initializeTls(options, *tls_context.mutable_common_tls_context(), false); |
1314 | 0 | if (options.ocsp_staple_required_) { |
1315 | 0 | tls_context.set_ocsp_staple_policy( |
1316 | 0 | envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::MUST_STAPLE); |
1317 | 0 | } |
1318 | 0 | tls_context.set_prefer_client_ciphers(options.prefer_client_ciphers_); |
1319 | 0 | filter_chain->mutable_transport_socket()->set_name("envoy.transport_sockets.tls"); |
1320 | 0 | filter_chain->mutable_transport_socket()->mutable_typed_config()->PackFrom(tls_context); |
1321 | 0 | } |
1322 | | |
1323 | | void ConfigHelper::addQuicDownstreamTransportSocketConfig( |
1324 | 0 | bool enable_early_data, std::vector<absl::string_view> custom_alpns) { |
1325 | 0 | for (auto& listener : *bootstrap_.mutable_static_resources()->mutable_listeners()) { |
1326 | 0 | if (listener.udp_listener_config().has_quic_options()) { |
1327 | | // Disable SO_REUSEPORT, because it undesirably allows parallel test jobs to use the same |
1328 | | // port. |
1329 | 0 | listener.mutable_enable_reuse_port()->set_value(false); |
1330 | 0 | } |
1331 | 0 | } |
1332 | 0 | configDownstreamTransportSocketWithTls( |
1333 | 0 | bootstrap_, |
1334 | 0 | [&](envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_tls_context) { |
1335 | 0 | initializeTls(ServerSslOptions().setRsaCert(true).setTlsV13(true), common_tls_context, |
1336 | 0 | true); |
1337 | 0 | for (absl::string_view alpn : custom_alpns) { |
1338 | 0 | common_tls_context.add_alpn_protocols(alpn); |
1339 | 0 | } |
1340 | 0 | }, |
1341 | 0 | enable_early_data); |
1342 | 0 | } |
1343 | | |
1344 | | bool ConfigHelper::setAccessLog( |
1345 | | const std::string& filename, absl::string_view format, |
1346 | 0 | std::vector<envoy::config::core::v3::TypedExtensionConfig> formatters) { |
1347 | 0 | if (getFilterFromListener("http") == nullptr) { |
1348 | 0 | return false; |
1349 | 0 | } |
1350 | | // Replace null device with a real path for the file access log. |
1351 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1352 | 0 | hcm_config; |
1353 | 0 | loadHttpConnectionManager(hcm_config); |
1354 | 0 | envoy::extensions::access_loggers::file::v3::FileAccessLog access_log_config; |
1355 | 0 | if (!format.empty()) { |
1356 | 0 | auto* log_format = access_log_config.mutable_log_format(); |
1357 | 0 | log_format->mutable_text_format_source()->set_inline_string(absl::StrCat(format, "\n")); |
1358 | 0 | if (!formatters.empty()) { |
1359 | 0 | for (const auto& formatter : formatters) { |
1360 | 0 | auto* added_formatter = log_format->add_formatters(); |
1361 | 0 | added_formatter->CopyFrom(formatter); |
1362 | 0 | } |
1363 | 0 | } |
1364 | 0 | } |
1365 | 0 | access_log_config.set_path(filename); |
1366 | 0 | hcm_config.mutable_access_log(0)->mutable_typed_config()->PackFrom(access_log_config); |
1367 | 0 | storeHttpConnectionManager(hcm_config); |
1368 | 0 | return true; |
1369 | 0 | } |
1370 | | |
1371 | 0 | bool ConfigHelper::setListenerAccessLog(const std::string& filename, absl::string_view format) { |
1372 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1373 | 0 | if (bootstrap_.mutable_static_resources()->listeners_size() == 0) { |
1374 | 0 | return false; |
1375 | 0 | } |
1376 | 0 | envoy::extensions::access_loggers::file::v3::FileAccessLog access_log_config; |
1377 | 0 | if (!format.empty()) { |
1378 | 0 | access_log_config.mutable_log_format()->mutable_text_format_source()->set_inline_string( |
1379 | 0 | std::string(format)); |
1380 | 0 | } |
1381 | 0 | access_log_config.set_path(filename); |
1382 | 0 | bootstrap_.mutable_static_resources() |
1383 | 0 | ->mutable_listeners(0) |
1384 | 0 | ->add_access_log() |
1385 | 0 | ->mutable_typed_config() |
1386 | 0 | ->PackFrom(access_log_config); |
1387 | 0 | return true; |
1388 | 0 | } |
1389 | | |
1390 | | void ConfigHelper::initializeTlsKeyLog( |
1391 | | envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& tls_context, |
1392 | 0 | const ServerSslOptions& options) { |
1393 | 0 | if (options.keylog_path_.empty()) { |
1394 | 0 | return; |
1395 | 0 | } |
1396 | 0 | auto tls_keylog_path = tls_context.mutable_key_log()->mutable_path(); |
1397 | 0 | *tls_keylog_path = options.keylog_path_; |
1398 | |
|
1399 | 0 | if (options.keylog_local_filter_) { |
1400 | 0 | auto tls_keylog_local = tls_context.mutable_key_log()->mutable_local_address_range(); |
1401 | 0 | auto new_element_local = tls_keylog_local->Add(); |
1402 | 0 | if (options.keylog_local_negative_) { |
1403 | 0 | if (options.ip_version_ == Network::Address::IpVersion::v6) { |
1404 | 0 | new_element_local->set_address_prefix("1::2"); |
1405 | 0 | new_element_local->mutable_prefix_len()->set_value(128); |
1406 | 0 | } else { |
1407 | 0 | new_element_local->set_address_prefix("127.0.0.2"); |
1408 | 0 | new_element_local->mutable_prefix_len()->set_value(32); |
1409 | 0 | } |
1410 | 0 | } else { |
1411 | 0 | new_element_local->set_address_prefix( |
1412 | 0 | Network::Test::getLoopbackAddressString(options.ip_version_)); |
1413 | 0 | if (options.keylog_multiple_ips_) { |
1414 | 0 | auto more_local = tls_keylog_local->Add(); |
1415 | 0 | if (options.ip_version_ == Network::Address::IpVersion::v6) { |
1416 | 0 | more_local->set_address_prefix("1::2"); |
1417 | 0 | more_local->mutable_prefix_len()->set_value(128); |
1418 | 0 | } else { |
1419 | 0 | more_local->set_address_prefix("127.0.0.2"); |
1420 | 0 | more_local->mutable_prefix_len()->set_value(32); |
1421 | 0 | } |
1422 | 0 | } |
1423 | 0 | } |
1424 | 0 | } |
1425 | |
|
1426 | 0 | if (options.keylog_remote_filter_) { |
1427 | 0 | auto tls_keylog_remote = tls_context.mutable_key_log()->mutable_remote_address_range(); |
1428 | 0 | auto new_element_remote = tls_keylog_remote->Add(); |
1429 | 0 | if (options.keylog_remote_negative_) { |
1430 | 0 | if (options.ip_version_ == Network::Address::IpVersion::v6) { |
1431 | 0 | new_element_remote->set_address_prefix("1::2"); |
1432 | 0 | new_element_remote->mutable_prefix_len()->set_value(128); |
1433 | 0 | } else { |
1434 | 0 | new_element_remote->set_address_prefix("127.0.0.2"); |
1435 | 0 | new_element_remote->mutable_prefix_len()->set_value(32); |
1436 | 0 | } |
1437 | 0 | } else { |
1438 | 0 | new_element_remote->set_address_prefix( |
1439 | 0 | Network::Test::getLoopbackAddressString(options.ip_version_)); |
1440 | 0 | if (options.keylog_multiple_ips_) { |
1441 | 0 | auto more_remote = tls_keylog_remote->Add(); |
1442 | 0 | if (options.ip_version_ == Network::Address::IpVersion::v6) { |
1443 | 0 | more_remote->set_address_prefix("1::2"); |
1444 | 0 | more_remote->mutable_prefix_len()->set_value(128); |
1445 | 0 | } else { |
1446 | 0 | more_remote->set_address_prefix("127.0.0.2"); |
1447 | 0 | more_remote->mutable_prefix_len()->set_value(32); |
1448 | 0 | } |
1449 | 0 | } |
1450 | 0 | } |
1451 | 0 | } |
1452 | 0 | } |
1453 | | |
1454 | | void ConfigHelper::initializeTls( |
1455 | | const ServerSslOptions& options, |
1456 | | envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_tls_context, |
1457 | 0 | bool http3) { |
1458 | 0 | if (!http3) { |
1459 | | // If it's HTTP/3, leave it empty as QUIC will derive the supported ALPNs from QUIC version by |
1460 | | // default. |
1461 | 0 | common_tls_context.add_alpn_protocols(Http::Utility::AlpnNames::get().Http2); |
1462 | 0 | common_tls_context.add_alpn_protocols(Http::Utility::AlpnNames::get().Http11); |
1463 | 0 | } |
1464 | |
|
1465 | 0 | auto* validation_context = common_tls_context.mutable_validation_context(); |
1466 | 0 | if (options.custom_validator_config_) { |
1467 | 0 | validation_context->set_allocated_custom_validator_config(options.custom_validator_config_); |
1468 | 0 | } else { |
1469 | 0 | if (options.client_with_intermediate_cert_) { |
1470 | 0 | validation_context->add_verify_certificate_hash(TEST_CLIENT2_CERT_HASH); |
1471 | 0 | std::string cert_yaml; |
1472 | 0 | if (options.trust_root_only_) { |
1473 | 0 | cert_yaml = R"EOF( |
1474 | 0 | trusted_ca: |
1475 | 0 | filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" |
1476 | 0 | )EOF"; |
1477 | 0 | } else { |
1478 | 0 | cert_yaml = R"EOF( |
1479 | 0 | trusted_ca: |
1480 | 0 | filename: "{{ test_rundir }}/test/config/integration/certs/intermediate_partial_ca_cert_chain.pem" |
1481 | 0 | )EOF"; |
1482 | 0 | } |
1483 | 0 | #ifdef ENVOY_ENABLE_YAML |
1484 | 0 | TestUtility::loadFromYaml(TestEnvironment::substitute(cert_yaml), *validation_context); |
1485 | | #else |
1486 | | UNREFERENCED_PARAMETER(cert_yaml); |
1487 | | PANIC("YAML support compiled out"); |
1488 | | #endif |
1489 | 0 | if (options.max_verify_depth_.has_value()) { |
1490 | 0 | validation_context->mutable_max_verify_depth()->set_value( |
1491 | 0 | options.max_verify_depth_.value()); |
1492 | 0 | } |
1493 | 0 | } else { |
1494 | 0 | validation_context->mutable_trusted_ca()->set_filename( |
1495 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/cacert.pem")); |
1496 | 0 | validation_context->add_verify_certificate_hash( |
1497 | 0 | options.expect_client_ecdsa_cert_ ? TEST_CLIENT_ECDSA_CERT_HASH : TEST_CLIENT_CERT_HASH); |
1498 | 0 | } |
1499 | 0 | } |
1500 | 0 | validation_context->set_allow_expired_certificate(options.allow_expired_certificate_); |
1501 | | |
1502 | | // We'll negotiate up to TLSv1.3 for the tests that care, but it really |
1503 | | // depends on what the client sets. |
1504 | 0 | common_tls_context.mutable_tls_params()->set_tls_maximum_protocol_version( |
1505 | 0 | options.tlsv1_3_ ? envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_3 |
1506 | 0 | : envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_2); |
1507 | 0 | for (const auto& curve : options.curves_) { |
1508 | 0 | common_tls_context.mutable_tls_params()->add_ecdh_curves(curve); |
1509 | 0 | } |
1510 | 0 | for (const auto& cipher : options.ciphers_) { |
1511 | 0 | common_tls_context.mutable_tls_params()->add_cipher_suites(cipher); |
1512 | 0 | } |
1513 | 0 | if (options.rsa_cert_) { |
1514 | 0 | auto* tls_certificate = common_tls_context.add_tls_certificates(); |
1515 | 0 | tls_certificate->mutable_certificate_chain()->set_filename( |
1516 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/servercert.pem")); |
1517 | 0 | tls_certificate->mutable_private_key()->set_filename( |
1518 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/serverkey.pem")); |
1519 | 0 | if (options.rsa_cert_ocsp_staple_) { |
1520 | 0 | tls_certificate->mutable_ocsp_staple()->set_filename( |
1521 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/server_ocsp_resp.der")); |
1522 | 0 | } |
1523 | 0 | } |
1524 | 0 | if (options.ecdsa_cert_) { |
1525 | 0 | auto* tls_certificate = common_tls_context.add_tls_certificates(); |
1526 | 0 | tls_certificate->mutable_certificate_chain()->set_filename( |
1527 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/server_ecdsacert.pem")); |
1528 | 0 | tls_certificate->mutable_private_key()->set_filename( |
1529 | 0 | TestEnvironment::runfilesPath("test/config/integration/certs/server_ecdsakey.pem")); |
1530 | 0 | if (options.ecdsa_cert_ocsp_staple_) { |
1531 | 0 | tls_certificate->mutable_ocsp_staple()->set_filename(TestEnvironment::runfilesPath( |
1532 | 0 | "test/config/integration/certs/server_ecdsa_ocsp_resp.der")); |
1533 | 0 | } |
1534 | 0 | } |
1535 | |
|
1536 | 0 | if (!options.san_matchers_.empty()) { |
1537 | 0 | *validation_context->mutable_match_typed_subject_alt_names() = {options.san_matchers_.begin(), |
1538 | 0 | options.san_matchers_.end()}; |
1539 | 0 | } |
1540 | 0 | if (!options.tls_cert_selector_yaml_.empty()) { |
1541 | 0 | auto* cert_selector = common_tls_context.mutable_custom_tls_certificate_selector(); |
1542 | 0 | #ifdef ENVOY_ENABLE_YAML |
1543 | 0 | TestUtility::loadFromYaml(TestEnvironment::substitute(options.tls_cert_selector_yaml_), |
1544 | 0 | *cert_selector); |
1545 | | #else |
1546 | | UNREFERENCED_PARAMETER(cert_selector); |
1547 | | PANIC("YAML support compiled out"); |
1548 | | #endif |
1549 | 0 | } |
1550 | 0 | initializeTlsKeyLog(common_tls_context, options); |
1551 | 0 | } |
1552 | | |
1553 | 1.97k | void ConfigHelper::renameListener(const std::string& name) { |
1554 | 1.97k | auto* static_resources = bootstrap_.mutable_static_resources(); |
1555 | 1.97k | if (static_resources->listeners_size() > 0) { |
1556 | 1.96k | static_resources->mutable_listeners(0)->set_name(name); |
1557 | 1.96k | } |
1558 | 1.97k | } |
1559 | | |
1560 | 10.4k | envoy::config::listener::v3::Filter* ConfigHelper::getFilterFromListener(const std::string& name) { |
1561 | 10.4k | RELEASE_ASSERT(!finalized_, ""); |
1562 | 10.4k | if (bootstrap_.mutable_static_resources()->listeners_size() == 0) { |
1563 | 14 | return nullptr; |
1564 | 14 | } |
1565 | 10.4k | auto* listener = bootstrap_.mutable_static_resources()->mutable_listeners(0); |
1566 | 10.4k | if (listener->filter_chains_size() == 0) { |
1567 | 0 | return nullptr; |
1568 | 0 | } |
1569 | 10.4k | auto* filter_chain = listener->mutable_filter_chains(0); |
1570 | 10.4k | for (ssize_t i = 0; i < filter_chain->filters_size(); i++) { |
1571 | 10.4k | if (filter_chain->mutable_filters(i)->name() == name) { |
1572 | 10.4k | return filter_chain->mutable_filters(i); |
1573 | 10.4k | } |
1574 | 10.4k | } |
1575 | 0 | return nullptr; |
1576 | 10.4k | } |
1577 | | |
1578 | | envoy::config::listener::v3::ListenerFilter* |
1579 | 0 | ConfigHelper::getListenerFilterFromListener(const std::string& name) { |
1580 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1581 | 0 | if (bootstrap_.mutable_static_resources()->listeners_size() == 0) { |
1582 | 0 | return nullptr; |
1583 | 0 | } |
1584 | 0 | auto* listener = bootstrap_.mutable_static_resources()->mutable_listeners(0); |
1585 | 0 | for (ssize_t i = 0; i < listener->listener_filters_size(); i++) { |
1586 | 0 | if (listener->mutable_listener_filters(i)->name() == name) { |
1587 | 0 | return listener->mutable_listener_filters(i); |
1588 | 0 | } |
1589 | 0 | } |
1590 | 0 | return nullptr; |
1591 | 0 | } |
1592 | | |
1593 | 0 | void ConfigHelper::addNetworkFilter(const std::string& filter_yaml) { |
1594 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1595 | 0 | auto* filter_chain = |
1596 | 0 | bootstrap_.mutable_static_resources()->mutable_listeners(0)->mutable_filter_chains(0); |
1597 | 0 | auto* filter_list_back = filter_chain->add_filters(); |
1598 | 0 | #ifdef ENVOY_ENABLE_YAML |
1599 | 0 | TestUtility::loadFromYaml(filter_yaml, *filter_list_back); |
1600 | | #else |
1601 | | UNREFERENCED_PARAMETER(filter_list_back); |
1602 | | UNREFERENCED_PARAMETER(filter_yaml); |
1603 | | PANIC("YAML support compiled out"); |
1604 | | #endif |
1605 | | |
1606 | | // Now move it to the front. |
1607 | 0 | for (int i = filter_chain->filters_size() - 1; i > 0; --i) { |
1608 | 0 | filter_chain->mutable_filters()->SwapElements(i, i - 1); |
1609 | 0 | } |
1610 | 0 | } |
1611 | | |
1612 | 0 | void ConfigHelper::addListenerFilter(const std::string& filter_yaml) { |
1613 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1614 | 0 | auto* listener = bootstrap_.mutable_static_resources()->mutable_listeners(0); |
1615 | 0 | auto* filter_list_back = listener->add_listener_filters(); |
1616 | 0 | #ifdef ENVOY_ENABLE_YAML |
1617 | 0 | TestUtility::loadFromYaml(filter_yaml, *filter_list_back); |
1618 | | #else |
1619 | | UNREFERENCED_PARAMETER(filter_list_back); |
1620 | | UNREFERENCED_PARAMETER(filter_yaml); |
1621 | | PANIC("YAML support compiled out"); |
1622 | | #endif |
1623 | | |
1624 | | // Now move it to the front. |
1625 | 0 | for (int i = listener->listener_filters_size() - 1; i > 0; --i) { |
1626 | 0 | listener->mutable_listener_filters()->SwapElements(i, i - 1); |
1627 | 0 | } |
1628 | 0 | } |
1629 | | |
1630 | 0 | void ConfigHelper::addBootstrapExtension(const std::string& config) { |
1631 | 0 | RELEASE_ASSERT(!finalized_, ""); |
1632 | 0 | auto* extension = bootstrap_.add_bootstrap_extensions(); |
1633 | 0 | #ifdef ENVOY_ENABLE_YAML |
1634 | 0 | TestUtility::loadFromYaml(config, *extension); |
1635 | | #else |
1636 | | UNREFERENCED_PARAMETER(extension); |
1637 | | UNREFERENCED_PARAMETER(config); |
1638 | | PANIC("YAML support compiled out"); |
1639 | | #endif |
1640 | 0 | } |
1641 | | |
1642 | | bool ConfigHelper::loadHttpConnectionManager( |
1643 | 5.04k | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& hcm) { |
1644 | 5.04k | return loadFilter< |
1645 | 5.04k | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager>( |
1646 | 5.04k | "http", hcm); |
1647 | 5.04k | } |
1648 | | |
1649 | | void ConfigHelper::storeHttpConnectionManager( |
1650 | | const envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& |
1651 | 5.02k | hcm) { |
1652 | 5.02k | return storeFilter< |
1653 | 5.02k | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager>( |
1654 | 5.02k | "http", hcm); |
1655 | 5.02k | } |
1656 | | |
1657 | 0 | bool ConfigHelper::loadUdpProxyFilter(UdpProxyConfig& udp_proxy) { |
1658 | 0 | return loadListenerFilter<UdpProxyConfig>("udp_proxy", udp_proxy); |
1659 | 0 | } |
1660 | | |
1661 | 0 | void ConfigHelper::storeUdpProxyFilter(const UdpProxyConfig& udp_proxy) { |
1662 | 0 | return storeListenerFilter<UdpProxyConfig>("udp_proxy", udp_proxy); |
1663 | 0 | } |
1664 | | |
1665 | 5.01k | void ConfigHelper::addConfigModifier(ConfigModifierFunction function) { |
1666 | 5.01k | RELEASE_ASSERT(!finalized_, ""); |
1667 | 5.01k | config_modifiers_.push_back(std::move(function)); |
1668 | 5.01k | } |
1669 | | |
1670 | 1.16k | void ConfigHelper::addConfigModifier(HttpModifierFunction function) { |
1671 | 1.16k | addConfigModifier([function, this](envoy::config::bootstrap::v3::Bootstrap&) -> void { |
1672 | 1.16k | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1673 | 1.16k | hcm_config; |
1674 | 1.16k | if (!loadHttpConnectionManager(hcm_config)) { |
1675 | 0 | return; |
1676 | 0 | } |
1677 | 1.16k | function(hcm_config); |
1678 | 1.16k | storeHttpConnectionManager(hcm_config); |
1679 | 1.16k | }); |
1680 | 1.16k | } |
1681 | | |
1682 | 0 | void ConfigHelper::addConfigModifier(UdpProxyModifierFunction function) { |
1683 | 0 | addConfigModifier([function, this](envoy::config::bootstrap::v3::Bootstrap&) -> void { |
1684 | 0 | UdpProxyConfig udp_proxy_config; |
1685 | 0 | if (!loadUdpProxyFilter(udp_proxy_config)) { |
1686 | 0 | return; |
1687 | 0 | } |
1688 | 0 | function(udp_proxy_config); |
1689 | 0 | storeUdpProxyFilter(udp_proxy_config); |
1690 | 0 | }); |
1691 | 0 | } |
1692 | | |
1693 | 0 | void ConfigHelper::setLds(absl::string_view version_info) { |
1694 | 0 | applyConfigModifiers(); |
1695 | |
|
1696 | 0 | envoy::service::discovery::v3::DiscoveryResponse lds; |
1697 | 0 | lds.set_version_info(std::string(version_info)); |
1698 | 0 | for (auto& listener : bootstrap_.static_resources().listeners()) { |
1699 | 0 | ProtobufWkt::Any* resource = lds.add_resources(); |
1700 | 0 | resource->PackFrom(listener); |
1701 | 0 | } |
1702 | |
|
1703 | 0 | const std::string lds_filename = |
1704 | 0 | bootstrap().dynamic_resources().lds_config().path_config_source().path(); |
1705 | 0 | #ifdef ENVOY_ENABLE_YAML |
1706 | 0 | std::string file = TestEnvironment::writeStringToFileForTest( |
1707 | 0 | "new_lds_file", MessageUtil::getJsonStringFromMessageOrError(lds)); |
1708 | 0 | TestEnvironment::renameFile(file, lds_filename); |
1709 | | #else |
1710 | | UNREFERENCED_PARAMETER(lds_filename); |
1711 | | PANIC("YAML support compiled out"); |
1712 | | #endif |
1713 | 0 | } |
1714 | | |
1715 | | void ConfigHelper::setDownstreamOutboundFramesLimits(uint32_t max_all_frames, |
1716 | 0 | uint32_t max_control_frames) { |
1717 | 0 | auto filter = getFilterFromListener("http"); |
1718 | 0 | if (filter) { |
1719 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1720 | 0 | hcm_config; |
1721 | 0 | loadHttpConnectionManager(hcm_config); |
1722 | 0 | if (hcm_config.codec_type() == envoy::extensions::filters::network::http_connection_manager:: |
1723 | 0 | v3::HttpConnectionManager::HTTP2) { |
1724 | 0 | auto* options = hcm_config.mutable_http2_protocol_options(); |
1725 | 0 | options->mutable_max_outbound_frames()->set_value(max_all_frames); |
1726 | 0 | options->mutable_max_outbound_control_frames()->set_value(max_control_frames); |
1727 | 0 | storeHttpConnectionManager(hcm_config); |
1728 | 0 | } |
1729 | 0 | } |
1730 | 0 | } |
1731 | | |
1732 | | void ConfigHelper::setUpstreamOutboundFramesLimits(uint32_t max_all_frames, |
1733 | 0 | uint32_t max_control_frames) { |
1734 | 0 | addConfigModifier( |
1735 | 0 | [max_all_frames, max_control_frames](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { |
1736 | 0 | ConfigHelper::HttpProtocolOptions protocol_options; |
1737 | 0 | auto* http_protocol_options = |
1738 | 0 | protocol_options.mutable_explicit_http_config()->mutable_http2_protocol_options(); |
1739 | 0 | http_protocol_options->mutable_max_outbound_frames()->set_value(max_all_frames); |
1740 | 0 | http_protocol_options->mutable_max_outbound_control_frames()->set_value(max_control_frames); |
1741 | 0 | ConfigHelper::setProtocolOptions(*bootstrap.mutable_static_resources()->mutable_clusters(0), |
1742 | 0 | protocol_options); |
1743 | 0 | }); |
1744 | 0 | } |
1745 | | |
1746 | | void ConfigHelper::setLocalReply( |
1747 | | const envoy::extensions::filters::network::http_connection_manager::v3::LocalReplyConfig& |
1748 | 0 | config) { |
1749 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager |
1750 | 0 | hcm_config; |
1751 | 0 | loadHttpConnectionManager(hcm_config); |
1752 | 0 | hcm_config.mutable_local_reply_config()->MergeFrom(config); |
1753 | 0 | storeHttpConnectionManager(hcm_config); |
1754 | 0 | } |
1755 | | |
1756 | | void ConfigHelper::adjustUpstreamTimeoutForTsan( |
1757 | 0 | envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager& hcm) { |
1758 | 0 | auto* route = |
1759 | 0 | hcm.mutable_route_config()->mutable_virtual_hosts(0)->mutable_routes(0)->mutable_route(); |
1760 | 0 | uint64_t timeout_ms = PROTOBUF_GET_MS_OR_DEFAULT(*route, timeout, 15000u); |
1761 | 0 | auto* timeout = route->mutable_timeout(); |
1762 | | // QUIC stream processing is slow under TSAN. Use larger timeout to prevent |
1763 | | // response_timeout. |
1764 | 0 | timeout->set_seconds(TIMEOUT_FACTOR * timeout_ms / 1000); |
1765 | 0 | } |
1766 | | |
1767 | | envoy::config::core::v3::Http3ProtocolOptions ConfigHelper::http2ToHttp3ProtocolOptions( |
1768 | | const envoy::config::core::v3::Http2ProtocolOptions& http2_options, |
1769 | 815 | size_t http3_max_stream_receive_window) { |
1770 | 815 | envoy::config::core::v3::Http3ProtocolOptions http3_options; |
1771 | 815 | if (http2_options.has_initial_stream_window_size() && |
1772 | 815 | http2_options.initial_stream_window_size().value() < http3_max_stream_receive_window) { |
1773 | | // Set http3 stream flow control window only if the configured http2 stream flow control |
1774 | | // window is smaller than the upper limit of flow control window supported by QUICHE which is |
1775 | | // also the default for http3 streams. |
1776 | 0 | http3_options.mutable_quic_protocol_options()->mutable_initial_stream_window_size()->set_value( |
1777 | 0 | http2_options.initial_stream_window_size().value()); |
1778 | 0 | } |
1779 | 815 | if (http2_options.has_override_stream_error_on_invalid_http_message()) { |
1780 | 815 | http3_options.mutable_override_stream_error_on_invalid_http_message()->set_value( |
1781 | 815 | http2_options.override_stream_error_on_invalid_http_message().value()); |
1782 | 815 | } else if (http2_options.stream_error_on_invalid_http_messaging()) { |
1783 | 0 | http3_options.mutable_override_stream_error_on_invalid_http_message()->set_value(true); |
1784 | 0 | } |
1785 | 815 | return http3_options; |
1786 | 815 | } |
1787 | | |
1788 | 0 | CdsHelper::CdsHelper() : cds_path_(TestEnvironment::writeStringToFileForTest("cds.pb_text", "")) {} |
1789 | | |
1790 | 0 | void CdsHelper::setCds(const std::vector<envoy::config::cluster::v3::Cluster>& clusters) { |
1791 | | // Write to file the DiscoveryResponse and trigger inotify watch. |
1792 | 0 | envoy::service::discovery::v3::DiscoveryResponse cds_response; |
1793 | 0 | cds_response.set_version_info(std::to_string(cds_version_++)); |
1794 | 0 | cds_response.set_type_url(Config::TypeUrl::get().Cluster); |
1795 | 0 | for (const auto& cluster : clusters) { |
1796 | 0 | cds_response.add_resources()->PackFrom(cluster); |
1797 | 0 | } |
1798 | | // Past the initial write, need move semantics to trigger inotify move event that the |
1799 | | // FilesystemSubscriptionImpl is subscribed to. |
1800 | 0 | std::string path = TestEnvironment::writeStringToFileForTest( |
1801 | 0 | "cds.update.pb_text", MessageUtil::toTextProto(cds_response)); |
1802 | 0 | TestEnvironment::renameFile(path, cds_path_); |
1803 | 0 | } |
1804 | | |
1805 | 0 | EdsHelper::EdsHelper() : eds_path_(TestEnvironment::writeStringToFileForTest("eds.pb_text", "")) { |
1806 | | // cluster.cluster_0.update_success will be incremented on the initial |
1807 | | // load when Envoy comes up. |
1808 | 0 | ++update_successes_; |
1809 | 0 | } |
1810 | | |
1811 | | void EdsHelper::setEds(const std::vector<envoy::config::endpoint::v3::ClusterLoadAssignment>& |
1812 | 0 | cluster_load_assignments) { |
1813 | | // Write to file the DiscoveryResponse and trigger inotify watch. |
1814 | 0 | envoy::service::discovery::v3::DiscoveryResponse eds_response; |
1815 | 0 | eds_response.set_version_info(std::to_string(eds_version_++)); |
1816 | 0 | eds_response.set_type_url(Config::TypeUrl::get().ClusterLoadAssignment); |
1817 | 0 | for (const auto& cluster_load_assignment : cluster_load_assignments) { |
1818 | 0 | eds_response.add_resources()->PackFrom(cluster_load_assignment); |
1819 | 0 | } |
1820 | | // Past the initial write, need move semantics to trigger inotify move event that the |
1821 | | // FilesystemSubscriptionImpl is subscribed to. |
1822 | 0 | std::string path = TestEnvironment::writeStringToFileForTest( |
1823 | 0 | "eds.update.pb_text", MessageUtil::toTextProto(eds_response)); |
1824 | 0 | TestEnvironment::renameFile(path, eds_path_); |
1825 | 0 | } |
1826 | | |
1827 | | void EdsHelper::setEdsAndWait( |
1828 | | const std::vector<envoy::config::endpoint::v3::ClusterLoadAssignment>& cluster_load_assignments, |
1829 | 0 | IntegrationTestServerStats& server_stats) { |
1830 | | // Make sure the last version has been accepted before setting a new one. |
1831 | 0 | server_stats.waitForCounterGe("cluster.cluster_0.update_success", update_successes_); |
1832 | 0 | setEds(cluster_load_assignments); |
1833 | | // Make sure Envoy has consumed the update now that it is running. |
1834 | 0 | ++update_successes_; |
1835 | 0 | server_stats.waitForCounterGe("cluster.cluster_0.update_success", update_successes_); |
1836 | 0 | RELEASE_ASSERT( |
1837 | 0 | update_successes_ == server_stats.counter("cluster.cluster_0.update_success")->value(), ""); |
1838 | 0 | } |
1839 | | |
1840 | | } // namespace Envoy |