git.delta.rocks / jrsonnet / refs/commits / d97c9fe9e5c4

difftreelog

source

modules/nixos/secrets.nix5.8 KiBsourcehistory
1{2  lib,3  fleetLib,4  config,5  pkgs,6  fleetConfiguration,7  ...8}:9let10  inherit (builtins)11    hashString12    toJSON13    ;14  inherit (lib.stringsWithDeps) stringAfter;15  inherit (lib.options) mkOption literalExpression;16  inherit (lib.lists) optional;17  inherit (lib.attrsets) mapAttrs mapAttrsToList;18  inherit (lib.modules) mkIf;19  inherit (lib.types)20    submodule21    str22    attrsOf23    unspecified24    uniq25    functionTo26    package27    bool28    enum29    either30    ;31  inherit (fleetLib.strings) decodeRawSecret;3233  sysConfig = config;34  secretPartType =35    secretName:36    submodule (37      { config, ... }:38      let39        partName = config._module.args.name;40      in41      {42        options = {43          hash = mkOption {44            type = str;45            description = "Hash of secret in encoded format";46          };47          path = mkOption {48            type = str;49            description = "Path to secret part, incorporating data hash (thus it will be updated on secret change)";50          };51          stablePath = mkOption {52            type = str;53            description = "Path to secret part, stable path (users are expected to watch for file changes/re-read secret on demand)";54          };55          data = mkOption {56            type = str;57            description = "Secret public data (only available for plaintext)";58          };59          raw = mkOption {60            type = str;61            description = "Raw (encoded/encrypted secret part data)";62          };63        };64        config = {65          hash = hashString "sha1" config.raw;66          data = decodeRawSecret config.raw;67          path = "/run/secrets/${secretName}/${config.hash}-${partName}";68          stablePath = "/run/secrets/${secretName}/${partName}";69        };70      }71    );72  secretType = submodule (73    {74      config,75      ...76    }:77    let78      secretName = config._module.args.name;79      literal = l: enum [l];80    in81    {82      options = {83        parts = mkOption {84          type = uniq (attrsOf (secretPartType secretName));85          description = "Definition of secret parts";86        };87        generator = mkOption {88          type = either (functionTo package) (literal "shared");89          description = "Derivation to evaluate for secret generation";90        };91        mode = mkOption {92          type = str;93          description = "Secret mode";94          default = "0440";95        };96        owner = mkOption {97          type = str;98          description = "Owner of the secret";99          default = "root";100        };101        group = mkOption {102          type = str;103          description = "Group of the secret";104          default = sysConfig.users.users.${config.owner}.group;105          defaultText = literalExpression "config.users.users.$${owner}.group";106        };107      };108      config = {109        # C api is broken in regard to thunks110        # https://github.com/NixOS/nix/issues/12800111        parts = let 112          hostName = sysConfig.networking.hostName;113          generator = config.generator;114        in builtins.deepSeq [115          hostName116          secretName117          generator118        ] (builtins.fleetEnsureHostSecret119          hostName120          secretName121          generator);122      };123    }124  );125  secretsFile = pkgs.writeTextFile {126    name = "secrets.json";127    text = toJSON config.system.secretsData;128  };129  useSysusers =130    (config.systemd ? sysusers && config.systemd.sysusers.enable)131    || (config ? userborn && config.userborn.enable);132in133{134  options = {135    secrets = mkOption {136      type = attrsOf secretType;137      default = { };138      apply = mapAttrs (_: secret: secret.parts // {definition = secret;});139      description = "Host-local secrets";140    };141    system.secretsData = mkOption {142      type = unspecified;143      default = mapAttrs (_: s:144        (removeAttrs s.definition ["generator"]) // {145          parts = mapAttrs (_: part: removeAttrs part ["data"]) s.definition.parts;146        }147      ) config.secrets;148      description = "secrets.json contents";149    };150  };151  config = {152    environment.systemPackages = [ pkgs.fleet-install-secrets ];153154    assertions = mapAttrsToList (name: secret: let155      hasSharedDefinition = fleetConfiguration.secrets ? name;156    in {157      assertion = (secret.definition.generator == "shared") == hasSharedDefinition;158      message = if hasSharedDefinition then"secret ${name} has host-specific secret generator, secrets with host-specific generators can not have shared generator in fleet configuration"159      else "secret ${name} is declared as shared, for shared secret fleet configuration should include shared secret generator";160    }) config.secrets;161162    systemd.services.fleet-install-secrets = mkIf useSysusers {163      wantedBy = [ "sysinit.target" ];164      after = [ "systemd-sysusers.service" ];165      restartTriggers = [166        secretsFile167      ];168      aliases = [169        "sops-install-secrets"170        "agenix-install-secrets"171      ];172173      unitConfig.DefaultDependencies = false;174175      serviceConfig = {176        Type = "oneshot";177        RemainAfterExit = true;178        ExecStart = "${pkgs.fleet-install-secrets}/bin/fleet-install-secrets install ${secretsFile}";179      };180    };181    system.activationScripts.decryptSecrets = mkIf (!useSysusers) (182      stringAfter183        (184          [185            # secrets are owned by user/group, thus we need to refer to those186            "users"187            "groups"188            "specialfs"189          ]190          # nixos-impermanence compatibility: secrets are encrypted by host-key,191          # but with impermanence we expect that the host-key is installed by192          # persist-file activation script.193          ++ (optional (config.system.activationScripts ? "persist-files") "persist-files")194        )195        ''196          1>&2 echo "setting up secrets"197          ${pkgs.fleet-install-secrets}/bin/fleet-install-secrets install ${secretsFile}198        ''199    );200  };201}