depot/ops/vault/cfg/servers.nix

142 lines
4.1 KiB
Nix

{ depot, lib, config, ... }:
let
inherit (lib) mkOption nameValuePair mapToAttrs types mkEnableOption mapAttrs' filterAttrs mkMerge mapAttrsToList concatStringsSep mkBefore;
minutes = m: m * 60;
serversType = types.attrsOf (types.submodule ({ name, ... }: {
options = {
enable = mkOption {
type = types.bool;
default = true;
};
resourceName = mkOption {
type = types.str;
default = "server_${name}";
internal = true;
};
extraPolicies = mkOption {
type = with types; listOf str;
default = [];
};
apps = mkOption {
type = with types; listOf str;
default = [];
};
appPolicies = mkOption {
# Server-specific app policies.
type = with types; attrsOf lines;
default = {};
};
userPolicies = mkOption {
# Server-specific user policies.
type = with types; attrsOf lines;
default = {};
};
hostnames = mkOption {
type = with types; listOf str;
default = [
"${name}.as205479.net"
"${name}.blade.as205479.net"
"${name}.int.as205479.net"
];
};
policy = mkOption {
type = types.lines;
default = ''
path "ssh-host/sign/${name}" {
capabilities = ["update"]
allowed_parameters = {
"cert_type" = ["host"]
"public_key" = []
"valid_principals" = []
}
}
'';
};
};
config.apps = mkBefore [ "deployer" ];
}));
cfg = config.my.enabledServers;
in {
options = {
my.servers = mkOption {
type = serversType;
};
my.enabledServers = mkOption {
internal = true;
readOnly = true;
default = filterAttrs (n: v: v.enable) config.my.servers;
type = serversType;
};
};
config.my.servers = mapToAttrs (name: nameValuePair name {}) (builtins.attrNames depot.ops.nixos.systemConfigs);
config.resource = mkMerge (mapAttrsToList (serverName: serverCfg: mkMerge ([{
vault_policy.${serverCfg.resourceName} = {
name = "server/${serverName}";
inherit (serverCfg) policy;
};
vault_approle_auth_backend_role.${serverCfg.resourceName} = {
backend = "\${vault_auth_backend.approle.path}";
role_name = serverName;
role_id = serverName;
secret_id_num_uses = 0;
token_ttl = minutes 20;
token_max_ttl = minutes 30;
token_policies =
["default" "server" "server-user" "\${vault_policy.${serverCfg.resourceName}.name}"]
++ serverCfg.extraPolicies
++ (map (name: "\${vault_policy.app_${name}.name}") serverCfg.apps)
++ (map (name: "\${vault_policy.server_${serverCfg.resourceName}_app_${name}.name}") (builtins.attrNames serverCfg.appPolicies))
++ (map (name: "\${vault_policy.server_${serverCfg.resourceName}_user_${name}.name}") (builtins.attrNames serverCfg.userPolicies));
};
vault_identity_entity.${serverCfg.resourceName} = {
name = serverName;
metadata.server = serverName;
};
vault_identity_entity_alias.${serverCfg.resourceName} = {
name = serverName;
mount_accessor = "\${vault_auth_backend.approle.accessor}";
canonical_id = "\${vault_identity_entity.${serverCfg.resourceName}.id}";
};
vault_ssh_secret_backend_role.${serverCfg.resourceName} = {
name = serverName;
backend = "\${vault_mount.ssh-host.path}";
key_type = "ca";
allow_host_certificates = true;
allow_bare_domains = true;
allowed_domains = concatStringsSep "," serverCfg.hostnames;
ttl = 7 * 24 * 60 * 60;
max_ttl = 7 * 24 * 60 * 60;
};
}]
++ mapAttrsToList (appName: policy: {
vault_policy.${"server_${serverCfg.resourceName}_app_${appName}"} = {
name = "server/${serverName}/app/${appName}";
inherit policy;
};
}) serverCfg.appPolicies
++ mapAttrsToList (userName: policy: {
vault_policy.${"server_${serverCfg.resourceName}_user_${userName}"} = {
name = "server/${serverName}/user/${userName}";
inherit policy;
};
}) serverCfg.userPolicies)) cfg);
}