forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utility.h
385 lines (302 loc) · 16.4 KB
/
utility.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
#pragma once
#include <chrono>
#include <functional>
#include <string>
#include <vector>
#include "envoy/api/api.h"
#include "envoy/config/bootstrap/v3/bootstrap.pb.h"
#include "envoy/config/cluster/v3/cluster.pb.h"
#include "envoy/config/core/v3/base.pb.h"
#include "envoy/config/endpoint/v3/endpoint.pb.h"
#include "envoy/config/listener/v3/listener_components.pb.h"
#include "envoy/config/route/v3/route_components.pb.h"
#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h"
#include "envoy/extensions/transport_sockets/tls/v3/cert.pb.h"
#include "envoy/extensions/upstreams/http/v3/http_protocol_options.pb.h"
#include "envoy/http/codes.h"
#include "common/config/api_version.h"
#include "common/network/address_impl.h"
#include "common/protobuf/protobuf.h"
#include "common/protobuf/utility.h"
#include "test/integration/server_stats.h"
#include "absl/types/optional.h"
namespace Envoy {
class ConfigHelper {
public:
using HttpConnectionManager =
envoy::extensions::filters::network::http_connection_manager::v3::HttpConnectionManager;
struct ServerSslOptions {
ServerSslOptions& setRsaCert(bool rsa_cert) {
rsa_cert_ = rsa_cert;
return *this;
}
ServerSslOptions& setRsaCertOcspStaple(bool rsa_cert_ocsp_staple) {
rsa_cert_ocsp_staple_ = rsa_cert_ocsp_staple;
return *this;
}
ServerSslOptions& setEcdsaCert(bool ecdsa_cert) {
ecdsa_cert_ = ecdsa_cert;
return *this;
}
ServerSslOptions& setEcdsaCertOcspStaple(bool ecdsa_cert_ocsp_staple) {
ecdsa_cert_ocsp_staple_ = ecdsa_cert_ocsp_staple;
return *this;
}
ServerSslOptions& setOcspStapleRequired(bool ocsp_staple_required) {
ocsp_staple_required_ = ocsp_staple_required;
return *this;
}
ServerSslOptions& setTlsV13(bool tlsv1_3) {
tlsv1_3_ = tlsv1_3;
return *this;
}
ServerSslOptions& setExpectClientEcdsaCert(bool expect_client_ecdsa_cert) {
expect_client_ecdsa_cert_ = expect_client_ecdsa_cert;
return *this;
}
bool rsa_cert_{true};
bool rsa_cert_ocsp_staple_{true};
bool ecdsa_cert_{false};
bool ecdsa_cert_ocsp_staple_{false};
bool ocsp_staple_required_{false};
bool tlsv1_3_{false};
bool expect_client_ecdsa_cert_{false};
};
// Set up basic config, using the specified IpVersion for all connections: listeners, upstream,
// and admin connections.
//
// By default, this runs with an L7 proxy config, but config can be set to TCP_PROXY_CONFIG
// to test L4 proxying.
ConfigHelper(const Network::Address::IpVersion version, Api::Api& api,
const std::string& config = httpProxyConfig());
static void
initializeTls(const ServerSslOptions& options,
envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_context);
using ConfigModifierFunction = std::function<void(envoy::config::bootstrap::v3::Bootstrap&)>;
using HttpModifierFunction = std::function<void(HttpConnectionManager&)>;
// A basic configuration (admin port, cluster_0, one listener) with no network filters.
static std::string baseConfig();
// A basic configuration (admin port, cluster_0, one udp listener) with no network filters.
static std::string baseUdpListenerConfig();
// A string for a tls inspector listener filter which can be used with addListenerFilter()
static std::string tlsInspectorFilter();
// A basic configuration for L4 proxying.
static std::string tcpProxyConfig();
// A basic configuration for L7 proxying.
static std::string httpProxyConfig();
// A basic configuration for L7 proxying with QUIC transport.
static std::string quicHttpProxyConfig();
// A string for a basic buffer filter, which can be used with addFilter()
static std::string defaultBufferFilter();
// A string for a small buffer filter, which can be used with addFilter()
static std::string smallBufferFilter();
// A string for a health check filter which can be used with addFilter()
static std::string defaultHealthCheckFilter();
// A string for a squash filter which can be used with addFilter()
static std::string defaultSquashFilter();
// A string for startTls transport socket config.
static std::string startTlsConfig();
// Configuration for L7 proxying, with clusters cluster_1 and cluster_2 meant to be added via CDS.
// api_type should be REST, GRPC, or DELTA_GRPC.
static std::string discoveredClustersBootstrap(const std::string& api_type);
static std::string adsBootstrap(const std::string& api_type,
envoy::config::core::v3::ApiVersion resource_api_version,
envoy::config::core::v3::ApiVersion transport_api_version =
envoy::config::core::v3::ApiVersion::AUTO);
// Builds a standard Cluster config fragment, with a single endpoint (at address:port).
static envoy::config::cluster::v3::Cluster buildStaticCluster(const std::string& name, int port,
const std::string& address);
// ADS configurations
static envoy::config::cluster::v3::Cluster buildCluster(
const std::string& name, const std::string& lb_policy = "ROUND_ROBIN",
envoy::config::core::v3::ApiVersion api_version = envoy::config::core::v3::ApiVersion::V3);
static envoy::config::cluster::v3::Cluster buildTlsCluster(
const std::string& name, const std::string& lb_policy = "ROUND_ROBIN",
envoy::config::core::v3::ApiVersion api_version = envoy::config::core::v3::ApiVersion::V3);
static envoy::config::endpoint::v3::ClusterLoadAssignment buildClusterLoadAssignment(
const std::string& name, const std::string& ip_version, uint32_t port,
envoy::config::core::v3::ApiVersion api_version = envoy::config::core::v3::ApiVersion::V3);
static envoy::config::listener::v3::Listener buildBaseListener(
const std::string& name, const std::string& address, const std::string& filter_chains = "",
envoy::config::core::v3::ApiVersion api_version = envoy::config::core::v3::ApiVersion::V3);
static envoy::config::listener::v3::Listener buildListener(
const std::string& name, const std::string& route_config, const std::string& address,
const std::string& stat_prefix,
envoy::config::core::v3::ApiVersion api_version = envoy::config::core::v3::ApiVersion::V3);
static envoy::config::route::v3::RouteConfiguration buildRouteConfig(
const std::string& name, const std::string& cluster,
envoy::config::core::v3::ApiVersion api_version = envoy::config::core::v3::ApiVersion::V3);
// Builds a standard Endpoint suitable for population by finalize().
static envoy::config::endpoint::v3::Endpoint buildEndpoint(const std::string& address);
// Run the final config modifiers, and then set the upstream ports based on upstream connections.
// This is the last operation run on |bootstrap_| before it is handed to Envoy.
// Ports are assigned by looping through clusters, hosts, and addresses in the
// order they are stored in |bootstrap_|
void finalize(const std::vector<uint32_t>& ports);
// Set source_address in the bootstrap bind config.
void setSourceAddress(const std::string& address_string);
// Overwrite the first host and route for the primary listener.
void setDefaultHostAndRoute(const std::string& host, const std::string& route);
// Sets byte limits on upstream and downstream connections.
void setBufferLimits(uint32_t upstream_buffer_limit, uint32_t downstream_buffer_limit);
// Set the idle timeout on downstream connections through the HttpConnectionManager.
void setDownstreamHttpIdleTimeout(std::chrono::milliseconds idle_timeout);
// Set the max connection duration for downstream connections through the HttpConnectionManager.
void setDownstreamMaxConnectionDuration(std::chrono::milliseconds max_connection_duration);
// Set the max stream duration for downstream connections through the HttpConnectionManager.
void setDownstreamMaxStreamDuration(std::chrono::milliseconds max_stream_duration);
// Set the connect timeout on upstream connections.
void setConnectTimeout(std::chrono::milliseconds timeout);
envoy::config::route::v3::VirtualHost createVirtualHost(const char* host, const char* route = "/",
const char* cluster = "cluster_0");
void addVirtualHost(const envoy::config::route::v3::VirtualHost& vhost);
// Add an HTTP filter prior to existing filters.
void addFilter(const std::string& filter_yaml);
// Add a network filter prior to existing filters.
void addNetworkFilter(const std::string& filter_yaml);
// Add a listener filter prior to existing filters.
void addListenerFilter(const std::string& filter_yaml);
// Add a new bootstrap extension.
void addBootstrapExtension(const std::string& config);
// Sets the client codec to the specified type.
void setClientCodec(envoy::extensions::filters::network::http_connection_manager::v3::
HttpConnectionManager::CodecType type);
// Add the default SSL configuration.
void addSslConfig(const ServerSslOptions& options);
void addSslConfig() { addSslConfig({}); }
// Set the HTTP access log for the first HCM (if present) to a given file. The default is
// the platform's null device.
bool setAccessLog(const std::string& filename, absl::string_view format = "",
std::vector<envoy::config::core::v3::TypedExtensionConfig> formatters = {});
// Set the listener access log for the first listener to a given file.
bool setListenerAccessLog(const std::string& filename, absl::string_view format = "");
// Renames the first listener to the name specified.
void renameListener(const std::string& name);
// Allows callers to do their own modification to |bootstrap_| which will be
// applied just before ports are modified in finalize().
void addConfigModifier(ConfigModifierFunction function);
// Allows callers to easily modify the HttpConnectionManager configuration.
// Modifiers will be applied just before ports are modified in finalize
void addConfigModifier(HttpModifierFunction function);
// Allows callers to easily modify the filter named 'name' from the first filter chain from the
// first listener. Modifiers will be applied just before ports are modified in finalize
template <class FilterType>
void addFilterConfigModifier(const std::string& name,
std::function<void(Protobuf::Message& filter)> function) {
addConfigModifier([name, function, this](envoy::config::bootstrap::v3::Bootstrap&) -> void {
FilterType filter_config;
loadFilter<FilterType>(name, filter_config);
function(filter_config);
storeFilter<FilterType>(name, filter_config);
});
}
// Apply any outstanding config modifiers, stick all the listeners in a discovery response message
// and write it to the lds file.
void setLds(absl::string_view version_info);
// Set limits on pending downstream outbound frames.
void setDownstreamOutboundFramesLimits(uint32_t max_all_frames, uint32_t max_control_frames);
// Set limits on pending upstream outbound frames.
void setUpstreamOutboundFramesLimits(uint32_t max_all_frames, uint32_t max_control_frames);
// Return the bootstrap configuration for hand-off to Envoy.
const envoy::config::bootstrap::v3::Bootstrap& bootstrap() { return bootstrap_; }
// Allow a finalized configuration to be edited for generating xDS responses
void applyConfigModifiers();
// Configure Envoy to do TLS to upstream.
void configureUpstreamTls(bool use_alpn = false);
// Skip validation that ensures that all upstream ports are referenced by the
// configuration generated in ConfigHelper::finalize.
void skipPortUsageValidation() { skip_port_usage_validation_ = true; }
// Add this key value pair to the static runtime.
void addRuntimeOverride(const std::string& key, const std::string& value);
// Enable deprecated v2 API resources via the runtime.
void enableDeprecatedV2Api();
// Add filter_metadata to a cluster with the given name
void addClusterFilterMetadata(absl::string_view metadata_yaml,
absl::string_view cluster_name = "cluster_0");
// Given an HCM with the default config, set the matcher to be a connect matcher and enable
// CONNECT requests.
static void setConnectConfig(HttpConnectionManager& hcm, bool terminate_connect, bool allow_post);
void setLocalReply(
const envoy::extensions::filters::network::http_connection_manager::v3::LocalReplyConfig&
config);
using HttpProtocolOptions = envoy::extensions::upstreams::http::v3::HttpProtocolOptions;
static void setProtocolOptions(envoy::config::cluster::v3::Cluster& cluster,
HttpProtocolOptions& protocol_options);
static void setHttp2(envoy::config::cluster::v3::Cluster& cluster);
private:
static bool shouldBoost(envoy::config::core::v3::ApiVersion api_version) {
return api_version == envoy::config::core::v3::ApiVersion::V2;
}
static std::string apiVersionStr(envoy::config::core::v3::ApiVersion api_version) {
return api_version == envoy::config::core::v3::ApiVersion::V2 ? "V2" : "V3";
}
// Load the first HCM struct from the first listener into a parsed proto.
bool loadHttpConnectionManager(HttpConnectionManager& hcm);
// Take the contents of the provided HCM proto and stuff them into the first HCM
// struct of the first listener.
void storeHttpConnectionManager(const HttpConnectionManager& hcm);
// Load the first FilterType struct from the first listener into a parsed proto.
template <class FilterType> bool loadFilter(const std::string& name, FilterType& filter) {
RELEASE_ASSERT(!finalized_, "");
auto* filter_config = getFilterFromListener(name);
if (filter_config) {
auto* config = filter_config->mutable_typed_config();
filter = MessageUtil::anyConvert<FilterType>(*config);
return true;
}
return false;
}
// Take the contents of the provided FilterType proto and stuff them into the first FilterType
// struct of the first listener.
template <class FilterType> void storeFilter(const std::string& name, const FilterType& filter) {
RELEASE_ASSERT(!finalized_, "");
auto* filter_config_any = getFilterFromListener(name)->mutable_typed_config();
filter_config_any->PackFrom(filter);
}
// Finds the filter named 'name' from the first filter chain from the first listener.
envoy::config::listener::v3::Filter* getFilterFromListener(const std::string& name);
// Configure a tap transport socket for a cluster/filter chain.
void setTapTransportSocket(const std::string& tap_path, const std::string& type,
envoy::config::core::v3::TransportSocket& transport_socket,
const Protobuf::Message* tls_config);
// The bootstrap proto Envoy will start up with.
envoy::config::bootstrap::v3::Bootstrap bootstrap_;
// The config modifiers added via addConfigModifier() which will be applied in finalize()
std::vector<ConfigModifierFunction> config_modifiers_;
// Track if the connect timeout has been set (to avoid clobbering a custom setting with the
// default).
bool connect_timeout_set_{false};
// Option to disable port usage validation for cases where the number of
// upstream ports created is expected to be larger than the number of
// upstreams in the config.
bool skip_port_usage_validation_{false};
// A sanity check guard to make sure config is not modified after handing it to Envoy.
bool finalized_{false};
};
class CdsHelper {
public:
CdsHelper();
// Set CDS contents on filesystem.
void setCds(const std::vector<envoy::config::cluster::v3::Cluster>& cluster);
const std::string& cds_path() const { return cds_path_; }
private:
const std::string cds_path_;
uint32_t cds_version_{};
};
// Common code for tests that deliver EDS update via the filesystem.
class EdsHelper {
public:
EdsHelper();
// Set EDS contents on filesystem and wait for Envoy to pick this up.
void setEds(const std::vector<envoy::config::endpoint::v3::ClusterLoadAssignment>&
cluster_load_assignments);
void setEdsAndWait(const std::vector<envoy::config::endpoint::v3::ClusterLoadAssignment>&
cluster_load_assignments,
IntegrationTestServerStats& server_stats);
const std::string& eds_path() const { return eds_path_; }
private:
const std::string eds_path_;
uint32_t eds_version_{};
uint32_t update_successes_{};
};
} // namespace Envoy