ops/vault/cfg: add acme-ca

This commit is contained in:
Luke Granger-Brown 2022-03-16 00:18:47 +00:00
parent fb7e18260a
commit 148e071c21
3 changed files with 139 additions and 0 deletions

48
ops/vault/cfg/acme-ca.nix Normal file
View file

@ -0,0 +1,48 @@
{ ... }:
{
imports = [ ./module-acme-ca.nix ];
my.acme.accounts = let
base = {
key_type = "EC256";
ignore_dns_propagation = true;
};
letsencrypt = base // {
contact = "letsencrypt@lukegb.com";
terms_of_service_agreed = true;
};
letsencrypt-staging = letsencrypt // {
server_url = "https://acme-staging-v02.api.letsencrypt.org/directory";
};
letsencrypt-prod = letsencrypt // {
server_url = "https://acme-v02.api.letsencrypt.org/directory";
};
cloudflare = t: t // {
provider = "cloudflare";
provider_configuration.CLOUDFLARE_DNS_API_TOKEN = "\${data.vault_generic_secret.misc.data[\"cloudflareToken\"]}";
};
gcloud-as205479 = t: t // {
provider = "gcloud";
provider_configuration.GCE_PROJECT = "as205479-177317";
};
in {
letsencrypt-cloudflare = cloudflare letsencrypt-prod;
letsencrypt-staging-cloudflare = cloudflare letsencrypt-staging;
letsencrypt-gcloud-as205479 = gcloud-as205479 letsencrypt-prod;
letsencrypt-staging-gcloud-as205479 = gcloud-as205479 letsencrypt-staging;
};
my.acme.roles = let
cloudflareDomains = [ "lukegb.com" "bfob.gg" "lukegb.dev" "lukegb.tech" "lukegb.xyz" "zxcvbnm.ninja" ];
gcloudDomains = [ "as205479.net" "event.lukegb.tech" "tech.lukegb.tech" ];
in {
letsencrypt-cloudflare.allowed_domains = cloudflareDomains;
letsencrypt-staging-cloudflare.allowed_domains = cloudflareDomains;
letsencrypt-gcloud-as205479.allowed_domains = gcloudDomains;
letsencrypt-staging-gcloud-as205479.allowed_domains = gcloudDomains;
};
}

View file

@ -12,6 +12,8 @@
./ssh-ca-server.nix
./servers.nix
./acme-ca.nix
];
terraform = {

View file

@ -0,0 +1,89 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mapAttrs' nameValuePair mkMerge mkOption mkIf any types;
hackterpolate = s: let
parts = builtins.split "(\\\$\\{[^}]+})" s;
unescape = s: builtins.fromJSON ''"${s}"'';
strParts = lib.imap1 (i: v: if lib.mod i 2 == 0 then unescape (builtins.elemAt v 0) else v) parts;
in lib.concatStrings strParts;
cfg = config.my.acme;
accountsEndpoints = mapAttrs' (name: value: nameValuePair "acme_account_${name}" {
depends_on = [ "vault_mount.acme" ];
path = "acme/accounts/${name}";
disable_read = true;
data_json = hackterpolate (builtins.toJSON value);
}) cfg.accounts;
rolesEndpoints = mapAttrs' (name: value: nameValuePair "acme_role_${name}" {
depends_on = [ "vault_mount.acme" ];
path = "acme/roles/${name}";
disable_read = true;
data_json = hackterpolate (builtins.toJSON value);
}) cfg.roles;
mkMergeIf = things: mkIf (any (t: t != { }) things) (mkMerge things);
in {
options = {
my.acme.mountPoint = mkOption {
default = "acme";
type = types.str;
};
my.acme.accounts = mkOption {
default = {};
type = (pkgs.formats.json { }).type;
};
my.acme.roles = mkOption {
default = {};
type = types.attrsOf (types.submodule ({ name, ... }: {
options = {
account = mkOption {
type = types.str;
default = name;
};
allow_bare_domains = mkOption {
type = types.bool;
default = true;
};
allow_subdomains = mkOption {
type = types.bool;
default = true;
};
allowed_domains = mkOption {
type = with types; listOf str;
};
cache_for_ratio = mkOption {
type = types.int;
default = 20;
};
disable_cache = mkOption {
type = types.bool;
default = false;
};
};
}));
};
};
config = {
resource.vault_mount.acme = {
path = config.my.acme.mountPoint;
type = "acme";
};
resource.vault_generic_endpoint = mkMergeIf [
accountsEndpoints
rolesEndpoints
];
};
}