git.delta.rocks / fleet / refs/commits / 7bc4be6bcef6

difftreelog

source

lib/default.nix9.8 KiBsourcehistory
1# Shared functions for fleet configuration, available as `fleet` module argument2{ 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    /**49      Use in places, where fleet might know better than nixpkgs defaults to50    */51    mkFleetDefault = mkOverride 999;52    /**53      Some generators use mkDefault, but optionDefault is set by nixpkgs.54    */55    mkFleetGeneratorDefault = mkOverride 1001;56  };5758  inherit (modules) mkFleetDefault mkFleetGeneratorDefault;5960  secrets = {6162    /**63      Generate a random secret password, 32 ascii characters by default6465      Options:66        size: generated password length in ascii characters (bytes).67        noSymbols: by default, character set includes various special characters ($ , ! + * : ~), and might68                   not be accepted in some contexts, this option switches charset to just [A-Za-z0-9].6970      Output:71        Resulting secret has only part: secret, which contains encrypted password.72    */73    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    /**92      Generate a random password suitable for PostgreSQL role authentication.9394      Options:95        size: generated password length in ascii characters (bytes).96        iterations: PBKDF2 iteration count (PG default: 4096).97        noSymbols: by default, character set includes various special characters ($ , ! + * : ~), and might98                   not be accepted in some contexts, this option switches charset to just [A-Za-z0-9].99100      Output:101        secret: encrypted password.102        hash: SCRAM-SHA-256 hash of the password to be used by postgres.103    */104    # It is not possible to extract it into a scram-sha-256 generic generator because there is no estabilished format105    # for it, and mongodb for example encodes it differently.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    /**130      Generate a random ed25519 keypair131132      Options:133        noEmbedPublic: By default, secret key also embeds public key in itself ("extended" format, 64 bytes)134                       When noEmbedPublis is enabled - only the private scalar is included.135        encoding: Encoring of public and secret parts, can be "raw" (default), "base64" or "hex".136137      Output:138        Resulting secret has two parts: public and secret, where the secret part is encrypted.139140      This secret format is used by e.g Garage S3 server141    */142    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    /**162      Generate a random x25519 keypair163164      Options:165        encoding: Encoring of public and secret parts, can be "raw" (default), "base64" or "hex".166167      Output:168        Resulting secret has two parts: public and secret, where the secret part is encrypted.169170      This secret format is used by e.g Wireguard VPN for peers (base64-encoded)171    */172    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    /**251      Generate a random RSA keypair252253      Options:254        size: RSA key size, 4096 by default255256      Output:257        Resulting secret has two parts: public and secret, where the secret part is encrypted.258        Both parts are PEM encoded.259    */260    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    /**286      Generate a random byte sequence287288      Options:289        size: generated password length in bytes, 32 by default.290        encoding: how the generated bytes should be encoded, "raw" (default), "hex" or "base64"291        noNuls: prevent output byte sequence from containing internal \0, useful for some C applications292                that can't handle their strings properly.293294      Output:295        Resulting secret has only part: secret, which contains encrypted bytes.296297      Might be used for e.g. Wireguard VPN PSK keys (base64-encoded)298    */299    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    /**317      Shorthand for `mkBytes`, which defaults to "hex" encoding318    */319    mkHexBytes =320      {321        count ? 32,322      }:323      mkBytes {324        inherit count;325        encoding = "hex";326      };327    /**328      Shorthand for `mkBytes`, which defaults to "base64" encoding329    */330    mkBase64Bytes =331      {332        count ? 32,333      }:334      mkBytes {335        inherit count;336        encoding = "base64";337      };338339    # Wireguard340    # mkWireguard = {}: mkX25519 {encoding = "base64";};341    # mkWireguardPsk = {}: mkBase64Bytes {count = 32;};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      /**365        Decode public secret part into string366      */367      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}