Ask for confirmation before allowing flake Nix configuration settings
This commit is contained in:
parent
605bacdc92
commit
0287f83057
|
@ -233,28 +233,28 @@ static Flake getFlake(
|
||||||
if (auto nixConfig = vInfo.attrs->get(sNixConfig)) {
|
if (auto nixConfig = vInfo.attrs->get(sNixConfig)) {
|
||||||
expectType(state, tAttrs, *nixConfig->value, *nixConfig->pos);
|
expectType(state, tAttrs, *nixConfig->value, *nixConfig->pos);
|
||||||
|
|
||||||
for (auto & option : *nixConfig->value->attrs) {
|
for (auto & setting : *nixConfig->value->attrs) {
|
||||||
forceTrivialValue(state, *option.value, *option.pos);
|
forceTrivialValue(state, *setting.value, *setting.pos);
|
||||||
if (option.value->type == tString)
|
if (setting.value->type == tString)
|
||||||
flake.config.options.insert({option.name, state.forceStringNoCtx(*option.value, *option.pos)});
|
flake.config.settings.insert({setting.name, state.forceStringNoCtx(*setting.value, *setting.pos)});
|
||||||
else if (option.value->type == tInt)
|
else if (setting.value->type == tInt)
|
||||||
flake.config.options.insert({option.name, state.forceInt(*option.value, *option.pos)});
|
flake.config.settings.insert({setting.name, state.forceInt(*setting.value, *setting.pos)});
|
||||||
else if (option.value->type == tBool)
|
else if (setting.value->type == tBool)
|
||||||
flake.config.options.insert({option.name, state.forceBool(*option.value, *option.pos)});
|
flake.config.settings.insert({setting.name, state.forceBool(*setting.value, *setting.pos)});
|
||||||
else if (option.value->isList()) {
|
else if (setting.value->isList()) {
|
||||||
std::vector<std::string> ss;
|
std::vector<std::string> ss;
|
||||||
for (unsigned int n = 0; n < option.value->listSize(); ++n) {
|
for (unsigned int n = 0; n < setting.value->listSize(); ++n) {
|
||||||
auto elem = option.value->listElems()[n];
|
auto elem = setting.value->listElems()[n];
|
||||||
if (elem->type != tString)
|
if (elem->type != tString)
|
||||||
throw TypeError("list element in flake configuration option '%s' is %s while a string is expected",
|
throw TypeError("list element in flake configuration setting '%s' is %s while a string is expected",
|
||||||
option.name, showType(*option.value));
|
setting.name, showType(*setting.value));
|
||||||
ss.push_back(state.forceStringNoCtx(*elem, *option.pos));
|
ss.push_back(state.forceStringNoCtx(*elem, *setting.pos));
|
||||||
}
|
}
|
||||||
flake.config.options.insert({option.name, ss});
|
flake.config.settings.insert({setting.name, ss});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw TypeError("flake configuration option '%s' is %s",
|
throw TypeError("flake configuration setting '%s' is %s",
|
||||||
option.name, showType(*option.value));
|
setting.name, showType(*setting.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,27 +637,34 @@ Flake::~Flake() { }
|
||||||
|
|
||||||
void ConfigFile::apply()
|
void ConfigFile::apply()
|
||||||
{
|
{
|
||||||
for (auto & [name, value] : options) {
|
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-suffix"};
|
||||||
// FIXME: support 'trusted-public-keys' (and other options), but make it TOFU.
|
|
||||||
if (name != "bash-prompt-suffix" &&
|
for (auto & [name, value] : settings) {
|
||||||
name != "bash-prompt" &&
|
|
||||||
name != "substituters" &&
|
auto baseName = hasPrefix(name, "extra-") ? std::string(name, 6) : name;
|
||||||
name != "extra-substituters")
|
|
||||||
{
|
|
||||||
warn("ignoring untrusted flake configuration option '%s'", name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// FIXME: Move into libutil/config.cc.
|
// FIXME: Move into libutil/config.cc.
|
||||||
|
std::string valueS;
|
||||||
if (auto s = std::get_if<std::string>(&value))
|
if (auto s = std::get_if<std::string>(&value))
|
||||||
globalConfig.set(name, *s);
|
valueS = *s;
|
||||||
else if (auto n = std::get_if<int64_t>(&value))
|
else if (auto n = std::get_if<int64_t>(&value))
|
||||||
globalConfig.set(name, fmt("%d", n));
|
valueS = fmt("%d", n);
|
||||||
else if (auto b = std::get_if<Explicit<bool>>(&value))
|
else if (auto b = std::get_if<Explicit<bool>>(&value))
|
||||||
globalConfig.set(name, b->t ? "true" : "false");
|
valueS = b->t ? "true" : "false";
|
||||||
else if (auto ss = std::get_if<std::vector<std::string>>(&value))
|
else if (auto ss = std::get_if<std::vector<std::string>>(&value))
|
||||||
globalConfig.set(name, concatStringsSep(" ", *ss)); // FIXME: evil
|
valueS = concatStringsSep(" ", *ss); // FIXME: evil
|
||||||
else
|
else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
||||||
|
if (!whitelist.count(baseName)) {
|
||||||
|
// FIXME: filter ANSI escapes, newlines, \r, etc.
|
||||||
|
if (std::tolower(logger->ask(fmt("do you want to allow configuration setting '%s' to be set to '%s' (y/N)?", name, valueS)).value_or('n')) != 'y') {
|
||||||
|
warn("ignoring untrusted flake configuration setting '%s'", name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalConfig.set(name, valueS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct ConfigFile
|
||||||
{
|
{
|
||||||
using ConfigValue = std::variant<std::string, int64_t, Explicit<bool>, std::vector<std::string>>;
|
using ConfigValue = std::variant<std::string, int64_t, Explicit<bool>, std::vector<std::string>>;
|
||||||
|
|
||||||
std::map<std::string, ConfigValue> options;
|
std::map<std::string, ConfigValue> settings;
|
||||||
|
|
||||||
void apply();
|
void apply();
|
||||||
};
|
};
|
||||||
|
|
|
@ -466,6 +466,17 @@ public:
|
||||||
Logger::writeToStdout(s);
|
Logger::writeToStdout(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<char> ask(std::string_view msg) override
|
||||||
|
{
|
||||||
|
auto state(state_.lock());
|
||||||
|
if (!state->active || !isatty(STDIN_FILENO)) return {};
|
||||||
|
std::cerr << fmt("\r\e[K%s ", msg);
|
||||||
|
auto s = trim(readLine(STDIN_FILENO));
|
||||||
|
if (s.size() != 1) return {};
|
||||||
|
draw(*state);
|
||||||
|
return s[0];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Logger * makeProgressBar(bool printBuildLogs)
|
Logger * makeProgressBar(bool printBuildLogs)
|
||||||
|
|
|
@ -106,6 +106,9 @@ public:
|
||||||
formatHelper(f, args...);
|
formatHelper(f, args...);
|
||||||
writeToStdout(f.str());
|
writeToStdout(f.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::optional<char> ask(std::string_view s)
|
||||||
|
{ return {}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
ActivityId getCurActivity();
|
ActivityId getCurActivity();
|
||||||
|
|
Loading…
Reference in a new issue