12{ lib }:3let4 inherit (lib.trivial) isFunction functionArgs;5 inherit (lib.options) mkOption mergeOneOption;6 inherit (lib.modules) mkOverride;7 inherit (lib.types)8 listOf9 submodule10 attrsOf11 mkOptionType12 ;13 inherit (lib.strings) optionalString hasPrefix removePrefix;14in15rec {16 types = {17 overlay = mkOptionType {18 name = "nixpkgs-overlay";19 description = "nixpkgs overlay";20 check = {21 __functor = _self: isFunction;22 isV2MergeCoherent = true;23 };24 merge = mergeOneOption;25 };26 listOfOverlay = listOf types.overlay;2728 mkHostsType = module: attrsOf (submodule module);29 mkDataType = module: submodule module;30 };3132 options = {33 mkHostsOption =34 module:35 mkOption {36 type = types.mkHostsType module;37 };38 mkDataOption =39 module:40 mkOption {41 type = types.mkDataType module;42 };43 };4445 inherit (options) mkHostsOption;4647 modules = {48 495051 mkFleetDefault = mkOverride 999;52 535455 mkFleetGeneratorDefault = mkOverride 1001;56 };5758 inherit (modules) mkFleetDefault mkFleetGeneratorDefault;5960 secrets = {6162 6364656667686970717273 mkPassword =74 {75 size ? 32,76 }:77 (78 {79 coreutils,80 mkSecretGenerator,81 }:82 mkSecretGenerator {83 script = ''84 mkdir $out85 gh generate password -o $out/secret --size ${toString size}86 '';87 parts.secret.encrypted = true;88 }89 );9091 9293949596979899100101102103104 mkEd25519 =105 {106 noEmbedPublic ? false,107 encoding ? null,108 }:109 (110 { mkSecretGenerator }:111 mkSecretGenerator {112 script = ''113 mkdir $out114 gh generate ed25519 -p $out/public -s $out/secret \115 ${optionalString noEmbedPublic "--no-embed-public"} \116 ${optionalString (encoding != null) "--encoding=${encoding}"}117 '';118 parts.secret.encrypted = true;119 parts.public.encrypted = false;120 }121 );122123 124125126127128129130131132133134 mkX25519 =135 {136 encoding ? null,137 }:138 (139 { mkSecretGenerator }:140 mkSecretGenerator {141 script = ''142 mkdir $out143 gh generate x25519 -p $out/public -s $out/secret \144 ${optionalString (encoding != null) "--encoding=${encoding}"}145 '';146147 parts.secret.encrypted = true;148 parts.public.encrypted = false;149 }150 );151152 mkAskPass =153 {154 prompt ? "Secret value",155 part ? "secret",156 }:157 (158 {159 kdePackages,160 mkImpureSecretGenerator,161 }:162 mkImpureSecretGenerator {163 164 script = ''165 mkdir $out166 ${kdePackages.kdialog}/bin/kdialog --inputbox "${prompt}" | gh private -o $out/${part}167 '';168169 parts.${part}.encrypted = true;170 }171 );172173 mkAskFile =174 {175 header ? "",176 part ? "secret",177 }:178 (179 {180 kdePackages,181 coreutils,182 mkImpureSecretGenerator,183 }:184 mkImpureSecretGenerator {185 script = ''186 mkdir $out187 tmpfile=$(${coreutils}/bin/mktemp)188 trap "${coreutils}/bin/rm -f $tmpfile" EXIT189 cat > "$tmpfile" <<'HEADER'190 ${header}191 HEADER192 ${kdePackages.kate}/bin/kate --startanon --new --block "$tmpfile"193 gh private -o $out/${part} < "$tmpfile"194 '';195196 parts.${part}.encrypted = true;197 }198 );199200 mkAskEnv =201 {202 header ? "",203 variables ? [ ],204 part ? "secret",205 }:206 mkAskFile {207 inherit part;208 header = builtins.concatStringsSep "\n" (209 (map (l: "# ${l}") (lib.splitString "\n" header))210 ++ (map (v: "${v}=") variables)211 );212 };213214 215216217218219220221222223224 mkRsa =225 {226 size ? 4096,227 }:228 (229 {230 openssl,231 mkSecretGenerator,232 }:233 mkSecretGenerator {234 script = ''235 mkdir $out236237 ${openssl}/bin/openssl genrsa -out rsa_private.key ${toString size}238 ${openssl}/bin/openssl rsa -in rsa_private.key -pubout -out rsa_public.key239240 cat rsa_private.key | gh private -o $out/secret241 cat rsa_public.key | gh public -o $out/public242 '';243244 parts.secret.encrypted = true;245 parts.public.encrypted = false;246 }247 );248249 250251252253254255256257258259260261262263 mkBytes =264 {265 count ? 32,266 encoding,267 noNuls ? false,268 }:269 (270 { mkSecretGenerator }:271 mkSecretGenerator {272 script = ''273 mkdir $out274 gh generate bytes --count=${toString count} --encoding=${encoding} -o $out/secret \275 ${optionalString noNuls "--no-nuls"}276 '';277 parts.secret.encrypted = true;278 }279 );280 281282283 mkHexBytes =284 {285 count ? 32,286 }:287 mkBytes {288 inherit count;289 encoding = "hex";290 };291 292293294 mkBase64Bytes =295 {296 count ? 32,297 }:298 mkBytes {299 inherit count;300 encoding = "base64";301 };302303 304 305 306 };307308 inherit (secrets)309 mkPassword310 mkEd25519311 mkX25519312 mkRsa313 mkBytes314 mkHexBytes315 mkBase64Bytes316 mkAskPass317 mkAskFile318 mkAskEnv319 ;320321 strings =322 let323 plaintextPrefix = "<PLAINTEXT>";324 plaintextNewlinePrefix = "<PLAINTEXT-NL>";325 in326 {327 328329330 decodeRawSecret =331 raw:332 if hasPrefix plaintextPrefix raw then333 removePrefix plaintextPrefix raw334 else if hasPrefix plaintextNewlinePrefix raw then335 removePrefix plaintextNewlinePrefix raw336 else337 throw "decodeRawSecret only works with plaintext-encoded secret public parts, got ${raw}";338 };339340 inherit (strings) decodeRawSecret;341}