options.nix (5755B)
1 # modules/features/pentest/options.nix — the toolkit's master switch and the 2 # options no single category owns. 3 # 4 # daemon.pentest.enable the whole toolkit (default false) 5 # daemon.pentest.<category>.enable declared by each category itself 6 # (_sets.nix), so adding a category 7 # touches one file, not two 8 # daemon.pentest.payloads.windowsArches which .exe variants to cross-build 9 # daemon.pentest.htb.vpnDir where .ovpn profiles are looked for 10 # daemon.pentest.htb.promptTarget show $TARGET in the prompt 11 # 12 # Scope: authorised lab use (HackTheBox CPTS prep). Nothing here points at any 13 # host; the operator supplies targets at runtime. 14 { inputs, lib, self, ... }: 15 { 16 # `daemon.pentest.enable = false` must be a usable state, not an eval error. 17 # The spec gives the master switch `default = false`, so "off" is the normal 18 # case for any other machine built from this flake. This check evaluates the 19 # whole toolkit with the master switch off and fails if any assertion fires. 20 # Under `config` because this module also declares `options`. 21 config.perSystem = 22 { pkgs, system, ... }: 23 let 24 probe = enable: 25 inputs.nixpkgs.lib.nixosSystem { 26 inherit system; 27 specialArgs = { 28 inherit inputs; 29 user = "probe"; 30 }; 31 modules = [ 32 self.nixosModules.pentest 33 { 34 daemon.pentest.enable = enable; 35 # Enough to make a nixosSystem evaluate. 36 boot.loader.grub.devices = [ "nodev" ]; 37 fileSystems."/" = { device = "/dev/null"; fsType = "ext4"; }; 38 system.stateVersion = "26.05"; 39 nixpkgs.config.allowUnfree = true; 40 users.users.probe.isNormalUser = true; 41 } 42 ]; 43 }; 44 failures = enable: 45 map (a: a.message) (builtins.filter (a: !a.assertion) (probe enable).config.assertions); 46 offFailures = failures false; 47 in 48 { 49 checks.pentest-options-off = 50 if offFailures != [ ] then 51 throw '' 52 daemon.pentest.enable = false must evaluate cleanly, but these 53 assertions fired: 54 ${lib.concatMapStringsSep "\n" (m: " - " + m) offFailures} 55 '' 56 else 57 pkgs.runCommand "pentest-options-off-check" { } '' 58 echo "daemon.pentest.enable = false evaluates with no failed assertions" > $out 59 ''; 60 }; 61 62 # Each category file registers its package list here (_sets.nix), and 63 # devshells.nix reads the merged result for the union shell and the 64 # all-category collision check. 65 # 66 # It lives under `flake.lib` rather than a top-level `flake.pentestPackages` 67 # for two reasons: the option has to be DECLARED as an attribute set, or 68 # flake-parts treats the whole thing as one freeform value and the second 69 # category to define it fails with "defined multiple times"; and `lib` is an 70 # output Nix recognises, so `nix flake check` does not warn about an unknown 71 # flake output. 72 options.flake = inputs.flake-parts.lib.mkSubmoduleOptions { 73 lib = lib.mkOption { 74 # A submodule, not a bare attrset: `pentestPackages` has to merge across 75 # the category files, so it needs its own attrsOf option. The freeform 76 # type keeps `flake.lib` open for anything else. 77 type = lib.types.submoduleWith { 78 modules = [ 79 { 80 freeformType = lib.types.lazyAttrsOf lib.types.raw; 81 options.pentestPackages = lib.mkOption { 82 type = lib.types.lazyAttrsOf lib.types.raw; 83 default = { }; 84 description = "Per-category `pkgs -> [package]` functions, by category name."; 85 }; 86 } 87 ]; 88 }; 89 default = { }; 90 description = "Flake-level helpers, including pentestPackages."; 91 }; 92 }; 93 94 # Under `config` because this module also declares `options` above. 95 config.flake.nixosModules.pentest-options = 96 { lib, config, user, ... }: 97 let 98 cfg = config.daemon.pentest; 99 # Every category option declared by _sets.nix: an attrset carrying a 100 # boolean `enable`. `htb` and `payloads.windowsArches` are not categories 101 # and drop out of this filter on their own. 102 categories = lib.filterAttrs (_: v: lib.isAttrs v && v ? enable && lib.isBool v.enable) cfg; 103 enabledWhileOff = lib.attrNames (lib.filterAttrs (_: v: v.enable) categories); 104 in 105 { 106 options.daemon.pentest = { 107 enable = lib.mkEnableOption "the offensive security toolkit"; 108 109 payloads.windowsArches = lib.mkOption { 110 type = lib.types.listOf (lib.types.enum [ "amd64" "x86" "arm64" ]); 111 default = [ "amd64" "x86" ]; 112 description = "Windows architectures to cross-build payload binaries for."; 113 }; 114 115 htb.vpnDir = lib.mkOption { 116 type = lib.types.str; 117 default = "/home/${user}/.config/htb/vpn"; 118 description = '' 119 Directory scanned for OpenVPN profiles by `htbvpn list`. Deliberately 120 not Nix-managed: HTB profiles are per-account and rotate. 121 ''; 122 }; 123 124 htb.promptTarget = lib.mkOption { 125 type = lib.types.bool; 126 default = true; 127 description = "Show the current $TARGET in the shell prompt."; 128 }; 129 }; 130 131 config.assertions = [ 132 { 133 assertion = cfg.enable || enabledWhileOff == [ ]; 134 message = 135 "daemon.pentest: ${lib.concatStringsSep ", " enabledWhileOff} " 136 + "enabled while daemon.pentest.enable is false. Set daemon.pentest.enable = true."; 137 } 138 ]; 139 }; 140 }