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 generationData ? null,93 parts,94 }:95 (prev.writeShellScript "impureGenerator.sh" ''96 97 set -eu9899 export GENERATOR_HELPER_IDENTITIES="${concatStringsSep "\n" recipients}";100 export PATH=${final.fleet-generator-helper}/bin:$PATH101102 103 tmp=$(mktemp -d)104 cd $tmp105 106107 created_at=$(date -u +"%Y-%m-%dT%H:%M:%S.%NZ")108109 ${script}110111 if ! test -d $out; then112 echo "impure generator script did not produce expected \$out output"113 exit 1114 fi115116 echo -n $created_at > $out/created_at117 echo -n SUCCESS > $out/marker118 '').overrideAttrs119 (old: {120 passthru = {121 inherit impureOn parts generationData;122 generatorKind = "impure";123 };124 });125 126 mkSecretGenerator = { script, parts }: mkImpureSecretGenerator { inherit script parts; };127128 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 };160}