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 = listOf str;26 description = ''27 Specifies the list of hosts authorized to decrypt and access this shared secret.28 '';29 };30 regenerateOnOwnerAdded = mkOption {31 type = bool;32 description = ''33 Controls whether the secret must be regenerated when new owners are added.3435 Set to true when the secret contains owner-specific references (e.g., X.509 Subject Alternative Names).36 When true, adding a new owner will trigger secret regeneration instead of simple re-encryption.37 '';38 };39 regenerateOnOwnerRemoved = mkOption {40 default = config.regenerateOnOwnerAdded;41 defaultText = literalExpression "regenerateOnOwnerAdded";42 type = bool;43 description = ''44 Determines secret behavior when owners are removed from the configuration.4546 Typically mirrors regenerateOnOwnerAdded. Override cautiously.47 Set to false if host permissions are revoked through alternative mechanisms like firewall rules.48 '';49 };50 allowDifferent = mkOption {51 type = bool;52 description = ''53 When adding owner, do not update secret value for other owners, instead creating a new distribution54 '';55 };56 generator = mkOption {57 type = uniq (nullOr (functionTo package));58 description = ''59 Function evaluating to nix derivation responsible for (re)generating the secret's content.6061 An input to this function - `pkgs` of a generator host with implementation-defined representation of extra encryption data,62 use `mkSecretGenerator` helpers to implement own generators.63 '';64 default = null;65 };66 };67 };68in69{70 options = {71 secrets = mkOption {72 type = attrsOf (submodule sharedSecret);73 default = { };74 description = "Collection of secrets shared across multiple hosts with configurable ownership";75 };76 };77 config = {78 nixpkgs.overlays = [79 (final: prev: {80 mkSecretGenerators =81 { recipients }:82 rec {83 84 85 86 mkImpureSecretGenerator =87 {88 script,89 90 91 impureOn ? null,92 parts,93 }:94 (prev.writeShellScript "impureGenerator.sh" ''95 96 set -eu9798 export GENERATOR_HELPER_IDENTITIES="${concatStringsSep "\n" recipients}";99 export PATH=${final.fleet-generator-helper}/bin:$PATH100101 102 tmp=$(mktemp -d)103 cd $tmp104 105106 created_at=$(date -u +"%Y-%m-%dT%H:%M:%S.%NZ")107108 ${script}109110 if ! test -d $out; then111 echo "impure generator script did not produce expected \$out output"112 exit 1113 fi114115 echo -n $created_at > $out/created_at116 echo -n SUCCESS > $out/marker117 '').overrideAttrs118 (old: {119 passthru = {120 inherit impureOn parts;121 generatorKind = "impure";122 };123 });124 125 mkSecretGenerator = { script, parts }: mkImpureSecretGenerator { inherit script parts; };126127 128 129 130 131 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}