1{2 lib,3 ...4}:5let6 inherit (lib.options) mkOption literalExpression;7 inherit (lib.types)8 nullOr9 listOf10 str11 bool12 attrsOf13 submodule14 functionTo15 package16 uniq17 ;18 inherit (lib.strings) concatStringsSep;1920 sharedSecret =21 { config, ... }:22 {23 options = {24 expectedOwners = mkOption {25 type = nullOr (listOf str);26 description = ''27 Specifies the list of hosts authorized to decrypt and access this shared secret.2829 When null, secret ownership is managed manually via fleet.nix and CLI.30 Decrypted secrets will be stored at /run/secrets/$\{name} on authorized hosts.31 '';32 default = null;33 };34 regenerateOnOwnerAdded = mkOption {35 type = bool;36 description = ''37 Controls whether the secret must be regenerated when new owners are added.3839 Set to true when the secret contains owner-specific references (e.g., X.509 Subject Alternative Names).40 When true, adding a new owner will trigger secret regeneration instead of simple re-encryption.41 '';42 };43 regenerateOnOwnerRemoved = mkOption {44 default = config.regenerateOnOwnerAdded;45 defaultText = literalExpression "regenerateOnOwnerAdded";46 type = bool;47 description = ''48 Determines secret behavior when owners are removed from the configuration.4950 Typically mirrors regenerateOnOwnerAdded. Override cautiously.51 Set to false if host permissions are revoked through alternative mechanisms like firewall rules.52 '';53 };54 allowDifferent = mkOption {55 type = bool;56 description = ''57 When adding owner, do not update secret value for other owners, instead creating a new distribution58 '';59 };60 generator = mkOption {61 type = uniq (nullOr (functionTo package));62 description = ''63 Function evaluating to nix derivation responsible for (re)generating the secret's content.6465 An input to this function - `pkgs` of a generator host with implementation-defined representation of extra encryption data,66 use `mkSecretGenerator` helpers to implement own generators.67 '';68 default = null;69 };70 };71 };72in73{74 options = {75 secrets = mkOption {76 type = attrsOf (submodule sharedSecret);77 default = { };78 description = "Collection of secrets shared across multiple hosts with configurable ownership";79 };80 };81 config = {82 nixpkgs.overlays = [83 (final: prev: {84 mkSecretGenerators =85 { recipients }:86 rec {87 88 89 90 mkImpureSecretGenerator =91 {92 script,93 94 95 impureOn ? null,96 parts,97 }:98 (prev.writeShellScript "impureGenerator.sh" ''99 100 set -eu101102 export GENERATOR_HELPER_IDENTITIES="${concatStringsSep "\n" recipients}";103 export PATH=${final.fleet-generator-helper}/bin:$PATH104105 106 tmp=$(mktemp -d)107 cd $tmp108 109110 created_at=$(date -u +"%Y-%m-%dT%H:%M:%S.%NZ")111112 ${script}113114 if ! test -d $out; then115 echo "impure generator script did not produce expected \$out output"116 exit 1117 fi118119 echo -n $created_at > $out/created_at120 echo -n SUCCESS > $out/marker121 '').overrideAttrs122 (old: {123 passthru = {124 inherit impureOn parts;125 generatorKind = "impure";126 };127 });128 129 mkSecretGenerator = { script, parts }: mkImpureSecretGenerator { inherit script parts; };130131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 };160 })161 ];162 };163}