NixDaemon

NixOS pentest workstation as one flake — IceBreaker's successor
git clone https://git.daemon-sec.xyz/NixDaemon.git
Log | Files | Refs | README

_aliases.nix (2911B)


      1 # modules/features/pentest/_aliases.nix — reach a toolkit's `.py` scripts by
      2 # bare name, without taking a name a real tool already owns.
      3 #
      4 # impacket installs 70 example scripts as `secretsdump.py`, `psexec.py`,
      5 # `GetUserSPNs.py`. Muscle memory from Kali wants both `secretsdump.py` and
      6 # `secretsdump`, so this symlinks the suffix away — except that impacket also
      7 # ships `split.py`, `ping.py`, `net.py`, `reg.py`, `services.py`, `attrib.py`
      8 # and `smbclient.py`. Stripping those blindly is not a style question:
      9 # environment.systemPackages merges every package into one profile with
     10 # buildEnv, so `impacket-aliases/bin/net` and `samba/bin/net` is a hard
     11 # collision and the whole system stops building. Before this guard existed the
     12 # probe in python.nix failed exactly there.
     13 #
     14 # So: the `<prefix>-<name>` alias is always made, and the bare one only when no
     15 # package in `reservedFrom` (plus `extraReserved`) already owns that name. The
     16 # reserved set is read from those packages' bin/ at build time, so it tracks
     17 # what is really installed instead of a list that rots.
     18 #
     19 #   secretsdump.py -> secretsdump, impacket-secretsdump   (free)
     20 #   net.py         -> impacket-net                        (samba owns `net`)
     21 #
     22 # $out/collisions records every name that was held back, so `pentest-cheat` and
     23 # a future reviewer can see what moved and why.
     24 { lib, pkgs }:
     25 {
     26   package,
     27   prefix,
     28   reservedFrom ? [ ],
     29   extraReserved ? [ ],
     30 }:
     31 pkgs.runCommand "${prefix}-aliases"
     32   {
     33     meta.description = "suffix-free aliases for ${package.pname or prefix}, collision-guarded";
     34   }
     35   ''
     36     mkdir -p $out/bin
     37     : > $out/collisions
     38 
     39     reserved=$(
     40       {
     41         for d in ${lib.escapeShellArgs (map (p: "${p}/bin") reservedFrom)}; do
     42           [ -d "$d" ] && ls -1 "$d"
     43         done
     44         ${lib.optionalString (extraReserved != [ ]) ''printf '%s\n' ${lib.escapeShellArgs extraReserved}''}
     45       } | sort -u
     46     )
     47     is_reserved() { printf '%s\n' "$reserved" | grep -qxF "$1"; }
     48 
     49     for f in ${package}/bin/*.py; do
     50       [ -e "$f" ] || continue
     51       base=$(basename "$f" .py)
     52 
     53       # Always reachable under the prefix, whatever happens to the bare name.
     54       ln -s "$f" "$out/bin/${prefix}-$base"
     55 
     56       if is_reserved "$base"; then
     57         echo "$base (held back: a real tool owns this name) -> ${prefix}-$base" >> $out/collisions
     58       else
     59         ln -s "$f" "$out/bin/$base"
     60       fi
     61     done
     62 
     63     # Belt and braces: assert no bare alias is a reserved name, so a future
     64     # change to the logic above fails here rather than at system-rebuild time.
     65     for b in $out/bin/*; do
     66       n=$(basename "$b")
     67       case "$n" in ${prefix}-*) continue ;; esac
     68       if is_reserved "$n"; then
     69         echo "${prefix}-aliases: bare alias '$n' shadows a real tool" >&2
     70         exit 1
     71       fi
     72     done
     73 
     74     echo "${prefix}-aliases: $(ls -1 $out/bin | wc -l) aliases, $(wc -l < $out/collisions) held back"
     75   ''