diff --git a/README.md b/README.md index 307e647..75c088b 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,17 @@ If you haven't installed Homebrew before, use the following configuration: # # With mutableTaps disabled, taps can no longer be added imperatively with `brew tap`. mutableTaps = false; + + # Optional: Declarative Homebrew tap trust entries. + # + # Note: The trust entries are _not_ removed if you remove them from those lists! + # Use the `brew untrust` command to remove a trust entry. + trust = { + formulae = [ ]; + casks = [ ]; + commands = [ ]; + taps = [ ]; + }; }; } # Optional: Align homebrew taps config with nix-homebrew @@ -83,6 +94,25 @@ With `nix-homebrew.mutableTaps = false`, taps can be removed by deleting the cor Setting `homebrew.taps` to equal `nix-homebrew.taps` attribute names reduces configuration mismatches. +For non-official taps, Homebrew requires [explicit trust](https://docs.brew.sh/Tap-Trust). +You may use imperative `brew trust`/`brew untrust` commands, or configure `nix-homebrew` to add trust entries during activation: + +```nix +nix-homebrew.trust = { + formulae = [ "user/repo/formula" ]; + casks = [ "user/repo/cask" ]; + commands = [ "user/repo/command" ]; + + # To quote upstream documentation: + # > Trust a whole tap only when you are comfortable with all current and + # > future formulae, casks and external commands from that tap being loaded + # > by Homebrew. + taps = [ "user/repo" ]; +}; +``` +Note that when you remove items from those lists, the corresponding trust entries are _not_ removed automatically. +Use the `brew untrust` command to remove a trust entry. + ### B. Existing Homebrew Installation If you've already installed Homebrew with the official script, you can let `nix-homebrew` automatically migrate it: diff --git a/ci/tests.nix b/ci/tests.nix index 55a5ad5..7db127a 100644 --- a/ci/tests.nix +++ b/ci/tests.nix @@ -83,6 +83,12 @@ let mkdir -p "$out/Casks/u" touch "$out/Casks/u/ungoogled-chromium.rb" ''; + fakeThirdPartyTap = pkgs.runCommandLocal "thirdparty-test-tap" { } '' + mkdir -p "$out/Formula" "$out/Casks" "$out/cmd" + touch "$out/Formula/foo.rb" + touch "$out/Casks/test-cask.rb" + touch "$out/cmd/brew-test-command.rb" + ''; in { imports = [ @@ -96,6 +102,12 @@ let autoMigrate = true; taps = { "homebrew/homebrew-cask" = fakeCaskTap; + "thirdparty/homebrew-testtap" = fakeThirdPartyTap; + }; + trust = { + formulae = [ "thirdparty/testtap/foo" ]; + casks = [ "thirdparty/testtap/test-cask" ]; + commands = [ "thirdparty/testtap/test-command" ]; }; }; @@ -113,6 +125,15 @@ let test -f "$cask_path" + >&2 echo "Checking declarative Homebrew trust entries" + brew trust --json=v1 --formula | grep '"thirdparty/testtap/foo"' + brew trust --json=v1 --cask | grep '"thirdparty/testtap/test-cask"' + brew trust --json=v1 --command | grep '"thirdparty/testtap/test-command"' + if brew trust --json=v1 --tap | grep '"thirdparty/testtap"'; then + >&2 echo "Expected thirdparty/testtap not to be trusted as a whole tap" + exit 1 + fi + tap_root_real="$(${pkgs.coreutils}/bin/realpath "$tap_root")" cask_real="$(${pkgs.coreutils}/bin/realpath "$cask_path")" diff --git a/modules/default.nix b/modules/default.nix index 9158544..d09bfca 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -252,6 +252,19 @@ let exit 1 fi /bin/ln -shf "${makeBinBrew prefix}" "$BIN_BREW" + + ${setupTrust} + ''; + + setupTrust = let + trustEntries = flag: entries: lib.concatMapStrings (entry: '' + /usr/bin/sudo -n -u ${lib.escapeShellArg cfg.user} -H "$BIN_BREW" trust ${flag} ${lib.escapeShellArg entry} >/dev/null + '') entries; + in '' + ${trustEntries "--tap" cfg.trust.taps} + ${trustEntries "--formula" cfg.trust.formulae} + ${trustEntries "--cask" cfg.trust.casks} + ${trustEntries "--command" cfg.trust.commands} ''; setupTaps = taps: @@ -390,6 +403,68 @@ in { type = types.bool; default = true; }; + trust = lib.mkOption { + description = '' + Tap trust entries to be added during activation. + + Note: The trust entries are _not_ removed if you remove them from + those lists! Use the `brew untrust` command to remove a trust entry. + + Refer to upstream documentations for more information: + + ''; + type = types.submodule { + options = { + taps = lib.mkOption { + description = '' + Taps to trust in their entirety. + + This should be used with caution. To quote upstream documentation: + + > Trust a whole tap only when you are comfortable with all current and + > future formulae, casks and external commands from that tap being loaded + > by Homebrew. + ''; + type = types.listOf types.str; + default = []; + example = [ + "user/repo" + ]; + }; + formulae = lib.mkOption { + description = '' + Fully-qualified formulae to trust. + ''; + type = types.listOf types.str; + default = []; + example = [ + "user/repo/formula" + ]; + }; + casks = lib.mkOption { + description = '' + Fully-qualified casks to trust. + ''; + type = types.listOf types.str; + default = []; + example = [ + "user/repo/cask" + ]; + }; + commands = lib.mkOption { + description = '' + Fully-qualified external commands to trust. + ''; + type = types.listOf types.str; + default = []; + example = [ + "user/repo/command" + ]; + }; + }; + }; + default = {}; + }; autoMigrate = lib.mkOption { description = '' Whether to allow nix-homebrew to automatically migrate existing Homebrew installations.