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 105 106 mkPostgresPassword =107 {108 size ? 32,109 iterations ? 4096,110 noSymbols ? false,111 }:112 (113 { mkSecretGenerator }:114 mkSecretGenerator {115 script = ''116 mkdir $out117 gh generate postgres-password \118 -s $out/secret \119 -H $out/hash \120 --size ${toString size} \121 --iterations ${toString iterations} \122 ${optionalString noSymbols "--no-symbols"}123 '';124 parts.secret.encrypted = true;125 parts.hash.encrypted = false;126 }127 );128129 130131132133134135136137138139140141142 mkEd25519 =143 {144 noEmbedPublic ? false,145 encoding ? null,146 }:147 (148 { mkSecretGenerator }:149 mkSecretGenerator {150 script = ''151 mkdir $out152 gh generate ed25519 -p $out/public -s $out/secret \153 ${optionalString noEmbedPublic "--no-embed-public"} \154 ${optionalString (encoding != null) "--encoding=${encoding}"}155 '';156 parts.secret.encrypted = true;157 parts.public.encrypted = false;158 }159 );160161 162163164165166167168169170171172 mkX25519 =173 {174 encoding ? null,175 }:176 (177 { mkSecretGenerator }:178 mkSecretGenerator {179 script = ''180 mkdir $out181 gh generate x25519 -p $out/public -s $out/secret \182 ${optionalString (encoding != null) "--encoding=${encoding}"}183 '';184185 parts.secret.encrypted = true;186 parts.public.encrypted = false;187 }188 );189190 mkAskPass =191 {192 prompt ? "Secret value",193 part ? "secret",194 }:195 (196 {197 kdePackages,198 mkImpureSecretGenerator,199 }:200 mkImpureSecretGenerator {201 script = ''202 mkdir $out203 ${kdePackages.kdialog}/bin/kdialog --inputbox "${prompt}" | gh private -o $out/${part}204 '';205206 parts.${part}.encrypted = true;207 }208 );209210 mkAskFile =211 {212 header ? "",213 part ? "secret",214 }:215 (216 {217 kdePackages,218 coreutils,219 mkImpureSecretGenerator,220 }:221 mkImpureSecretGenerator {222 script = ''223 mkdir $out224 tmpfile=$(${coreutils}/bin/mktemp)225 trap "${coreutils}/bin/rm -f $tmpfile" EXIT226 cat > "$tmpfile" <<'HEADER'227 ${header}228 HEADER229 ${kdePackages.kate}/bin/kate --startanon --new --block "$tmpfile"230 gh private -o $out/${part} < "$tmpfile"231 '';232233 parts.${part}.encrypted = true;234 }235 );236237 mkAskEnv =238 {239 header ? "",240 variables ? [ ],241 part ? "secret",242 }:243 mkAskFile {244 inherit part;245 header = builtins.concatStringsSep "\n" (246 (map (l: "# ${l}") (lib.splitString "\n" header)) ++ (map (v: "${v}=") variables)247 );248 };249250 251252253254255256257258259260 mkRsa =261 {262 size ? 4096,263 }:264 (265 {266 openssl,267 mkSecretGenerator,268 }:269 mkSecretGenerator {270 script = ''271 mkdir $out272273 ${openssl}/bin/openssl genrsa -out rsa_private.key ${toString size}274 ${openssl}/bin/openssl rsa -in rsa_private.key -pubout -out rsa_public.key275276 cat rsa_private.key | gh private -o $out/secret277 cat rsa_public.key | gh public -o $out/public278 '';279280 parts.secret.encrypted = true;281 parts.public.encrypted = false;282 }283 );284285 286287288289290291292293294295296297298299 mkBytes =300 {301 count ? 32,302 encoding,303 noNuls ? false,304 }:305 (306 { mkSecretGenerator }:307 mkSecretGenerator {308 script = ''309 mkdir $out310 gh generate bytes --count=${toString count} --encoding=${encoding} -o $out/secret \311 ${optionalString noNuls "--no-nuls"}312 '';313 parts.secret.encrypted = true;314 }315 );316 317318319 mkHexBytes =320 {321 count ? 32,322 }:323 mkBytes {324 inherit count;325 encoding = "hex";326 };327 328329330 mkBase64Bytes =331 {332 count ? 32,333 }:334 mkBytes {335 inherit count;336 encoding = "base64";337 };338339 340 341 342 };343344 inherit (secrets)345 mkPassword346 mkPostgresPassword347 mkEd25519348 mkX25519349 mkRsa350 mkBytes351 mkHexBytes352 mkBase64Bytes353 mkAskPass354 mkAskFile355 mkAskEnv356 ;357358 strings =359 let360 plaintextPrefix = "<PLAINTEXT>";361 plaintextNewlinePrefix = "<PLAINTEXT-NL>";362 in363 {364 365366367 decodeRawSecret =368 raw:369 if hasPrefix plaintextPrefix raw then370 removePrefix plaintextPrefix raw371 else if hasPrefix plaintextNewlinePrefix raw then372 removePrefix plaintextNewlinePrefix raw373 else374 throw "decodeRawSecret only works with plaintext-encoded secret public parts, got ${raw}";375 };376377 inherit (strings) decodeRawSecret;378}