Line data Source code
1 : #include "source/server/configuration_impl.h"
2 :
3 : #include <chrono>
4 : #include <list>
5 : #include <memory>
6 : #include <string>
7 : #include <vector>
8 :
9 : #include "envoy/common/exception.h"
10 : #include "envoy/config/bootstrap/v3/bootstrap.pb.h"
11 : #include "envoy/config/metrics/v3/stats.pb.h"
12 : #include "envoy/config/trace/v3/http_tracer.pb.h"
13 : #include "envoy/network/connection.h"
14 : #include "envoy/runtime/runtime.h"
15 : #include "envoy/server/instance.h"
16 : #include "envoy/server/tracer_config.h"
17 : #include "envoy/ssl/context_manager.h"
18 :
19 : #include "source/common/access_log/access_log_impl.h"
20 : #include "source/common/common/assert.h"
21 : #include "source/common/common/utility.h"
22 : #include "source/common/config/runtime_utility.h"
23 : #include "source/common/config/utility.h"
24 : #include "source/common/network/socket_option_factory.h"
25 : #include "source/common/protobuf/utility.h"
26 : #include "source/extensions/access_loggers/common/file_access_log_impl.h"
27 :
28 : namespace Envoy {
29 : namespace Server {
30 : namespace Configuration {
31 :
32 : bool FilterChainUtility::buildFilterChain(Network::FilterManager& filter_manager,
33 784 : const Filter::NetworkFilterFactoriesList& factories) {
34 784 : for (const auto& filter_config_provider : factories) {
35 784 : auto config = filter_config_provider->config();
36 784 : if (!config.has_value()) {
37 0 : return false;
38 0 : }
39 :
40 784 : Network::FilterFactoryCb& factory = config.value();
41 784 : factory(filter_manager);
42 784 : }
43 :
44 784 : return filter_manager.initializeReadFilters();
45 784 : }
46 :
47 : bool FilterChainUtility::buildFilterChain(Network::ListenerFilterManager& filter_manager,
48 784 : const Filter::ListenerFilterFactoriesList& factories) {
49 784 : for (const auto& filter_config_provider : factories) {
50 0 : auto config = filter_config_provider->config();
51 0 : if (!config.has_value()) {
52 0 : return false;
53 0 : }
54 0 : auto config_value = config.value();
55 0 : config_value(filter_manager);
56 0 : }
57 :
58 784 : return true;
59 784 : }
60 :
61 : void FilterChainUtility::buildUdpFilterChain(
62 : Network::UdpListenerFilterManager& filter_manager, Network::UdpReadFilterCallbacks& callbacks,
63 0 : const std::vector<Network::UdpListenerFilterFactoryCb>& factories) {
64 0 : for (const Network::UdpListenerFilterFactoryCb& factory : factories) {
65 0 : factory(filter_manager, callbacks);
66 0 : }
67 0 : }
68 :
69 : bool FilterChainUtility::buildQuicFilterChain(
70 : Network::QuicListenerFilterManager& filter_manager,
71 0 : const Filter::QuicListenerFilterFactoriesList& factories) {
72 0 : for (const auto& filter_config_provider : factories) {
73 0 : auto config = filter_config_provider->config();
74 0 : if (!config.has_value()) {
75 0 : return false;
76 0 : }
77 0 : auto config_value = config.value();
78 0 : config_value(filter_manager);
79 0 : }
80 :
81 0 : return true;
82 0 : }
83 :
84 : StatsConfigImpl::StatsConfigImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstrap)
85 131 : : deferred_stat_options_(bootstrap.deferred_stat_options()) {
86 131 : if (bootstrap.has_stats_flush_interval() &&
87 131 : bootstrap.stats_flush_case() !=
88 0 : envoy::config::bootstrap::v3::Bootstrap::STATS_FLUSH_NOT_SET) {
89 0 : throwEnvoyExceptionOrPanic(
90 0 : "Only one of stats_flush_interval or stats_flush_on_admin should be set!");
91 0 : }
92 :
93 131 : flush_interval_ =
94 131 : std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(bootstrap, stats_flush_interval, 5000));
95 :
96 131 : if (bootstrap.stats_flush_case() == envoy::config::bootstrap::v3::Bootstrap::kStatsFlushOnAdmin) {
97 0 : flush_on_admin_ = bootstrap.stats_flush_on_admin();
98 0 : }
99 131 : }
100 :
101 : void MainImpl::initialize(const envoy::config::bootstrap::v3::Bootstrap& bootstrap,
102 : Instance& server,
103 131 : Upstream::ClusterManagerFactory& cluster_manager_factory) {
104 : // In order to support dynamic configuration of tracing providers,
105 : // a former server-wide Tracer singleton has been replaced by
106 : // an Tracer instance per "envoy.filters.network.http_connection_manager" filter.
107 : // Tracing configuration as part of bootstrap config is still supported,
108 : // however, it's become mandatory to process it prior to static Listeners.
109 : // Otherwise, static Listeners will be configured in assumption that
110 : // tracing configuration is missing from the bootstrap config.
111 131 : initializeTracers(bootstrap.tracing(), server);
112 :
113 : // stats_config_ should be set before creating the ClusterManagers so that it is available
114 : // from the ServerFactoryContext when creating the static clusters and stats sinks, where
115 : // stats deferred instantiation setting is read.
116 131 : stats_config_ = std::make_unique<StatsConfigImpl>(bootstrap);
117 :
118 131 : const auto& secrets = bootstrap.static_resources().secrets();
119 131 : ENVOY_LOG(info, "loading {} static secret(s)", secrets.size());
120 201 : for (ssize_t i = 0; i < secrets.size(); i++) {
121 70 : ENVOY_LOG(debug, "static secret #{}: {}", i, secrets[i].name());
122 70 : THROW_IF_NOT_OK(server.secretManager().addStaticSecret(secrets[i]));
123 70 : }
124 :
125 131 : ENVOY_LOG(info, "loading {} cluster(s)", bootstrap.static_resources().clusters().size());
126 131 : cluster_manager_ = cluster_manager_factory.clusterManagerFromProto(bootstrap);
127 :
128 131 : const auto& listeners = bootstrap.static_resources().listeners();
129 131 : ENVOY_LOG(info, "loading {} listener(s)", listeners.size());
130 137 : for (ssize_t i = 0; i < listeners.size(); i++) {
131 19 : ENVOY_LOG(debug, "listener #{}:", i);
132 19 : absl::StatusOr<bool> update_or_error =
133 19 : server.listenerManager().addOrUpdateListener(listeners[i], "", false);
134 19 : if (!update_or_error.status().ok()) {
135 13 : throwEnvoyExceptionOrPanic(std::string(update_or_error.status().message()));
136 13 : }
137 19 : }
138 118 : initializeWatchdogs(bootstrap, server);
139 : // This has to happen after ClusterManager initialization, as it depends on config from
140 : // ClusterManager.
141 118 : initializeStatsConfig(bootstrap, server);
142 118 : }
143 :
144 : void MainImpl::initializeStatsConfig(const envoy::config::bootstrap::v3::Bootstrap& bootstrap,
145 113 : Instance& server) {
146 113 : ENVOY_LOG(info, "loading stats configuration");
147 :
148 113 : for (const envoy::config::metrics::v3::StatsSink& sink_object : bootstrap.stats_sinks()) {
149 : // Generate factory and translate stats sink custom config.
150 2 : auto& factory = Config::Utility::getAndCheckFactory<StatsSinkFactory>(sink_object);
151 2 : ProtobufTypes::MessagePtr message = Config::Utility::translateToFactoryConfig(
152 2 : sink_object, server.messageValidationContext().staticValidationVisitor(), factory);
153 :
154 2 : stats_config_->addSink(factory.createStatsSink(*message, server.serverFactoryContext()));
155 2 : }
156 113 : }
157 :
158 : void MainImpl::initializeTracers(const envoy::config::trace::v3::Tracing& configuration,
159 131 : Instance& server) {
160 131 : ENVOY_LOG(info, "loading tracing configuration");
161 :
162 : // Default tracing configuration must be set prior to processing of static Listeners begins.
163 131 : server.setDefaultTracingConfig(configuration);
164 :
165 131 : if (!configuration.has_http()) {
166 131 : return;
167 131 : }
168 :
169 : // Validating tracing configuration (minimally).
170 0 : ENVOY_LOG(info, " validating default server-wide tracing driver: {}",
171 0 : configuration.http().name());
172 :
173 : // Now see if there is a factory that will accept the config.
174 0 : auto& factory = Config::Utility::getAndCheckFactory<TracerFactory>(configuration.http());
175 0 : ProtobufTypes::MessagePtr message = Config::Utility::translateToFactoryConfig(
176 0 : configuration.http(), server.messageValidationContext().staticValidationVisitor(), factory);
177 :
178 : // Notice that the actual Tracer instance will be created on demand
179 : // in the context of "envoy.filters.network.http_connection_manager" filter.
180 : // The side effect of this is that provider-specific configuration
181 : // is no longer validated in this step.
182 0 : }
183 :
184 : void MainImpl::initializeWatchdogs(const envoy::config::bootstrap::v3::Bootstrap& bootstrap,
185 115 : Instance& server) {
186 115 : if (bootstrap.has_watchdog() && bootstrap.has_watchdogs()) {
187 0 : throwEnvoyExceptionOrPanic("Only one of watchdog or watchdogs should be set!");
188 0 : }
189 :
190 115 : if (bootstrap.has_watchdog()) {
191 0 : main_thread_watchdog_ = std::make_unique<WatchdogImpl>(bootstrap.watchdog(), server);
192 0 : worker_watchdog_ = std::make_unique<WatchdogImpl>(bootstrap.watchdog(), server);
193 115 : } else {
194 115 : main_thread_watchdog_ =
195 115 : std::make_unique<WatchdogImpl>(bootstrap.watchdogs().main_thread_watchdog(), server);
196 115 : worker_watchdog_ =
197 115 : std::make_unique<WatchdogImpl>(bootstrap.watchdogs().worker_watchdog(), server);
198 115 : }
199 115 : }
200 :
201 : WatchdogImpl::WatchdogImpl(const envoy::config::bootstrap::v3::Watchdog& watchdog,
202 228 : Instance& server) {
203 228 : miss_timeout_ =
204 228 : std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, miss_timeout, 200));
205 228 : megamiss_timeout_ =
206 228 : std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, megamiss_timeout, 1000));
207 :
208 228 : uint64_t kill_timeout = PROTOBUF_GET_MS_OR_DEFAULT(watchdog, kill_timeout, 0);
209 228 : const uint64_t max_kill_timeout_jitter =
210 228 : PROTOBUF_GET_MS_OR_DEFAULT(watchdog, max_kill_timeout_jitter, 0);
211 :
212 : // Adjust kill timeout if we have skew enabled.
213 228 : if (kill_timeout > 0 && max_kill_timeout_jitter > 0) {
214 : // Increments the kill timeout with a random value in (0, max_skew].
215 : // We shouldn't have overflow issues due to the range of Duration.
216 : // This won't be entirely uniform, depending on how large max_skew
217 : // is relation to uint64.
218 0 : kill_timeout += (server.api().randomGenerator().random() % max_kill_timeout_jitter) + 1;
219 0 : }
220 :
221 228 : kill_timeout_ = std::chrono::milliseconds(kill_timeout);
222 228 : multikill_timeout_ =
223 228 : std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, multikill_timeout, 0));
224 228 : multikill_threshold_ = PROTOBUF_PERCENT_TO_DOUBLE_OR_DEFAULT(watchdog, multikill_threshold, 0.0);
225 228 : actions_ = watchdog.actions();
226 228 : }
227 :
228 244 : InitialImpl::InitialImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstrap) {
229 244 : const auto& admin = bootstrap.admin();
230 :
231 244 : admin_.profile_path_ =
232 244 : admin.profile_path().empty() ? "/var/log/envoy/envoy.prof" : admin.profile_path();
233 244 : if (admin.has_address()) {
234 139 : admin_.address_ = Network::Address::resolveProtoAddress(admin.address());
235 139 : }
236 244 : admin_.socket_options_ = std::make_shared<std::vector<Network::Socket::OptionConstSharedPtr>>();
237 244 : if (!admin.socket_options().empty()) {
238 0 : Network::Socket::appendOptions(
239 0 : admin_.socket_options_,
240 0 : Network::SocketOptionFactory::buildLiteralOptions(admin.socket_options()));
241 0 : }
242 244 : admin_.ignore_global_conn_limit_ = admin.ignore_global_conn_limit();
243 :
244 244 : if (!bootstrap.flags_path().empty()) {
245 14 : flags_path_ = bootstrap.flags_path();
246 14 : }
247 :
248 244 : if (bootstrap.has_layered_runtime()) {
249 103 : layered_runtime_.MergeFrom(bootstrap.layered_runtime());
250 103 : if (layered_runtime_.layers().empty()) {
251 1 : layered_runtime_.add_layers()->mutable_admin_layer();
252 1 : }
253 103 : }
254 244 : }
255 :
256 : void InitialImpl::initAdminAccessLog(const envoy::config::bootstrap::v3::Bootstrap& bootstrap,
257 208 : FactoryContext& factory_context) {
258 208 : const auto& admin = bootstrap.admin();
259 :
260 208 : for (const auto& access_log : admin.access_log()) {
261 98 : AccessLog::InstanceSharedPtr current_access_log =
262 98 : AccessLog::AccessLogFactory::fromProto(access_log, factory_context);
263 98 : admin_.access_logs_.emplace_back(current_access_log);
264 98 : }
265 :
266 208 : if (!admin.access_log_path().empty()) {
267 3 : Filesystem::FilePathAndType file_info{Filesystem::DestinationType::File,
268 3 : admin.access_log_path()};
269 3 : admin_.access_logs_.emplace_back(new Extensions::AccessLoggers::File::FileAccessLog(
270 3 : file_info, {}, Formatter::HttpSubstitutionFormatUtils::defaultSubstitutionFormatter(),
271 3 : factory_context.serverFactoryContext().accessLogManager()));
272 3 : }
273 208 : }
274 :
275 : } // namespace Configuration
276 : } // namespace Server
277 : } // namespace Envoy
|