Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bazel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,11 @@ selects.config_setting_group(
],
)

config_setting(
name = "disable_admin_html",
values = {"define": "admin_html=disabled"},
)

Comment on lines +321 to +325

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config_setting(
name = "disable_hot_restart_setting",
values = {"define": "hot_restart=disabled"},
Expand Down
1 change: 1 addition & 0 deletions bazel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ The following optional features can be disabled on the Bazel build command-line:
tcmalloc with `--define tcmalloc=gperftools` which is the default for builds other than x86_64 and aarch64.
* deprecated features with `--define deprecated_features=disabled`
* http3/quic with --//bazel:http3=False
* admin HTML home page with `--define=admin_html=disabled`

## Enabling optional features

Expand Down
4 changes: 4 additions & 0 deletions bazel/envoy_build_system.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ load(
load(":envoy_pch.bzl", _envoy_pch_library = "envoy_pch_library")
load(
":envoy_select.bzl",
_envoy_select_admin_html = "envoy_select_admin_html",
_envoy_select_admin_no_html = "envoy_select_admin_no_html",
_envoy_select_boringssl = "envoy_select_boringssl",
_envoy_select_enable_http3 = "envoy_select_enable_http3",
_envoy_select_google_grpc = "envoy_select_google_grpc",
Expand Down Expand Up @@ -206,6 +208,8 @@ def envoy_google_grpc_external_deps():
# from the other bzl files (e.g. envoy_select.bzl, envoy_binary.bzl, etc.)

# Select wrappers (from envoy_select.bzl)
envoy_select_admin_html = _envoy_select_admin_html
envoy_select_admin_no_html = _envoy_select_admin_no_html
envoy_select_boringssl = _envoy_select_boringssl
envoy_select_google_grpc = _envoy_select_google_grpc
envoy_select_enable_http3 = _envoy_select_enable_http3
Expand Down
3 changes: 2 additions & 1 deletion bazel/envoy_internal.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DO NOT LOAD THIS FILE. Targets from this file should be considered private
# and not used outside of the @envoy//bazel package.
load(":envoy_select.bzl", "envoy_select_enable_http3", "envoy_select_google_grpc", "envoy_select_hot_restart")
load(":envoy_select.bzl", "envoy_select_admin_html", "envoy_select_enable_http3", "envoy_select_google_grpc", "envoy_select_hot_restart")

# Compute the final copts based on various options.
def envoy_copts(repository, test = False):
Expand Down Expand Up @@ -122,6 +122,7 @@ def envoy_copts(repository, test = False):
repository + "//bazel:uhv_enabled": ["-DENVOY_ENABLE_UHV"],
"//conditions:default": [],
}) + envoy_select_hot_restart(["-DENVOY_HOT_RESTART"], repository) + \
envoy_select_admin_html(["-DENVOY_ADMIN_HTML"], repository) + \
envoy_select_enable_http3(["-DENVOY_ENABLE_QUIC"], repository) + \
_envoy_select_perf_annotation(["-DENVOY_PERF_ANNOTATION"]) + \
_envoy_select_perfetto(["-DENVOY_PERFETTO"]) + \
Expand Down
13 changes: 13 additions & 0 deletions bazel/envoy_select.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ def envoy_select_google_grpc(xs, repository = ""):
"//conditions:default": xs,
})

# Selects the given values if admin HTML is enabled in the current build.
def envoy_select_admin_html(xs, repository = ""):
return select({
repository + "//bazel:disable_admin_html": [],
"//conditions:default": xs,
})

def envoy_select_admin_no_html(xs, repository = ""):
return select({
repository + "//bazel:disable_admin_html": xs,
"//conditions:default": [],
})

# Selects the given values if http3 is enabled in the current build.
def envoy_select_enable_http3(xs, repository = ""):
return select({
Expand Down
7 changes: 5 additions & 2 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ minor_behavior_changes:
that loads shared object libraries, such as those installed via luarocks.
- area: admin
change: |
changed default regex engine for /stats?filter= from std::regex to RE2, improving filtering speed
20x.
changed default regex engine for ``/stats?filter=`` from std::regex to RE2, improving
filtering speed 20x.
- area: admin
change: |
added compile-time option ``--define=admin_html=disabled`` to disable HTML home page.
- area: skywalking
change: |
use request path as operation name of ENTRY/EXIT spans.
Expand Down
1 change: 1 addition & 0 deletions ci/do_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ elif [[ "$CI_TARGET" == "bazel.compile_time_options" ]]; then
# Right now, none of the available compile-time options conflict with each other. If this
# changes, this build type may need to be broken up.
COMPILE_TIME_OPTIONS=(
"--define" "admin_html=disabled"
"--define" "signal_trace=disabled"
"--define" "hot_restart=disabled"
"--define" "google_grpc=disabled"
Expand Down
9 changes: 7 additions & 2 deletions source/server/admin/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
"envoy_select_admin_html",
"envoy_select_admin_no_html",
)

licenses(["notice"]) # Apache 2
Expand All @@ -10,7 +12,11 @@ envoy_package()

envoy_cc_library(
name = "admin_lib",
srcs = ["admin.cc"],
srcs = ["admin.cc"] + envoy_select_admin_html([
"admin_html.cc",
]) + envoy_select_admin_no_html([
"admin_no_html.cc",
]),
hdrs = ["admin.h"],
deps = [
":admin_filter_lib",
Expand Down Expand Up @@ -45,7 +51,6 @@ envoy_cc_library(
"//source/common/common:mutex_tracer_lib",
"//source/common/common:utility_lib",
"//source/common/formatter:substitution_formatter_lib",
"//source/common/html:utility_lib",
"//source/common/http:codes_lib",
"//source/common/http:conn_manager_lib",
"//source/common/http:date_provider_lib",
Expand Down
114 changes: 0 additions & 114 deletions source/server/admin/admin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include "source/common/common/mutex_tracer_impl.h"
#include "source/common/common/utility.h"
#include "source/common/formatter/substitution_formatter.h"
#include "source/common/html/utility.h"
#include "source/common/http/codes.h"
#include "source/common/http/conn_manager_utility.h"
#include "source/common/http/header_map_impl.h"
Expand All @@ -45,72 +44,6 @@
namespace Envoy {
namespace Server {

namespace {

/**
* Favicon base64 image was harvested by screen-capturing the favicon from a Chrome tab
* while visiting https://www.envoyproxy.io/. The resulting PNG was translated to base64
* by dropping it into https://www.base64-image.de/ and then pasting the resulting string
* below.
*
* The actual favicon source for that, https://www.envoyproxy.io/img/favicon.ico is nicer
* because it's transparent, but is also 67646 bytes, which is annoying to inline. We could
* just reference that rather than inlining it, but then the favicon won't work when visiting
* the admin page from a network that can't see the internet.
*/
const char EnvoyFavicon[] =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1"
"BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAH9SURBVEhL7ZRdTttAFIUrUFaAX5w9gIhgUfzshFRK+gIbaVbA"
"zwaqCly1dSpKk5A485/YCdXpHTB4BsdgVe0bD0cZ3Xsm38yZ8byTUuJ/6g3wqqoBrBhPTzmmLfptMbAzttJTpTKAF2MWC"
"7ADCdNIwXZpvMMwayiIwwS874CcOc9VuQPR1dBBChPMITpFXXU45hukIIH6kHhzVqkEYB8F5HYGvZ5B7EvwmHt9K/59Cr"
"U3QbY2RNYaQPYmJc+jPIBICNCcg20ZsAsCPfbcrFlRF+cJZpvXSJt9yMTxO/IAzJrCOfhJXiOgFEX/SbZmezTWxyNk4Q9"
"anHMmjnzAhEyhAW8LCE6wl26J7ZFHH1FMYQxh567weQBOO1AW8D7P/UXAQySq/QvL8Fu9HfCEw4SKALm5BkC3bwjwhSKr"
"A5hYAMXTJnPNiMyRBVzVjcgCyHiSm+8P+WGlnmwtP2RzbCMiQJ0d2KtmmmPorRHEhfMROVfTG5/fYrF5iWXzE80tfy9WP"
"sCqx5Buj7FYH0LvDyHiqd+3otpsr4/fa5+xbEVQPfrYnntylQG5VGeMLBhgEfyE7o6e6qYzwHIjwl0QwXSvvTmrVAY4D5"
"ddvT64wV0jRrr7FekO/XEjwuwwhuw7Ef7NY+dlfXpLb06EtHUJdVbsxvNUqBrwj/QGeEUSfwBAkmWHn5Bb/gAAAABJRU5";

const char AdminHtmlStart[] = R"(
<head>
<title>Envoy Admin</title>
<link rel='shortcut icon' type='image/png' href='@FAVICON@'/>
<style>
.home-table {
font-family: sans-serif;
font-size: medium;
border-collapse: collapse;
}

.home-row:nth-child(even) {
background-color: #dddddd;
}

.home-data {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}

.home-form {
margin-bottom: 0;
}
</style>
</head>
<body>
<table class='home-table'>
<thead>
<th class='home-data'>Command</th>
<th class='home-data'>Description</th>
</thead>
<tbody>
)";

const char AdminHtmlEnd[] = R"(
</tbody>
</table>
</body>
)";
} // namespace

ConfigTracker& AdminImpl::getConfigTracker() { return config_tracker_; }

AdminImpl::NullRouteConfigProvider::NullRouteConfigProvider(TimeSource& time_source)
Expand Down Expand Up @@ -389,53 +322,6 @@ void AdminImpl::getHelp(Buffer::Instance& response) {
}
}

Http::Code AdminImpl::handlerAdminHome(absl::string_view, Http::ResponseHeaderMap& response_headers,
Buffer::Instance& response, AdminStream&) {
response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Html);

response.add(absl::StrReplaceAll(AdminHtmlStart, {{"@FAVICON@", EnvoyFavicon}}));

// Prefix order is used during searching, but for printing do them in alpha order.
for (const UrlHandler* handler : sortedHandlers()) {
absl::string_view path = handler->prefix_;

if (path == "/") {
continue; // No need to print self-link to index page.
}

// Remove the leading slash from the link, so that the admin page can be
// rendered as part of another console, on a sub-path.
//
// E.g. consider a downstream dashboard that embeds the Envoy admin console.
// In that case, the "/stats" endpoint would be at
// https://DASHBOARD/envoy_admin/stats. If the links we present on the home
// page are absolute (e.g. "/stats") they won't work in the context of the
// dashboard. Removing the leading slash, they will work properly in both
// the raw admin console and when embedded in another page and URL
// hierarchy.
ASSERT(!path.empty());
ASSERT(path[0] == '/');
path = path.substr(1);

// For handlers that mutate state, render the link as a button in a POST form,
// rather than an anchor tag. This should discourage crawlers that find the /
// page from accidentally mutating all the server state by GETting all the hrefs.
const char* link_format =
handler->mutates_server_state_
? "<form action='{}' method='post' class='home-form'><button>{}</button></form>"
: "<a href='{}'>{}</a>";
const std::string link = fmt::format(link_format, path, path);

// Handlers are all specified by statically above, and are thus trusted and do
// not require escaping.
response.add(fmt::format("<tr class='home-row'><td class='home-data'>{}</td>"
"<td class='home-data'>{}</td></tr>\n",
link, Html::Utility::sanitize(handler->help_text_)));
}
response.add(AdminHtmlEnd);
return Http::Code::OK;
}

const Network::Address::Instance& AdminImpl::localAddress() {
return *server_.localInfo().address();
}
Expand Down
122 changes: 122 additions & 0 deletions source/server/admin/admin_html.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "source/common/html/utility.h"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to reviewers: this code is unchanged; just moved.

#include "source/server/admin/admin.h"

namespace Envoy {
namespace Server {

namespace {

/**
* Favicon base64 image was harvested by screen-capturing the favicon from a Chrome tab
* while visiting https://www.envoyproxy.io/. The resulting PNG was translated to base64
* by dropping it into https://www.base64-image.de/ and then pasting the resulting string
* below.
*
* The actual favicon source for that, https://www.envoyproxy.io/img/favicon.ico is nicer
* because it's transparent, but is also 67646 bytes, which is annoying to inline. We could
* just reference that rather than inlining it, but then the favicon won't work when visiting
* the admin page from a network that can't see the internet.
*/
const char EnvoyFavicon[] =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1"
"BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAH9SURBVEhL7ZRdTttAFIUrUFaAX5w9gIhgUfzshFRK+gIbaVbA"
"zwaqCly1dSpKk5A485/YCdXpHTB4BsdgVe0bD0cZ3Xsm38yZ8byTUuJ/6g3wqqoBrBhPTzmmLfptMbAzttJTpTKAF2MWC"
"7ADCdNIwXZpvMMwayiIwwS874CcOc9VuQPR1dBBChPMITpFXXU45hukIIH6kHhzVqkEYB8F5HYGvZ5B7EvwmHt9K/59Cr"
"U3QbY2RNYaQPYmJc+jPIBICNCcg20ZsAsCPfbcrFlRF+cJZpvXSJt9yMTxO/IAzJrCOfhJXiOgFEX/SbZmezTWxyNk4Q9"
"anHMmjnzAhEyhAW8LCE6wl26J7ZFHH1FMYQxh567weQBOO1AW8D7P/UXAQySq/QvL8Fu9HfCEw4SKALm5BkC3bwjwhSKr"
"A5hYAMXTJnPNiMyRBVzVjcgCyHiSm+8P+WGlnmwtP2RzbCMiQJ0d2KtmmmPorRHEhfMROVfTG5/fYrF5iWXzE80tfy9WP"
"sCqx5Buj7FYH0LvDyHiqd+3otpsr4/fa5+xbEVQPfrYnntylQG5VGeMLBhgEfyE7o6e6qYzwHIjwl0QwXSvvTmrVAY4D5"
"ddvT64wV0jRrr7FekO/XEjwuwwhuw7Ef7NY+dlfXpLb06EtHUJdVbsxvNUqBrwj/QGeEUSfwBAkmWHn5Bb/gAAAABJRU5";

const char AdminHtmlStart[] = R"(
<head>
<title>Envoy Admin</title>
<link rel='shortcut icon' type='image/png' href='@FAVICON@'/>
<style>
.home-table {
font-family: sans-serif;
font-size: medium;
border-collapse: collapse;
}

.home-row:nth-child(even) {
background-color: #dddddd;
}

.home-data {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}

.home-form {
margin-bottom: 0;
}
</style>
</head>
<body>
<table class='home-table'>
<thead>
<th class='home-data'>Command</th>
<th class='home-data'>Description</th>
</thead>
<tbody>
)";

const char AdminHtmlEnd[] = R"(
</tbody>
</table>
</body>
)";

} // namespace

Http::Code AdminImpl::handlerAdminHome(absl::string_view, Http::ResponseHeaderMap& response_headers,
Buffer::Instance& response, AdminStream&) {
response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Html);

response.add(absl::StrReplaceAll(AdminHtmlStart, {{"@FAVICON@", EnvoyFavicon}}));

// Prefix order is used during searching, but for printing do them in alpha order.
for (const UrlHandler* handler : sortedHandlers()) {
absl::string_view path = handler->prefix_;

if (path == "/") {
continue; // No need to print self-link to index page.
}

// Remove the leading slash from the link, so that the admin page can be
// rendered as part of another console, on a sub-path.
//
// E.g. consider a downstream dashboard that embeds the Envoy admin console.
// In that case, the "/stats" endpoint would be at
// https://DASHBOARD/envoy_admin/stats. If the links we present on the home
// page are absolute (e.g. "/stats") they won't work in the context of the
// dashboard. Removing the leading slash, they will work properly in both
// the raw admin console and when embedded in another page and URL
// hierarchy.
ASSERT(!path.empty());
ASSERT(path[0] == '/');
path = path.substr(1);

// For handlers that mutate state, render the link as a button in a POST form,
// rather than an anchor tag. This should discourage crawlers that find the /
// page from accidentally mutating all the server state by GETting all the hrefs.
const char* link_format =
handler->mutates_server_state_
? "<form action='{}' method='post' class='home-form'><button>{}</button></form>"
: "<a href='{}'>{}</a>";
const std::string link = fmt::format(link_format, path, path);

// Handlers are all specified by statically above, and are thus trusted and do
// not require escaping.
response.add(fmt::format("<tr class='home-row'><td class='home-data'>{}</td>"
"<td class='home-data'>{}</td></tr>\n",
link, Html::Utility::sanitize(handler->help_text_)));
}
response.add(AdminHtmlEnd);
return Http::Code::OK;
}

} // namespace Server
} // namespace Envoy
15 changes: 15 additions & 0 deletions source/server/admin/admin_no_html.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "source/common/html/utility.h"
#include "source/server/admin/admin.h"

namespace Envoy {
namespace Server {

Http::Code AdminImpl::handlerAdminHome(absl::string_view, Http::ResponseHeaderMap& response_headers,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this block here is the only new code in the PR.

Buffer::Instance& response, AdminStream&) {
response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Text);
response.add("HTML output was disabled by building with --define=admin_html=disabled");
return Http::Code::OK;
}

} // namespace Server
} // namespace Envoy
Loading