git.delta.rocks / jrsonnet / refs/commits / 53503cecc600

difftreelog

feat shared secrets expected owners

Yaroslav Bolyukin2022-03-27parent: #144b321.patch.diff
in: trunk

7 files changed

modifiedcrates/nixlike/Cargo.tomldiffbeforeafterboth
--- a/crates/nixlike/Cargo.toml
+++ b/crates/nixlike/Cargo.toml
@@ -4,7 +4,7 @@
 edition = "2021"
 
 [dependencies]
-dprint-core = "0.50.0"
+dprint-core = "0.51.0"
 linked-hash-map = "0.5.4"
 peg = "0.8.0"
 serde = "1.0.130"
modifiedlib/default.nixdiffbeforeafterboth
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -1,47 +1,56 @@
 { flake-utils }: {
   fleetConfiguration = { data, nixpkgs, hosts, ... }@allConfig:
     let
+      hostNames = nixpkgs.lib.attrNames hosts;
       config = builtins.removeAttrs allConfig [ "nixpkgs" "data" ];
       fleetLib = import ./fleetLib.nix {
-        inherit nixpkgs hosts;
+        inherit nixpkgs hostNames;
       };
     in
-    nixpkgs.lib.genAttrs flake-utils.lib.defaultSystems (system: rec {
-      root = nixpkgs.lib.evalModules {
-        modules = (import ../modules/fleet/_modules.nix) ++ [ config data ];
-        specialArgs = {
-          inherit nixpkgs;
-          fleet = fleetLib;
+    nixpkgs.lib.genAttrs flake-utils.lib.defaultSystems (system:
+      let
+        root = nixpkgs.lib.evalModules {
+          modules = (import ../modules/fleet/_modules.nix) ++ [ config data ];
+          specialArgs = {
+            inherit nixpkgs fleetLib;
+          };
         };
-      };
-      configuredHosts = root.config.hosts;
-      configuredSecrets = root.config.secrets;
-      configuredSystems = nixpkgs.lib.listToAttrs (
-        map
-          (
-            name: {
-              inherit name;
-              value = nixpkgs.lib.nixosSystem {
-                system = configuredHosts.${name}.system;
-                modules = configuredHosts.${name}.modules ++ (
-                  if configuredHosts.${name}.system == "aarch64-linux" then [ (nixpkgs + "/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix") ]
-                  else [ ]
-                ) ++ [
-                  ({ ... }: {
-                    nixpkgs.system = system;
-                    nixpkgs.localSystem.system = system;
-                    nixpkgs.crossSystem = if system == configuredHosts.${name}.system then null else {
-                      system = configuredHosts.${name}.system;
-                    };
-                  })
-                ];
-                specialArgs = {
-                  fleet = fleetLib.hostsToAttrs (host: configuredSystems.${host}.config);
+        failedAssertions = map (x: x.message) (nixpkgs.lib.filter (x: !x.assertion) root.config.assertions);
+        rootAssertWarn =
+          if failedAssertions != [ ]
+          then throw "Failed assertions:\n${nixpkgs.lib.concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
+          else nixpkgs.lib.showWarnings root.config.warnings root;
+      in
+      rec {
+        configuredHosts = rootAssertWarn.config.hosts;
+        configuredSecrets = rootAssertWarn.config.secrets;
+        configuredSystems = nixpkgs.lib.listToAttrs (
+          map
+            (
+              name: {
+                inherit name;
+                value = nixpkgs.lib.nixosSystem {
+                  system = configuredHosts.${name}.system;
+                  modules = configuredHosts.${name}.modules ++ (
+                    if configuredHosts.${name}.system == "aarch64-linux" then [ (nixpkgs + "/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix") ]
+                    else [ ]
+                  ) ++ [
+                    ({ ... }: {
+                      nixpkgs.system = system;
+                      nixpkgs.localSystem.system = system;
+                      nixpkgs.crossSystem = if system == configuredHosts.${name}.system then null else {
+                        system = configuredHosts.${name}.system;
+                      };
+                    })
+                  ];
+                  specialArgs = {
+                    inherit fleetLib;
+                    fleet = fleetLib.hostsToAttrs (host: configuredSystems.${host}.config);
+                  };
                 };
-              };
-            }
-          )
-          (builtins.attrNames root.config.hosts)
-      ); #nixpkgs.lib.nixosSystem {}
-    });
+              }
+            )
+            (builtins.attrNames rootAssertWarn.config.hosts)
+        ); #nixpkgs.lib.nixosSystem {}
+      });
 }
modifiedlib/fleetLib.nixdiffbeforeafterboth
--- a/lib/fleetLib.nix
+++ b/lib/fleetLib.nix
@@ -1,7 +1,5 @@
 # Shared functions for fleet configuration, available as `fleet` module argument
-{ nixpkgs, hosts }: with nixpkgs.lib; rec {
-  # Modules can't register hosts because of infinite recursion
-  hostNames = attrNames hosts;
+{ nixpkgs, hostNames }: with nixpkgs.lib; rec {
   hostsToAttrs = f: listToAttrs (
     map (name: { inherit name; value = f name; }) hostNames
   );
@@ -25,4 +23,7 @@
       a = elemAt sorted 0;
       b = elemAt sorted 1;
     };
+  hostPairName = this: other:
+    if this < other then "${this}-${other}"
+    else "${other}-${this}";
 }
modifiedmodules/fleet/_modules.nixdiffbeforeafterboth
--- a/modules/fleet/_modules.nix
+++ b/modules/fleet/_modules.nix
@@ -1,4 +1,5 @@
 [
+  ./assertions.nix
   ./meta.nix
   ./secrets.nix
 ]
addedmodules/fleet/assertions.nixdiffbeforeafterboth
--- /dev/null
+++ b/modules/fleet/assertions.nix
@@ -0,0 +1,34 @@
+{ lib, ... }:
+
+with lib;
+
+{
+
+  options = {
+
+    assertions = mkOption {
+      type = types.listOf types.unspecified;
+      internal = true;
+      default = [ ];
+      example = [{ assertion = false; message = "you can't enable this for that reason"; }];
+      description = ''
+        This option allows modules to express conditions that must
+        hold for the evaluation of the system configuration to
+        succeed, along with associated error messages for the user.
+      '';
+    };
+
+    warnings = mkOption {
+      internal = true;
+      default = [ ];
+      type = types.listOf types.str;
+      example = [ "The `foo' service is deprecated and will go away soon!" ];
+      description = ''
+        This option allows modules to show warnings to users during
+        the evaluation of the system configuration.
+      '';
+    };
+
+  };
+  # impl of assertions is in <fleet/lib/default.nix>
+}
modifiedmodules/fleet/meta.nixdiffbeforeafterboth
--- a/modules/fleet/meta.nix
+++ b/modules/fleet/meta.nix
@@ -1,4 +1,4 @@
-{ lib, fleet, config, ... }: with lib;
+{ lib, fleetLib, config, ... }: with lib;
 let
   host = with types; {
     options = {
@@ -42,7 +42,7 @@
     };
   };
   config = {
-    hosts = fleet.hostsToAttrs (host: {
+    hosts = fleetLib.hostsToAttrs (host: {
       modules = config.globalModules;
     });
     globalModules = import ../../nixos/modules/module-list.nix;
modifiedmodules/fleet/secrets.nixdiffbeforeafterboth
before · modules/fleet/secrets.nix
1{ lib, fleet, config, ... }: with lib;2let3  sharedSecret = with types; {4    options = {5      owners = mkOption {6        type = listOf str;7        description = ''8          List of hosts to encrypt secret for910          Secrets would be decrypted and stored to /run/secrets/$\{name} on owners11        '';12      };13      generator = mkOption {14        type = package;15        description = "Derivation to execute for secret generation";16      };17      expireIn = mkOption {18        type = nullOr int;19        description = "Time in hours, in which this secret should be regenerated";20        default = null;21      };22      public = mkOption {23        type = nullOr str;24        description = "Secret public data";25        default = null;26      };27      secret = mkOption {28        type = nullOr str;29        description = "Encrypted secret data";30        default = null;31      };32    };33  };34  hostSecret = with types; {35    options = {36      generator = mkOption {37        type = package;38        description = "Derivation to execute for secret generation";39      };40      expireIn = mkOption {41        type = nullOr int;42        description = "Time in hours, in which this secret should be regenerated";43        default = null;44      };45      public = mkOption {46        type = nullOr str;47        description = "Secret public data";48        default = null;49      };50      secret = mkOption {51        type = str;52        description = "Encrypted secret data";53      };54    };55  };56in57{58  options = with types; {59    sharedSecrets = mkOption {60      type = attrsOf (submodule sharedSecret);61      default = { };62      description = "Shared secrets";63    };64    hostSecrets = mkOption {65      type = attrsOf (attrsOf (submodule hostSecret));66      default = { };67      description = "Host secrets";68    };69  };70  config = with fleet; {71    hosts = hostsToAttrs (host: {72      modules =73        let74          cleanupSecret = (secretName: v: {75            inherit (v) public secret;76          });77        in78        [79          {80            secrets = (mapAttrs cleanupSecret81              (filterAttrs (_: v: builtins.elem host v.owners) config.sharedSecrets)82            ) // (mapAttrs cleanupSecret (config.hostSecrets.${host} or { }));83          }84        ];85    });86  };87}
after · modules/fleet/secrets.nix
1{ lib, fleetLib, config, ... }: with lib; with fleetLib;2let3  sharedSecret = with types; {4    options = {5      owners = mkOption {6        type = listOf str;7        description = ''8          For which owners this secret is currently encrypted,9          if not matches expectedOwners - then this secret is considered outdated, and10          should be regenerated/reencrypted11        '';12      };13      expectedOwners = mkOption {14        type = listOf str;15        description = ''16          List of hosts to encrypt secret for1718          Secrets would be decrypted and stored to /run/secrets/$\{name} on owners19        '';20        default = [ ];21      };22      generator = mkOption {23        type = package;24        description = "Derivation to execute for secret generation";25      };26      expireIn = mkOption {27        type = nullOr int;28        description = "Time in hours, in which this secret should be regenerated";29        default = null;30      };31      public = mkOption {32        type = nullOr str;33        description = "Secret public data";34        default = null;35      };36      secret = mkOption {37        type = nullOr str;38        description = "Encrypted secret data";39        default = null;40      };41    };42  };43  hostSecret = with types; {44    options = {45      generator = mkOption {46        type = package;47        description = "Derivation to execute for secret generation";48      };49      expireIn = mkOption {50        type = nullOr int;51        description = "Time in hours, in which this secret should be regenerated";52        default = null;53      };54      public = mkOption {55        type = nullOr str;56        description = "Secret public data";57        default = null;58      };59      secret = mkOption {60        type = str;61        description = "Encrypted secret data";62      };63    };64  };65in66{67  options = with types; {68    sharedSecrets = mkOption {69      type = attrsOf (submodule sharedSecret);70      default = { };71      description = "Shared secrets";72    };73    hostSecrets = mkOption {74      type = attrsOf (attrsOf (submodule hostSecret));75      default = { };76      description = "Host secrets";77    };78  };79  config = {80    assertions = mapAttrsToList81      (name: secret: {82        assertion = builtins.sort (a: b: a < b) secret.owners == builtins.sort (a: b: a < b) secret.expectedOwners;83        message = "Shared secret ${name} is expected to be encrypted for ${builtins.toJSON secret.expectedOwners}, but it is encrypted for ${builtins.toJSON secret.owners}";84      })85      config.sharedSecrets;86    hosts = hostsToAttrs (host: {87      modules =88        let89          cleanupSecret = (secretName: v: {90            inherit (v) public secret;91          });92        in93        [94          {95            secrets = (mapAttrs cleanupSecret96              (filterAttrs (_: v: builtins.elem host v.owners) config.sharedSecrets)97            ) // (mapAttrs cleanupSecret (config.hostSecrets.${host} or { }));98          }99        ];100    });101  };102}