libexpr/flake: (opinionated) changes to interactive flake config

So I recently saw it the first time in the wild, I liked that you get
interactively asked about the nix.conf settings from the flake, but
there were a few minor things that I'd like to see changed:

* The `(y/N)` was somewhere in the middle of the line. Moved it to
  the end. At first I assumed it was a bug because another thread into
  my terminal while I was answering the question.

* I had to say no four times for a single flake with two options. So if
  you already know you don't want any of the config for _this_ flake, I
  found a `No to all` switch that ignores the rest of the nix.conf
  settings a little more ergonomic than having to stop the invocation,
  looking up the exact wording of `--no-accept-flake-config` and
  restarting it. Hence, I added it.

* Added a note where the choices which settings to trust are persisted.
  My initial assumption was that this went into `nix.conf` which is not
  writable on NixOS, so I said no there as well.

Change-Id: I0a0d9c403f0662df4707697a77f08e6cd003ec6f
This commit is contained in:
Maximilian Bosch 2024-10-13 14:18:22 +02:00
parent a322fcea4a
commit 86eddb9e27
Signed by: ma27
SSH key fingerprint: SHA256:d7dmwHmpai66L6KIXA+wxzVbkPq0nGLrcHK3ZNroqZY
2 changed files with 50 additions and 8 deletions

View file

@ -0,0 +1,13 @@
---
synopsis: "Improvements to interactive flake config"
cls: [2066]
category: Improvements
credits: ma27
---
If `accept-flake-config` is set to `ask` and a `flake.nix` defines `nixConfig`,
Lix will ask on the CLI which of these settings should be used for the command.
Now, it's possible to answer with `N` (as opposed to `n` to only reject the setting
that is asked for) to reject _all untrusted_ entries from the flake's `nixConf`
section.

View file

@ -30,10 +30,44 @@ static void writeTrustedList(const TrustedList & trustedList)
writeFile(path, nlohmann::json(trustedList).dump()); writeFile(path, nlohmann::json(trustedList).dump());
} }
static bool askForSetting(
bool & negativeTrustOverride,
TrustedList & trustedList,
const std::string & name,
const std::string & valueS)
{
bool trusted = false;
// FIXME: filter ANSI escapes, newlines, \r, etc.
auto reply = logger->ask(fmt("Do you want to allow configuration setting '%s' to be set to '" ANSI_RED "%s" ANSI_NORMAL "'?\nThis may allow the flake to gain root, see the nix.conf manual page (" ANSI_BOLD "y" ANSI_NORMAL "es/" ANSI_BOLD "n" ANSI_NORMAL "o/" ANSI_BOLD "N" ANSI_NORMAL "o to all) ", name, valueS)).value_or('n');
if (reply == 'N') {
warn("Rejecting all untrusted nix.conf entries");
warn("you can set '%s' to '%b' to automatically reject configuration options supplied by flakes", "accept-flake-config", false);
negativeTrustOverride = true;
} else {
if (std::tolower(reply) == 'y') {
trusted = true;
} else {
warn("you can set '%s' to '%b' to automatically reject configuration options supplied by flakes", "accept-flake-config", false);
}
if (std::tolower(logger->ask(fmt("do you want to permanently (in %s) mark this value as %s? (y/N) ", trustedListPath(), trusted ? "trusted": "untrusted" )).value_or('n')) == 'y') {
trustedList[name][valueS] = trusted;
writeTrustedList(trustedList);
}
}
return trusted;
}
void ConfigFile::apply() void ConfigFile::apply()
{ {
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lockfile-summary"}; std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lockfile-summary"};
// Allows to ignore all subsequent settings from this file.
bool negativeTrustOverride = false;
for (auto & [name, value] : settings) { for (auto & [name, value] : settings) {
auto baseName = name.starts_with("extra-") ? std::string(name, 6) : name; auto baseName = name.starts_with("extra-") ? std::string(name, 6) : name;
@ -65,15 +99,10 @@ void ConfigFile::apply()
trusted = *saved; trusted = *saved;
printInfo("Using saved setting for '%s = %s' from ~/.local/share/nix/trusted-settings.json.", name, valueS); printInfo("Using saved setting for '%s = %s' from ~/.local/share/nix/trusted-settings.json.", name, valueS);
} else { } else {
// FIXME: filter ANSI escapes, newlines, \r, etc. if (negativeTrustOverride) {
if (std::tolower(logger->ask(fmt("Do you want to allow configuration setting '%s' to be set to '" ANSI_RED "%s" ANSI_NORMAL "' (y/N)? This may allow the flake to gain root, see the nix.conf manual page.", name, valueS)).value_or('n')) == 'y') { trusted = false;
trusted = true;
} else { } else {
warn("you can set '%s' to '%b' to automatically reject configuration options supplied by flakes", "accept-flake-config", false); trusted = askForSetting(negativeTrustOverride, trustedList, name, valueS);
}
if (std::tolower(logger->ask(fmt("do you want to permanently mark this value as %s (y/N)?", trusted ? "trusted": "untrusted" )).value_or('n')) == 'y') {
trustedList[name][valueS] = trusted;
writeTrustedList(trustedList);
} }
} }
break; break;