Disable network proxies by default (#631)

* Disable network proxies by default

and allow the user to enable them with the new --enable-network-proxy
flag

* Update man with new --enable-network-proxy flag

* Increase help space for option names

to accommodate the new option --enable-network-proxy
This commit is contained in:
Jaime González
2025-05-10 04:02:31 +02:00
committed by GitHub
parent 14c2e0174a
commit 0a49313ac9
7 changed files with 81 additions and 31 deletions

View File

@@ -54,6 +54,12 @@ Force to use the dynamic linker method of \f[C]intercept\f[R] command.
.TP
--force-wrapper
Force to use the compiler wrapper method of \f[C]intercept\f[R] command.
.TP
--enable-network-proxy
Forward HTTP proxy environment variables (\f[C]http_proxy\f[R],
\f[C]https_proxy\f[R], \f[C]grpc_proxy\f[R] and their capitalized
versions) to \f[C]intercept\f[R] command.
They are unset by default.
.SH COMMANDS
.TP
\f[B]\f[CB]bear-intercept(1)\f[B]\f[R]

View File

@@ -55,6 +55,11 @@ compilation database.
\--force-wrapper
: Force to use the compiler wrapper method of `intercept` command.
\--enable-network-proxy
: Forward HTTP proxy environment variables (`http_proxy`, `https_proxy`,
`grpc_proxy` and their capitalized versions) to `intercept` command.
They are unset by default.
# COMMANDS
`bear-intercept(1)`

View File

@@ -36,10 +36,11 @@ namespace {
auto verbose = arguments.as_bool(flags::VERBOSE).unwrap_or(false);
auto force_wrapper = arguments.as_bool(cmd::intercept::FLAG_FORCE_WRAPPER).unwrap_or(false);
auto force_preload = arguments.as_bool(cmd::intercept::FLAG_FORCE_PRELOAD).unwrap_or(false);
auto enable_network_proxy = arguments.as_bool(cmd::intercept::FLAG_ENABLE_NETWORK_PROXY).unwrap_or(false);
return rust::merge(program, command, rust::merge(library, wrapper, wrapper_dir))
.map<sys::Process::Builder>(
[&environment, &output, &verbose, &force_wrapper, &force_preload](auto tuple) {
[&environment, &output, &verbose, &force_wrapper, &force_preload, &enable_network_proxy](auto tuple) {
const auto&[program, command, pack] = tuple;
const auto&[library, wrapper, wrapper_dir] = pack;
@@ -57,6 +58,9 @@ namespace {
if (force_preload) {
builder.add_argument(cmd::intercept::FLAG_FORCE_PRELOAD);
}
if (enable_network_proxy) {
builder.add_argument(cmd::intercept::FLAG_ENABLE_NETWORK_PROXY);
}
if (verbose) {
builder.add_argument(flags::VERBOSE);
}
@@ -146,13 +150,14 @@ namespace bear {
rust::Result<flags::Arguments> Application::parse(int argc, const char **argv) const
{
const flags::Parser intercept_parser("intercept", cmd::VERSION, {
{cmd::intercept::FLAG_OUTPUT, {1, false, "path of the result file", {cmd::intercept::DEFAULT_OUTPUT}, std::nullopt}},
{cmd::intercept::FLAG_FORCE_PRELOAD, {0, false, "force to use library preload", std::nullopt, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_FORCE_WRAPPER, {0, false, "force to use compiler wrappers", std::nullopt, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_LIBRARY, {1, false, "path to the preload library", {cmd::library::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_WRAPPER, {1, false, "path to the wrapper executable", {cmd::wrapper::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_WRAPPER_DIR, {1, false, "path to the wrapper directory", {cmd::wrapper::DEFAULT_DIR_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_COMMAND, {-1, true, "command to execute", std::nullopt, std::nullopt}}
{cmd::intercept::FLAG_OUTPUT, {1, false, "path of the result file", {cmd::intercept::DEFAULT_OUTPUT}, std::nullopt}},
{cmd::intercept::FLAG_FORCE_PRELOAD, {0, false, "force to use library preload", std::nullopt, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_FORCE_WRAPPER, {0, false, "force to use compiler wrappers", std::nullopt, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_ENABLE_NETWORK_PROXY, {0, false, "enable http and https proxy", std::nullopt, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_LIBRARY, {1, false, "path to the preload library", {cmd::library::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_WRAPPER, {1, false, "path to the wrapper executable", {cmd::wrapper::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_WRAPPER_DIR, {1, false, "path to the wrapper directory", {cmd::wrapper::DEFAULT_DIR_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_COMMAND, {-1, true, "command to execute", std::nullopt, std::nullopt}}
});
const flags::Parser citnames_parser("citnames", cmd::VERSION, {
@@ -164,16 +169,17 @@ namespace bear {
});
const flags::Parser parser("bear", cmd::VERSION, {intercept_parser, citnames_parser}, {
{cmd::citnames::FLAG_OUTPUT, {1, false, "path of the result file", {cmd::citnames::DEFAULT_OUTPUT}, std::nullopt}},
{cmd::citnames::FLAG_APPEND, {0, false, "append result to an existing output file", std::nullopt, ADVANCED_GROUP}},
{cmd::citnames::FLAG_CONFIG, {1, false, "path of the config file", std::nullopt, ADVANCED_GROUP}},
{cmd::intercept::FLAG_FORCE_PRELOAD, {0, false, "force to use library preload", std::nullopt, ADVANCED_GROUP}},
{cmd::intercept::FLAG_FORCE_WRAPPER, {0, false, "force to use compiler wrappers", std::nullopt, ADVANCED_GROUP}},
{cmd::bear::FLAG_BEAR, {1, false, "path to the bear executable", {cmd::bear::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_LIBRARY, {1, false, "path to the preload library", {cmd::library::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_WRAPPER, {1, false, "path to the wrapper executable", {cmd::wrapper::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_WRAPPER_DIR, {1, false, "path to the wrapper directory", {cmd::wrapper::DEFAULT_DIR_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_COMMAND, {-1, true, "command to execute", std::nullopt, std::nullopt}}
{cmd::citnames::FLAG_OUTPUT, {1, false, "path of the result file", {cmd::citnames::DEFAULT_OUTPUT}, std::nullopt}},
{cmd::citnames::FLAG_APPEND, {0, false, "append result to an existing output file", std::nullopt, ADVANCED_GROUP}},
{cmd::citnames::FLAG_CONFIG, {1, false, "path of the config file", std::nullopt, ADVANCED_GROUP}},
{cmd::intercept::FLAG_FORCE_PRELOAD, {0, false, "force to use library preload", std::nullopt, ADVANCED_GROUP}},
{cmd::intercept::FLAG_FORCE_WRAPPER, {0, false, "force to use compiler wrappers", std::nullopt, ADVANCED_GROUP}},
{cmd::intercept::FLAG_ENABLE_NETWORK_PROXY, {0, false, "enable http and https proxy", std::nullopt, ADVANCED_GROUP}},
{cmd::bear::FLAG_BEAR, {1, false, "path to the bear executable", {cmd::bear::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_LIBRARY, {1, false, "path to the preload library", {cmd::library::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_WRAPPER, {1, false, "path to the wrapper executable", {cmd::wrapper::DEFAULT_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_WRAPPER_DIR, {1, false, "path to the wrapper directory", {cmd::wrapper::DEFAULT_DIR_PATH}, DEVELOPER_GROUP}},
{cmd::intercept::FLAG_COMMAND, {-1, true, "command to execute", std::nullopt, std::nullopt}}
});
return parser.parse_or_exit(argc, const_cast<const char **>(argv));
}
@@ -186,6 +192,12 @@ namespace bear {
return citnames.subcommand(args, envp);
}
if (auto intercept = ic::Intercept(log_config_); intercept.matches(args)) {
// Network proxy is disabled by default unless user explicitly enables it
if (!args.as_bool(cmd::intercept::FLAG_ENABLE_NETWORK_PROXY).unwrap_or(false)) {
for (auto proxyEnv : cmd::intercept::PROXY_ENV_VARS) {
unsetenv(proxyEnv);
}
}
return intercept.subcommand(args, envp);
}
return rust::Err(std::runtime_error("Invalid subcommand"));

View File

@@ -102,6 +102,8 @@ namespace cmd {
constexpr char FLAG_COMMAND[] = "--";
constexpr char FLAG_FORCE_WRAPPER[] = "--force-wrapper";
constexpr char FLAG_FORCE_PRELOAD[] = "--force-preload";
constexpr char FLAG_ENABLE_NETWORK_PROXY[] = "--enable-network-proxy";
constexpr const char* PROXY_ENV_VARS[] = {"http_proxy", "https_proxy", "grpc_proxy","all_proxy", "HTTP_PROXY", "HTTPS_PROXY", "GRPC_PROXY", "ALL_PROXY"};
constexpr char DEFAULT_OUTPUT[] = "events.json";
}

View File

@@ -110,11 +110,11 @@ namespace {
// print flag name
os << flag_name;
// decide if the help text goes into the same line or not
if (flag_size > 22) {
if (flag_size > 25) {
os << std::endl
<< std::string(15, ' ');
} else {
os << std::string(23 - flag_size, ' ');
os << std::string(26 - flag_size, ' ');
}
os << option.help;
// print default value if exists

View File

@@ -177,16 +177,16 @@ namespace {
const char *expected =
"Usage: test [--flag] [--option <arg>] [--options <arg0> <arg1> <arg2>] [--verbose] [-- ...]\n"
"\n"
" --flag a single flag\n"
" --option <arg> a flag with a value\n"
" --flag a single flag\n"
" --option <arg> a flag with a value\n"
" --options <arg0> <arg1> <arg2>\n"
" a flag with 3 values\n"
" --verbose run in verbose mode\n"
" -- ... rest of the arguments\n"
" --verbose run in verbose mode\n"
" -- ... rest of the arguments\n"
"\n"
"query options\n"
" --help print help and exit\n"
" --version print version and exit\n";
" --help print help and exit\n"
" --version print version and exit\n";
std::ostringstream out;
sut.print_help(nullptr, out);
@@ -367,8 +367,8 @@ namespace {
" dump\n"
"\n"
"query options\n"
" --help print help and exit\n"
" --version print version and exit\n";
" --help print help and exit\n"
" --version print version and exit\n";
std::ostringstream out;
sut.print_help(nullptr, out);
@@ -378,11 +378,11 @@ namespace {
const char *expected =
"Usage: test append [--option <arg>] [--verbose]\n"
"\n"
" --option <arg> a flag with a value\n"
" --verbose run in verbose mode\n"
" --option <arg> a flag with a value\n"
" --verbose run in verbose mode\n"
"\n"
"query options\n"
" --help print help and exit\n";
" --help print help and exit\n";
std::ostringstream out;
sut.print_help(&append, out);

View File

@@ -0,0 +1,25 @@
#!/usr/bin/env sh
# REQUIRES: shell, cc
# If an unreachable or an invalid http proxy is set, an error is returned if '--enable-network-proxy' is set
#
# RUN: env http_proxy=http://localhost:9999 %{intercept} --enable-network-proxy --output %t.json -- %{shell} %s 2> %t.stderr
# RUN: grep "failed to connect to all addresses" %t.stderr
# RUN: assert_intercepted %t.json count -eq 0
# If no http proxy is set, it should run correctly even with '--enable-network-proxy'
#
# RUN: %{intercept} --enable-network-proxy --output %t.json -- %{shell} %s
# RUN: assert_intercepted %t.json count -eq 1
# RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_enable_network_proxy.c -o shell_enable_network_proxy.o
# By default, even with an invalid http proxy set, it should run correctly
#
# RUN: env http_proxy=http://localhost:9999 %{intercept} --output %t.json -- %{shell}
# RUN: assert_intercepted %t.json count -eq 1
touch shell_enable_network_proxy.c
$CC -c shell_enable_network_proxy.c -o shell_enable_network_proxy.o