1{ lib, fleetLib, config, ... }: with lib; with fleetLib;2let3 sharedSecret = with types; ({config, ...}: {4 options = {5 expectedOwners = mkOption {6 type = nullOr (listOf str);7 description = ''8 List of hosts to encrypt secret for. null if managed by user (= via owners field from fleet.nix)910 Secrets would be decrypted and stored to /run/secrets/$\{name} on owners11 '';12 };13 14 regenerateOnOwnerAdded = mkOption {15 type = bool;16 description = ''17 Is this secret owner-dependent, and needs to be regenerated on ownership set change, or it may be just reencrypted.18 19 You want to have this option set to true, when this secret contains some reference to its owners, i.e x509 SANs.20 '';21 };22 regenerateOnOwnerRemoved = mkOption {23 default = config.regenerateOnOwnerAdded;24 type = bool;25 description = ''26 Should this secret be removed on owner removal, or it may be just reencrypted27 28 Most probably its value should be equal to regenerateOnOwnerAdded, override only if you know what are you doing.29 Contrary to regenerateOnOwnerAdded, you may want to set this option to false, when host permissions are revoked30 in some other way than by this secret ownership, I.e by firewall/etc.31 '';32 };33 generator = mkOption {34 type = nullOr unspecified;35 description = "Derivation to evaluate for secret generation";36 default = null;37 };38 createdAt = mkOption {39 type = nullOr str;40 description = "When this secret was (re)generated";41 default = null;42 };43 expiresAt = mkOption {44 type = nullOr str;45 description = "On which date this secret will expire, someone should regenerate this secret before it expires.";46 default = null;47 };4849 owners = mkOption {50 type = listOf str;51 description = ''52 For which owners this secret is currently encrypted,53 if not matches expectedOwners - then this secret is considered outdated, and54 should be regenerated/reencrypted.5556 Imported from fleet.nix57 '';58 default = [ ];59 };60 61 62 63 public = mkOption {64 type = nullOr str;65 description = "Secret public data. Imported from fleet.nix";66 default = null;67 };68 secret = mkOption {69 type = nullOr str;70 description = "Encrypted secret data. Imported from fleet.nix";71 default = null;72 internal = true;73 };74 };75 });76 hostSecret = with types; {77 options = {78 createdAt = mkOption {79 type = nullOr str;80 default = null;81 };82 expiresAt = mkOption {83 type = nullOr str;84 default = null;85 };86 public = mkOption {87 type = nullOr str;88 description = "Secret public data. Imported from fleet.nix";89 default = null;90 };91 secret = mkOption {92 type = nullOr str;93 description = "Encrypted secret data. Imported from fleet.nix";94 default = null;95 internal = true;96 };97 };98 };99in100{101 options = with types; {102 sharedSecrets = mkOption {103 type = attrsOf (submodule sharedSecret);104 default = { };105 description = "Shared secrets";106 };107 hostSecrets = mkOption {108 type = attrsOf (attrsOf (submodule hostSecret));109 default = { };110 description = "Host secrets. Imported from fleet.nix";111 internal = true;112 };113 };114 config = {115 assertions = mapAttrsToList116 (name: secret: {117 assertion = secret.expectedOwners == null || builtins.sort (a: b: a < b) secret.owners == builtins.sort (a: b: a < b) secret.expectedOwners;118 message = "Shared secret ${name} is expected to be encrypted for ${builtins.toJSON secret.expectedOwners}, but it is encrypted for ${builtins.toJSON secret.owners}. Run fleet secrets regenerate to fix";119 })120 config.sharedSecrets;121 hosts = hostsToAttrs (host: {122 modules =123 let124 cleanupSecret = (secretName: v: {125 inherit (v) public secret;126 shared = true;127 });128 in129 [130 {131 secrets = (mapAttrs cleanupSecret132 (filterAttrs (_: v: builtins.elem host v.owners) config.sharedSecrets)133 ) // (mapAttrs cleanupSecret (config.hostSecrets.${host} or { }));134 }135 ];136 });137 };138}