{ config, pkgs, lib, tflib, ... }: let cfg = config.prefab.consulAgent; inherit (lib) mkOption types mapAttrsToList fix optionalString optionalAttrs singleton mkMerge flip ; inherit (tflib) tf ; submoduleOptions = { datacenter = mkOption { description = '' ''; type = types.str; }; replicationDatacenters = mkOption { description = '' ''; type = with types; listOf str; }; encryptionKey = mkOption { description = '' DO NOT hardcode the secret in Nix, generate it with Terraform and let Terraform substitute it. ''; type = types.str; }; anonymousToken = mkOption { description = '' DO NOT hardcode the secret in Nix, generate it with Terraform and let Terraform substitute it. ''; type = types.submodule { options.secret = mkOption { description = ''''; type = types.str; }; options.accessor = mkOption { description = ''''; type = types.str; }; }; }; paths = { encryptionKey = mkOption { description = '' ''; type = types.str; }; agentToken = mkOption { description = '' ''; type = types.str; }; replicationToken = mkOption { description = '' ''; type = with types; nullOr str; default = null; }; anonymousToken = mkOption { description = '' ''; type = types.str; }; }; vaultKvMount = mkOption { description = '' ''; type = types.str; }; }; in { options.prefab.consulAgent = mkOption { description = '' ''; type = with types; attrsOf (submodule {options = submoduleOptions;}); default = {}; }; config.resource = mkMerge (flip mapAttrsToList cfg (hostname: value: fix (self: { "consul_acl_policy"."${hostname}_agent" = { name = "${hostname}-consul-agent"; rules = '' node "${hostname}" { policy = "write" } agent "${hostname}" { policy = "write" } service_prefix "" { policy = "write" } ''; }; "consul_acl_token"."${hostname}_consul_agent" = { description = "Consul agent token on ${hostname}"; node_identities = singleton { node_name = hostname; datacenter = value.datacenter; }; local = false; }; "vault_kv_secret_v2"."${hostname}_consul_encryption_key" = { mount = value.vaultKvMount; name = value.paths.encryptionKey; delete_all_versions = true; data_json = builtins.toJSON { key = value.encryptionKey; }; }; "vault_kv_secret_v2"."${hostname}_consul_anonymous_token" = { mount = value.vaultKvMount; name = value.paths.anonymousToken; delete_all_versions = true; data_json = builtins.toJSON { secret = value.anonymousToken.secret; accessor = value.anonymousToken.accessor; }; }; "vault_kv_secret_v2"."${hostname}_consul_agent" = { mount = value.vaultKvMount; name = value.paths.agentToken; delete_all_versions = true; data_json = builtins.toJSON { secret = tf "data.consul_acl_token_secret_id.${hostname}_consul_agent.secret_id"; accessor = tf "consul_acl_token.${hostname}_consul_agent.id"; }; }; "vault_policy"."${hostname}_consul" = { name = "${hostname}_consul_agent"; policy = '' path "${value.vaultKvMount}/data/${value.paths.encryptionKey}" { capabilities = ["read"] } path "${value.vaultKvMount}/data/${value.paths.agentToken}" { capabilities = ["read"] } ${optionalString (value.paths.replicationToken != null) '' path "${value.vaultKvMount}/data/${value.paths.replicationToken}" { capabilities = ["read"] } ''} path "${value.vaultKvMount}/data/${value.paths.anonymousToken}" { capabilities = ["read"] } ''; }; })) ++ (flip mapAttrsToList cfg ( hostname: value: (optionalAttrs (value.paths.replicationToken != null) { "consul_acl_policy"."${hostname}_replication" = { name = "${hostname}_consul_replication"; datacenters = value.replicationDatacenters; rules = '' acl = "write" operator = "write" service_prefix "" { policy = "read" intentions = "read" } ''; }; "consul_acl_token"."${hostname}_consul_replication" = { description = "Consul replication token on ${hostname}"; policies = [ (tf "consul_acl_policy.${hostname}_replication.name") ]; local = false; }; "vault_kv_secret_v2"."${hostname}_consul_replication" = { mount = value.vaultKvMount; name = value.paths.replicationToken; delete_all_versions = true; data_json = builtins.toJSON { secret = tf "data.consul_acl_token_secret_id.${hostname}_consul_replication.secret_id"; accessor = tf "consul_acl_token.${hostname}_consul_replication.id"; }; }; }) ))); config.data = mkMerge (flip mapAttrsToList cfg ( hostname: value: { "consul_acl_token_secret_id"."${hostname}_consul_agent" = { accessor_id = tf "consul_acl_token.${hostname}_consul_agent.id"; }; } ) ++ flip mapAttrsToList cfg ( hostname: value: (optionalAttrs (value.paths.replicationToken != null) { "consul_acl_token_secret_id"."${hostname}_consul_replication" = { accessor_id = tf "consul_acl_token.${hostname}_consul_replication.id"; }; }) )); }