1{ lib
2, fetchFromGitHub
3, runCommand
4, yallback
5, yara
6}:
7
8/* TODO/CAUTION:
9
10I don't want to discourage use, but I'm not sure how stable
11the API is. Have fun, but be prepared to track changes! :)
12
13For _now_, binlore is basically a thin wrapper around
14`<invoke yara> | <postprocess with yallback>` with support
15for running it on a derivation, saving the result in the
16store, and aggregating results from a set of packages.
17
18In the longer term, I suspect there are more uses for this
19general pattern (i.e., run some analysis tool that produces
20a deterministic output and cache the result per package...).
21
22I'm not sure how that'll look and if it'll be the case that
23binlore automatically collects all of them, or if you'll be
24configuring which "kind(s)" of lore it generates. Nailing
25that down will almost certainly mean reworking the API.
26
27*/
28
29let
30 src = fetchFromGitHub {
31 owner = "abathur";
32 repo = "binlore";
33 rev = "v0.2.0";
34 hash = "sha256-bBJky7Km+mieHTqoMz3mda3KaKxr9ipYpfQqn/4w8J0=";
35 };
36 /*
37 binlore has one one more yallbacks responsible for
38 routing the appropriate lore to a named file in the
39 appropriate format. At some point I might try to do
40 something fancy with this, but for now the answer to
41 *all* questions about the lore are: the bare minimum
42 to get resholve over the next feature hump in time to
43 hopefully slip this feature in before the branch-off.
44 */
45 # TODO: feeling really uninspired on the API
46 loreDef = {
47 # YARA rule file
48 rules = (src + "/execers.yar");
49 # output filenames; "types" of lore
50 types = [ "execers" "wrappers" ];
51 # shell rule callbacks; see github.com/abathur/yallback
52 yallback = (src + "/execers.yall");
53 # TODO:
54 # - echo for debug, can be removed at some point
55 # - I really just wanted to put the bit after the pipe
56 # in here, but I'm erring on the side of flexibility
57 # since this form will make it easier to pilot other
58 # uses of binlore.
59 callback = lore: drv: overrides: ''
60 if [[ -d "${drv}/bin" ]] || [[ -d "${drv}/lib" ]] || [[ -d "${drv}/libexec" ]]; then
61 echo generating binlore for $drv by running:
62 echo "${yara}/bin/yara --scan-list --recursive ${lore.rules} <(printf '%s\n' ${drv}/{bin,lib,libexec}) | ${yallback}/bin/yallback ${lore.yallback}"
63 else
64 echo "failed to generate binlore for $drv (none of ${drv}/{bin,lib,libexec} exist)"
65 fi
66 '' +
67 /*
68 Override lore for some packages. Unsure, but for now:
69 1. start with the ~name (pname-version)
70 2. remove characters from the end until we find a match
71 in overrides/
72 3. execute the override script with the list of expected
73 lore types
74 */
75 ''
76 i=''${#identifier}
77 filter=
78 while [[ $i > 0 ]] && [[ -z "$filter" ]]; do
79 if [[ -f "${overrides}/''${identifier:0:$i}" ]]; then
80 filter="${overrides}/''${identifier:0:$i}"
81 echo using "${overrides}/''${identifier:0:$i}" to generate overriden binlore for $drv
82 break
83 fi
84 ((i--)) || true # don't break build
85 done # || true # don't break build
86 if [[ -d "${drv}/bin" ]] || [[ -d "${drv}/lib" ]] || [[ -d "${drv}/libexec" ]]; then
87 ${yara}/bin/yara --scan-list --recursive ${lore.rules} <(printf '%s\n' ${drv}/{bin,lib,libexec}) | ${yallback}/bin/yallback ${lore.yallback} "$filter"
88 fi
89 '';
90 };
91 overrides = (src + "/overrides");
92
93in rec {
94 collect = { lore ? loreDef, drvs, strip ? [ ] }: (runCommand "more-binlore" { } ''
95 mkdir $out
96 for lorefile in ${toString lore.types}; do
97 cat ${lib.concatMapStrings (x: x + "/$lorefile ") (map (make lore) (map lib.getBin (builtins.filter lib.isDerivation drvs)))} > $out/$lorefile
98 substituteInPlace $out/$lorefile ${lib.concatMapStrings (x: "--replace '${x}/' '' ") strip}
99 done
100 '');
101 # TODO: echo for debug, can be removed at some point
102 make = lore: drv: runCommand "${drv.name}-binlore" {
103 identifier = drv.name;
104 drv = drv;
105 } (''
106 mkdir $out
107 touch $out/{${builtins.concatStringsSep "," lore.types}}
108
109 ${lore.callback lore drv overrides}
110
111 echo binlore for $drv written to $out
112 '');
113}