From 998d6d5348dfc2e7dce4a19a6297470ccfe6b2c8 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 13 Jun 2023 02:58:14 +0200 Subject: [PATCH] refactor: move all proxy related configuration to the nodes that define them --- flake.lock | 6 +- hosts/common/core/default.nix | 1 + hosts/sentinel/caddy.nix | 122 ------------------ hosts/sentinel/default.nix | 1 - hosts/sentinel/proxied-domains.nix | 25 ---- .../secrets/loki-basic-auth-hashes.age | 10 -- hosts/ward/microvms/grafana/default.nix | 37 ++++-- hosts/ward/microvms/kanidm/default.nix | 26 +++- hosts/ward/microvms/loki/default.nix | 51 +++++++- .../loki/secrets/loki-basic-auth-hashes.age | 10 ++ modules/distributed-config.nix | 2 +- modules/proxied-domains.nix | 7 + 12 files changed, 122 insertions(+), 176 deletions(-) delete mode 100644 hosts/sentinel/proxied-domains.nix delete mode 100644 hosts/sentinel/secrets/loki-basic-auth-hashes.age create mode 100644 hosts/ward/microvms/loki/secrets/loki-basic-auth-hashes.age create mode 100644 modules/proxied-domains.nix diff --git a/flake.lock b/flake.lock index 2937013..f8fcf49 100644 --- a/flake.lock +++ b/flake.lock @@ -31,11 +31,11 @@ ] }, "locked": { - "lastModified": 1686610839, - "narHash": "sha256-rK3m7hth4Nc7Xmi83Mf4j53s1Ym9mJr312g7ct4i5Ck=", + "lastModified": 1686617801, + "narHash": "sha256-fXNOCYjuFL4427jRW9C5xdc7KSJKhoFxXbBrxE3kibU=", "owner": "oddlama", "repo": "agenix-rekey", - "rev": "cd77cb3bd43ece5b5fb1517d4b32338ac3cc5798", + "rev": "787efa41f1611403320517bbd41cd7cb7ebdf93d", "type": "github" }, "original": { diff --git a/hosts/common/core/default.nix b/hosts/common/core/default.nix index 69c8708..9ae08ce 100644 --- a/hosts/common/core/default.nix +++ b/hosts/common/core/default.nix @@ -17,6 +17,7 @@ ../../../modules/interface-naming.nix ../../../modules/microvms.nix ../../../modules/promtail.nix + ../../../modules/proxied-domains.nix ../../../modules/repo.nix ../../../modules/wireguard.nix ]; diff --git a/hosts/sentinel/caddy.nix b/hosts/sentinel/caddy.nix index 099aba7..1b6fc96 100644 --- a/hosts/sentinel/caddy.nix +++ b/hosts/sentinel/caddy.nix @@ -14,34 +14,6 @@ # TODO message = "non-deterministic uid detected for: ${name}"; # TODO }); - age.secrets.loki-basic-auth-hashes = { - rekeyFile = ./secrets/loki-basic-auth-hashes.age; - generator = { - # Dependencies are added by the nodes that define passwords using - # distributed-config. - script = { - pkgs, - lib, - decrypt, - deps, - ... - }: - lib.flip lib.concatMapStrings deps ({ - name, - host, - file, - }: '' - echo " -> Aggregating "${lib.escapeShellArg host}":"${lib.escapeShellArg name}"" >&2 - echo -n ${lib.escapeShellArg host}" " - ${decrypt} ${lib.escapeShellArg file} \ - | ${pkgs.caddy}/bin/caddy hash-password --algorithm bcrypt \ - || die "Failure while aggregating caddy basic auth hashes" - ''); - }; - mode = "440"; - group = "caddy"; - }; - services.caddy = { enable = true; package = pkgs.caddy.withPackages { @@ -53,99 +25,5 @@ ]; vendorHash = "sha256-RqSXQihtY5+ACaMo7bLdhu1A+qcraexb1W/Ia+aUF1k"; }; - - # globalConfig = '' - # # servers { - # # metrics - # # } - - # order authenticate before respond - # order authorize before basicauth - - # security { - # oauth identity provider generic { - # realm generic - # driver generic - # client_id {env.GENERIC_CLIENT_ID} - # client_secret {env.GENERIC_CLIENT_SECRET} - # scopes openid email profile - # base_auth_url https://${authDomain}/ui/oauth2 - # metadata_url https://${authDomain}/oauth2/openid/{env.GENERIC_CLIENT_ID}/.well-known/openid-configuration - # } - - # authentication portal myportal { - # crypto default token lifetime 3600 - # crypto key sign-verify {env.JWT_SHARED_KEY} - # enable identity provider generic - # cookie domain myfiosgateway.com - # ui { - # links { - # "My Identity" "/whoami" icon "las la-user" - # } - # } - - # transform user { - # match realm generic - # action add role authp/user - # ui link "File Server" https://assetq.myfiosgateway.com:8443/ icon "las la-star" - # } - - # transform user { - # match realm generic - # match email greenpau@contoso.com - # action add role authp/admin - # } - # } - - # authorization policy mypolicy { - # set auth url https://auth.myfiosgateway.com:8443/oauth2/generic - # crypto key verify {env.JWT_SHARED_KEY} - # allow roles authp/admin authp/user - # validate bearer header - # inject headers with claims - # } - # } - # ''; - - # TODO move subconfigs to the relevant hosts instead. - # -> have something like merged config nodes..... - # -> needs to be in a way that doesn't trigger infinite recursion - - virtualHosts.${config.proxyDomains.kanidm} = { - useACMEHost = config.lib.extra.matchingWildcardCert config.proxyDomains.kanidm; - extraConfig = '' - encode zstd gzip - reverse_proxy { - to https://${nodes.ward-kanidm.config.extra.wireguard.proxy-sentinel.ipv4}:${lib.last (lib.splitString ":" nodes.ward-kanidm.config.services.kanidm.serverSettings.bindaddress)} - transport http { - tls_insecure_skip_verify - } - } - ''; - }; - - virtualHosts.${config.proxyDomains.grafana} = { - useACMEHost = config.lib.extra.matchingWildcardCert config.proxyDomains.grafana; - extraConfig = '' - encode zstd gzip - reverse_proxy { - to http://${nodes.ward-grafana.config.extra.wireguard.proxy-sentinel.ipv4}:${toString nodes.ward-grafana.config.services.grafana.settings.server.http_port} - } - ''; - }; - - virtualHosts.${config.proxyDomains.loki} = { - useACMEHost = config.lib.extra.matchingWildcardCert config.proxyDomains.loki; - extraConfig = '' - encode zstd gzip - skip_log - basicauth { - import ${config.age.secrets.loki-basic-auth-hashes.path} - } - reverse_proxy { - to http://${nodes.ward-loki.config.extra.wireguard.proxy-sentinel.ipv4}:${toString nodes.ward-loki.config.services.loki.configuration.server.http_listen_port} - } - ''; - }; }; } diff --git a/hosts/sentinel/default.nix b/hosts/sentinel/default.nix index 3f83fe2..ca21c68 100644 --- a/hosts/sentinel/default.nix +++ b/hosts/sentinel/default.nix @@ -12,7 +12,6 @@ ./fs.nix ./net.nix - ./proxied-domains.nix ./acme.nix ./caddy.nix diff --git a/hosts/sentinel/proxied-domains.nix b/hosts/sentinel/proxied-domains.nix deleted file mode 100644 index 39897ec..0000000 --- a/hosts/sentinel/proxied-domains.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit - (lib) - mkOption - types - ; - - inherit (config.repo.secrets.local) personalDomain; -in { - options.proxiedDomains = mkOption { - type = types.attrsOf types.str; - default = {}; - description = "Registry of relevant proxied domains"; - }; - - config.proxiedDomains = { - grafana = "grafana.${personalDomain}"; - kanidm = "auth.${personalDomain}"; - loki = "loki.${personalDomain}"; - }; -} diff --git a/hosts/sentinel/secrets/loki-basic-auth-hashes.age b/hosts/sentinel/secrets/loki-basic-auth-hashes.age deleted file mode 100644 index 137ef15..0000000 --- a/hosts/sentinel/secrets/loki-basic-auth-hashes.age +++ /dev/null @@ -1,10 +0,0 @@ -age-encryption.org/v1 --> X25519 vqJImcuJU5nQkpNVBkRvU5gEjhiIT6GJIlKIa7Yv1T4 -e30hk35HKlgSfI++1rC/CSJBjD0NInyUWv5suU2aDxU --> piv-p256 xqSe8Q Agg6on210aOduBZKkxcooDEb5INXxTn0py0lufQz3ymG -TT2/sfJlvVIPaCNoqHVpAkYcrpQJ2K0OTclpuNCd2Gw --> _cB-grease - ---- 31UQg77E61iYmWHRniBdikMqVz7L8C6WYpWKrNvVi2k -U M@!{ݍXQz!y 6X\]Ui4ByXu\^B.h%`M+ -qd$c-R;ȆV #[{rqqVql6Ef(RX2iKgWp 95D}z \ No newline at end of file diff --git a/hosts/ward/microvms/grafana/default.nix b/hosts/ward/microvms/grafana/default.nix index a9c9718..630e577 100644 --- a/hosts/ward/microvms/grafana/default.nix +++ b/hosts/ward/microvms/grafana/default.nix @@ -5,7 +5,10 @@ nodes, utils, ... -}: { +}: let + sentinelCfg = nodes.sentinel.config; + grafanaDomain = "grafana.${sentinelCfg.repo.secrets.local.personalDomain}"; +in { imports = [ ../../../../modules/proxy-via-sentinel.nix ]; @@ -27,9 +30,23 @@ group = "grafana"; }; - nodes.sentinel.age.secrets.loki-basic-auth-hashes.generator.dependencies = [ - config.age.secrets.grafana-loki-basic-auth-password - ]; + nodes.sentinel = { + age.secrets.loki-basic-auth-hashes.generator.dependencies = [ + config.age.secrets.grafana-loki-basic-auth-password + ]; + + proxiedDomains.grafana = grafanaDomain; + + services.caddy.virtualHosts.${grafanaDomain} = { + useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert grafanaDomain; + extraConfig = '' + encode zstd gzip + reverse_proxy { + to http://${config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port} + } + ''; + }; + }; services.grafana = { enable = true; @@ -38,8 +55,8 @@ users.allow_sign_up = false; server = { - domain = nodes.sentinel.config.proxiedDomains.grafana; - root_url = "https://${nodes.sentinel.config.proxiedDomains.grafana}"; + domain = grafanaDomain; + root_url = "https://${grafanaDomain}"; enforce_domain = true; enable_gzip = true; http_addr = config.extra.wireguard.proxy-sentinel.ipv4; @@ -66,9 +83,9 @@ client_secret = "r6Yk5PPSXFfYDPpK6TRCzXK8y1rTrfcb8F7wvNC5rZpyHTMF"; # TODO temporary test not a real secret scopes = "openid email profile"; login_attribute_path = "prefered_username"; - auth_url = "https://${nodes.sentinel.config.proxiedDomains.kanidm}/ui/oauth2"; - token_url = "https://${nodes.sentinel.config.proxiedDomains.kanidm}/oauth2/token"; - api_url = "https://${nodes.sentinel.config.proxiedDomains.kanidm}/oauth2/openid/grafana/userinfo"; + auth_url = "https://${sentinelCfg.proxiedDomains.kanidm}/ui/oauth2"; + token_url = "https://${sentinelCfg.proxiedDomains.kanidm}/oauth2/token"; + api_url = "https://${sentinelCfg.proxiedDomains.kanidm}/oauth2/openid/grafana/userinfo"; use_pkce = true; # Allow mapping oauth2 roles to server admin allow_assign_grafana_admin = true; @@ -89,7 +106,7 @@ name = "Loki"; type = "loki"; access = "proxy"; - url = "https://${nodes.sentinel.config.proxiedDomains.loki}"; + url = "https://${sentinelCfg.proxiedDomains.loki}"; orgId = 1; basicAuth = true; basicAuthUser = nodeName; diff --git a/hosts/ward/microvms/kanidm/default.nix b/hosts/ward/microvms/kanidm/default.nix index 46c3646..5bfa3d8 100644 --- a/hosts/ward/microvms/kanidm/default.nix +++ b/hosts/ward/microvms/kanidm/default.nix @@ -5,7 +5,10 @@ pkgs, utils, ... -}: { +}: let + sentinelCfg = nodes.sentinel.config; + kanidmDomain = "auth.${sentinelCfg.repo.secrets.local.personalDomain}"; +in { imports = [ ../../../../modules/proxy-via-sentinel.nix ]; @@ -26,12 +29,29 @@ group = "kanidm"; }; + nodes.sentinel = { + proxiedDomains.kanidm = kanidmDomain; + + services.caddy.virtualHosts.${kanidmDomain} = { + useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert kanidmDomain; + extraConfig = '' + encode zstd gzip + reverse_proxy { + to https://${config.services.kanidm.serverSettings.bindaddress} + transport http { + tls_insecure_skip_verify + } + } + ''; + }; + }; + services.kanidm = { enableServer = true; # enablePAM = true; serverSettings = { - domain = nodes.sentinel.config.proxiedDomains.kanidm; - origin = "https://${nodes.sentinel.config.proxiedDomains.kanidm}"; + domain = kanidmDomain; + origin = "https://${kanidmDomain}"; tls_chain = config.age.secrets."kanidm-self-signed.crt".path; tls_key = config.age.secrets."kanidm-self-signed.key".path; bindaddress = "${config.extra.wireguard.proxy-sentinel.ipv4}:8300"; diff --git a/hosts/ward/microvms/loki/default.nix b/hosts/ward/microvms/loki/default.nix index 687683f..a25d9bd 100644 --- a/hosts/ward/microvms/loki/default.nix +++ b/hosts/ward/microvms/loki/default.nix @@ -4,7 +4,10 @@ nodes, utils, ... -}: { +}: let + sentinelCfg = nodes.sentinel.config; + lokiDomain = "loki.${sentinelCfg.repo.secrets.local.personalDomain}"; +in { imports = [ ../../../../modules/proxy-via-sentinel.nix ]; @@ -13,6 +16,52 @@ sentinel-to-local.allowedTCPPorts = [3100]; }; + nodes.sentinel = { + proxiedDomains.loki = lokiDomain; + + age.secrets.loki-basic-auth-hashes = { + rekeyFile = ./secrets/loki-basic-auth-hashes.age; + generator = { + # Dependencies are added by the nodes that define passwords using + # distributed-config. + script = { + pkgs, + lib, + decrypt, + deps, + ... + }: + lib.flip lib.concatMapStrings deps ({ + name, + host, + file, + }: '' + echo " -> Aggregating "${lib.escapeShellArg host}":"${lib.escapeShellArg name}"" >&2 + echo -n ${lib.escapeShellArg host}" " + ${decrypt} ${lib.escapeShellArg file} \ + | ${pkgs.caddy}/bin/caddy hash-password --algorithm bcrypt \ + || die "Failure while aggregating caddy basic auth hashes" + ''); + }; + mode = "440"; + group = "caddy"; + }; + + services.caddy.virtualHosts.${lokiDomain} = { + useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert lokiDomain; + extraConfig = '' + encode zstd gzip + skip_log + basicauth { + import ${sentinelCfg.age.secrets.loki-basic-auth-hashes.path} + } + reverse_proxy { + to http://${config.services.loki.configuration.server.http_listen_address}:${toString config.services.loki.configuration.server.http_listen_port} + } + ''; + }; + }; + services.loki = let lokiDir = "/var/lib/loki"; in { diff --git a/hosts/ward/microvms/loki/secrets/loki-basic-auth-hashes.age b/hosts/ward/microvms/loki/secrets/loki-basic-auth-hashes.age new file mode 100644 index 0000000..24fd848 --- /dev/null +++ b/hosts/ward/microvms/loki/secrets/loki-basic-auth-hashes.age @@ -0,0 +1,10 @@ +age-encryption.org/v1 +-> X25519 oTqcGYrzcjVyYkWQndidK7lfyMfQUFaLukLu9ru7ygc +0viOW4o/PQEhZfZFOx4UxbRBCGUXCYcvDv6r8hi6aiQ +-> piv-p256 xqSe8Q Akl/Ab1PwdLsyhJv3KzPxdALttqJdNk1wNj+pNnrFs9v +FbVps0hL4XpaPxrIBFmBi+a4YKIjTYsqBjN9JwzpkP8 +-> ^/?z7Md-grease QDfMgTO +b+w4gj1Yxs6ocBCJN6AgLDad1/+EZ+HZ0zvMvGJaztxeIhNLSsiqoBn2GpwX6IcY +YWpLnO3Fw1xaU9Jqn9HJIqyYGFX1O5dBlvgu1rqgxytwiEEcDZaXOA1ZIupE +--- 0jXcY3KP8+JMsQ6+uhLE2bS1vGau/hr2b5ZD2SIUkbE +>@2([s&dK1}i_ ~͞QyWP:qQ}"]+P:qg|3k&6`hG \ No newline at end of file diff --git a/modules/distributed-config.nix b/modules/distributed-config.nix index 445da62..b0e50a6 100644 --- a/modules/distributed-config.nix +++ b/modules/distributed-config.nix @@ -37,7 +37,7 @@ in { isColmenaNode = elem nodeName (attrNames colmenaNodes); otherNodes = filter (n: n != nodeName) (attrNames colmenaNodes); foreignConfigs = concatMap (n: colmenaNodes.${n}.config.nodes.${nodeName} or []) otherNodes; - toplevelAttrs = ["age" "networking" "systemd" "services"]; + toplevelAttrs = ["age" "proxiedDomains" "networking" "systemd" "services"]; in optionalAttrs isColmenaNode (mergeToplevelConfigs toplevelAttrs ( foreignConfigs diff --git a/modules/proxied-domains.nix b/modules/proxied-domains.nix new file mode 100644 index 0000000..64fa656 --- /dev/null +++ b/modules/proxied-domains.nix @@ -0,0 +1,7 @@ +{lib, ...}: { + options.proxiedDomains = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = {}; + description = "Registry of proxied domains for easy cross-node referencing."; + }; +}