From 2eef6e55089978deb9028b5d3a669da5565d4606 Mon Sep 17 00:00:00 2001 From: arcnmx Date: Mon, 18 Mar 2024 19:10:43 -0700 Subject: [PATCH] chore(keycloak): cloudflared and vouch --- modules/nixos/vouch.nix | 5 + nixos/keycloak.nix | 31 ++++-- nixos/secrets/vouch.yaml | 116 +++++++++++++------- systems/hakurei/nixos.nix | 37 +------ systems/keycloak/lxc.json | 19 ++++ systems/keycloak/nixos.nix | 27 ++++- systems/keycloak/secrets.yaml | 6 +- systems/tei/cloudflared.nix | 23 ---- systems/tei/lxc.json | 1 - systems/tei/nixos.nix | 8 +- tf/cloudflare_idp_records.tf | 192 +++++++++++++++++----------------- tf/cloudflare_records.tf | 12 +-- tf/cloudflare_tunnels.tf | 31 +++++- tf/proxmox_vms.tf | 18 +++- tf/terraform.tfvars.sops | 6 +- 15 files changed, 303 insertions(+), 229 deletions(-) create mode 100644 systems/keycloak/lxc.json diff --git a/modules/nixos/vouch.nix b/modules/nixos/vouch.nix index b204133c..8f269ba4 100644 --- a/modules/nixos/vouch.nix +++ b/modules/nixos/vouch.nix @@ -138,6 +138,11 @@ in { }; } (mkIf cfg.enable { + networking.firewall.interfaces.local = { + allowedTCPPorts = mkIf (cfg.settings.vouch.listen != "127.0.0.1") [ + cfg.settings.vouch.port + ]; + }; systemd.services.vouch-proxy = { description = "Vouch-proxy"; after = ["network.target"]; diff --git a/nixos/keycloak.nix b/nixos/keycloak.nix index 013c3f8f..17ba5e23 100644 --- a/nixos/keycloak.nix +++ b/nixos/keycloak.nix @@ -1,5 +1,12 @@ {config, lib, ...}: let - inherit (lib.modules) mkForce; + inherit (lib.modules) mkIf mkForce mkDefault; + inherit (config.lib.access) mkSnakeOil; + cfg = config.services.keycloak; + cert = mkSnakeOil { + name = "keycloak-selfsigned"; + domain = hostname; + }; + hostname = "sso.${config.networking.domain}"; in { sops.secrets = let commonSecret = { @@ -9,13 +16,18 @@ in { in { keycloak_db_password = commonSecret; }; - users.users.keycloak = { - isSystemUser = true; - group = "keycloak"; + users = mkIf cfg.enable { + users.keycloak = { + isSystemUser = true; + group = "keycloak"; + }; + groups.keycloak = { + }; }; - networking.firewall.interfaces.local.allowedTCPPorts = [ 80 ]; - users.groups.keycloak = {}; + networking.firewall.interfaces.local.allowedTCPPorts = mkIf cfg.enable [ + (if cfg.sslCertificate != null then 443 else 80) + ]; systemd.services.keycloak.serviceConfig.DynamicUser = mkForce false; services.keycloak = { @@ -29,8 +41,11 @@ in { }; settings = { - hostname = "sso.${config.networking.domain}"; - proxy = "edge"; + hostname = mkDefault hostname; + proxy = mkDefault (if cfg.sslCertificate != null then "reencrypt" else "edge"); }; + + sslCertificate = mkDefault "${cert}/fullchain.pem"; + sslCertificateKey = mkDefault "${cert}/key.pem"; }; } diff --git a/nixos/secrets/vouch.yaml b/nixos/secrets/vouch.yaml index 49c70a7e..28f3f58c 100644 --- a/nixos/secrets/vouch.yaml +++ b/nixos/secrets/vouch.yaml @@ -10,66 +10,102 @@ sops: - recipient: age12ze362pu5mza6ef9akrptr7hfe4auaqul4rkta7kyy2tnrstqensgmujeq enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkRlA5L2JnSkpNVzZEOVNS - L3FLTlczZlhrZUxtbEpJcHVJdjFtYmJLeEdVCnA3WG5XSHpGaVlPT08ya3dCVnpa - aXorSHVndUUxRDFDdEttWURuNllxMWcKLS0tIFEycEtvK3REb1dyZDZxcHJheXU1 - U1pYY2ZTaDdheUZSc0V3bWNsNzNtMGcKi6F+m36wc4Sgn5lfa2GC6LQdGUqCPJ7g - jZVo/iNLE2gg2lIBFkFY1xBZJB0uPSeNnqWWc0eXm6kZL5u9WOvTXA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXd1paVkdKa2NyL2NQVnc2 + MXlvRTVYT1NIelZxc2g4WHE4bkoyeWVRK2hrClJCdk1Gck9RNGFHSEdCMkhXZXpq + Z3Blcjl5MGRVVWUxRVdLVzNPeUhYVGMKLS0tIDcyQ0llbXhXVFMwMC9WOWlxYk51 + N3ZqbGtGMUp5UjhicUFCVmJtS0xyZ0EKp7ygEx0BkhNF55wkII4MUSnMILb7TR5m + 2bzew7r7T000xEYLku8vf5nZCq6Bs3ei+BoD5/UZqpoaZGfaSjfPXQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age176uyyyk7veqnzmm8xzwfhf0u23m6hm02cldlfkldunqe6std0gcq6lg057 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxNkJWOW1rTldZZkg0TDhL + bzVrTnZFNVdrZXRMUk1MaUNNYlArMnJOc2hVCmJQai93eHE2UGp4c0M5d1RkTWlN + WmR4NG1VUFdTSWdmTnk3aWV5U1c2TlkKLS0tIEIweHNVOFdnU0JkcVBGMVJsTU0w + Y2EvUGU2N1FEUE53SXhFZ2lXL01zVEUKmKCWlLj09SZejQ6vRXug3BtsihbosSKS + Wdd8UTa+ejgSLwW21J1vaBKzfI/g+Icep9X/dZtXRnSufiyh6wbE2A== + -----END AGE ENCRYPTED FILE----- + - recipient: age10t6kc5069cyky929vvxk8aznqyxpkx3k5h5rmlyz83xtjmr22ahqe8mzes + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvSXNISCs5dDcxZnNLU0JB + Tjg4aWttalFYVElqSDIvbHFtcWhpWXlkSXlBClJmMVJQTVBQaldlV0NRTmZHNXFU + cWN6WjF1K0E1anJ2dXIvUUsySDBNSG8KLS0tIFFmM1ZiT0hxOC9qeHJ1TTBGVUlY + NlRnRk5IeGphWVg2L0lYckgvbGlQL3cKhzIjobf4AIXX9uYphJopPkbabElcLXxB + 7u1lawclcOExBJ2TMxwBAaF/TpiBE5nF9yfF37+BMWW2czVw6bwZLA== -----END AGE ENCRYPTED FILE----- - recipient: age1a2quf2ekkj94ygu7wgvhrvh44fwn32c0l2cwvgvjh23wst90s54szdsvgr enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxVU0zclMvSXdsYTRoUm9n - NTFhN05QOVgrM3B1UHR6ME1wUWF2cWRqUFdvCi8xY2JLK1lYUklRbngxWXBXcUF2 - RUE3eVJxdklKeXQvSDdDNDVNakRsTWcKLS0tIDJFUGFRU2pYeUdYVlVydm9QRzJp - TFNvOERxTkUyQnhJZVZqR1pKa3I0TE0Kh4OqiSCyZm5cMyVjHabP6I0FN2hhME0l - k2k0ssHtExdtewGvnuWIv+uYQMj86VGlCW3FDVTFRtWTFQ7n5eom/w== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTMzNkZTJaSFNuQ3hyYWVY + c3AxWEZLNk4yQjhrdDZocTVqSlhnbUdmWDBzCkJtNzQxNDFjUG1qb0NLblprNlJZ + MWdHODFMeU54TUl0V3lOVVo4cjhySlUKLS0tIHJMT21JajZOSCtHOGFpVTM1MXEv + RFlIcnd2ZEE2aGs4eWZCU2pCV0poZ1EKweqd24UCyUwnfeltrL+ZJJS91Ufnmqjs + FPdOo2FDhdSHH+iv5B6ekd0JIpEV1sRwoxbLOzfXbx8xqWyyiQzAfw== -----END AGE ENCRYPTED FILE----- - recipient: age16klpkaut5759dut8mdm3jn0rnp8w6kxyvs9n6ntqrdsayjtd7upqlvw489 enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4cmRRa3RlSG9UWnRqakgw - K2twVHhwRENIbDhPblp1R1lxV1BqTk1pSG5jCkpqT2Z1VXVWc3Z4YlFZRWJybWV4 - MTh6Tmw5dHFGQkZ3aHZVa3Y0UFlZTWsKLS0tIDloRmFGbjNhUHBYRjg5OTZ3QWZJ - V2xpcDFjcVY0MTBPcFU1ZnNiSDlac0EKQGBx++pF7S8L/wC29sE+J/JZYTgZykZJ - iRW6PMAxGci7WZx0GRqmDq2VL5GekHhmjlUDp9fSNAc3LIl3r9i8og== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCRWJ0c3VyNUYxK0M1b01K + QnRYa1BhUmNTNVllakZTSlRlYUpvVnVjUWswCnJhaExMM3kySE9XS2pJYndCbjA3 + cUJPZDA0TDVweCtRaVhVVmNBS0VIeGcKLS0tIDN5ME12WFBwL0FsdkJLMzNUM2lt + Wk5mYy85eW9IZFJXZzhhZGZYRndsV2MK8o7uJBtcm3WARDq6cIQxcN0lMFkijpEq + 0pGMN7cunnN3sa32GA6SP2lFa9ncn0AHkI8/c8h3q46o5VluJWH5+A== + -----END AGE ENCRYPTED FILE----- + - recipient: age13qgddr326g5je0fpq2r3k940vsr3fh9nlvl9xtcxk3xg2x0k3vsq7pvzaj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCU1J0NFpDanNjWmcvYWw5 + M25JcXRZdTN2ak5FTXNKNjJhaCtzcTIzaFJFCkVWWG9uSFNVckdFRzk0QUNydTZ5 + U2hCcDQ1U3IrWnZQaUxTU2ErM1Iza1kKLS0tIFZ2dzNHSXZhMk9xNzd1bnQ4Y3J2 + MmRFVStpUHZFQm5KVS9JT2UzandQUDAKzdRiWNaIDKhEczGLaRYONZXjCU9g9/V8 + NOUXtD/S0nGR1csgur//q+rVknEoSkrX76Xj/wkKyDImkKMaPSMGjA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ktmx2szedfnpe5xumnzs8vkk0ffqgga6ved3drtksg9pye6ndsnsnqq488 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzbWlaTWorL3NWOGJSbFh0 + YUZtMEQ2bkFtckZUemhmNXJQd3dGemxoT244Cm9GWFhMZ0NJbDE2WkQrU3VESldD + aHhvaGNCKzNzNllZZFlRWEpFWkpPU1EKLS0tIG5TdVRxSzBzcnpOUU9talRnT3U5 + RkQvakRmdjB3ME1rbnNTWjVDQU5QSmcKi1KhB8zpSLlaCgSelaEYdtOGHFLlc+Z3 + hagYdJqojaOYbTGVBkWAYK0Zfh++1/QbDYJH6ySjDC8mFFCqEdSuYQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2024-01-16T19:11:11Z" mac: ENC[AES256_GCM,data:1J3dCx5ptr2ah2LbvoP/rcUzPlzm3wZvpWLffIvh7PriNJ6vx2xj5fFK9s2AhIunxAaef0KJLzwzcfNwxEkJO3M6QSf0UUw3wopah1W3ZKLE2H/Z8bNncaNzSuh6QODbYShSG2yK4HmQApd8R9NfKlAHsDno+aRhuh7OYM7CaLI=,iv:KzMfJDJOqYm2epLM6Epd44aRoU7uJcusCl6m6/+cDtQ=,tag:tQ8MQ1NWey4E1dFu2YnOQw==,type:str] pgp: - - created_at: "2024-01-19T19:08:57Z" + - created_at: "2024-03-19T02:39:12Z" enc: |- -----BEGIN PGP MESSAGE----- - hQIMA82M54yws73UAQ//e7dXTAfUuvYIil1Z1xewbxo3Hu73cvlKMFyezV3Q/+Sg - NMDmw8sY1LDjrSdmiQIeJrl4If3ekU3ClR/3ZbjuZf/vuHx/Ys58P/wRc4PkKYgL - XUmU8PVRmbMsGwP/eDCdPetX8Er8ja2+O+4pM3JGDRhrNJIq4hZba8kghFCzZAHX - xaSf+rjUjuEr95VbiTLQf3ss978qCKwnCwYHET78sdOocAhuwrrRJ9ejCj7bb8RZ - +Z3ehpTRniHtogJkwu3E/tAP9eI01Q4fM492flbMJ28Xs1XljJnpVsjvrc5P5jEx - gP2p6O7Vduu5AXoBpjtNNxa2hlclTcfyqkTfeItsC5rrw2NQi+/8f9WP2nyne+6o - TSIu92WaP2Bz5bBu8i4gZUcnIX3YaF5rXIyN2PAD66qkyWhWVjKKCmgj4+xftPKR - 9/6BfpRDggrQx5kyMyJrT5jKTNctf5hU1Z+D+IpKnTeAxoJzAox1+hkumMXOkxLF - 5dTOQ2o3Ldkm5G58f3K/MqwFhh7wf1ilCWtJrCZ8UnppmH2iSlyBGhm1x62ac8YP - O0luHEDmjQ440VpJHszWEaC9j77J3weJORWaLOCAA7zsUvhggpuA7UXKlPZWkvzz - /+FYLs+u7CVKzlATenDMdhkZN+hYbb3bplPn/FKsfYG/DyTxh1z+nEcReEyPW2DS - XgER8BSgT7bQjXW3PCy165Y0iJjG+LIsNsfLwt4DTZipXE4yssZXiIG0trYiQtY5 - ssSL3WJ0FX0O2iVBtDnMqAt4rNHBtzMmkNn+B7p57N5cejMQWCJy4zAm3t/0e7M= - =c1Gq + hQIMA82M54yws73UAQ//U7Yp3mV1AOEy2Nu0e3dnaoUiDcvUfoiHL+HVrPKFaDPO + +cvNyNYWvlGSYCJRHWviVJ+bSFr3yaxm7O/MN98JjyQwzmeQvsYOlzWo/6/3GlMG + Cvhdad/AI3YQDIWbQw987zlP2Fs2lh3JXI0vKnTVXHcTE+GbqIO6NQOe4T+muG2H + FB9B+GU6yOxjdQKDs33tuai03VPZvSI3vAhDo2XRKjcfRjbvqGEXyrxYniq5L4hu + Ueb1qUZXKqiBCB7jxe7WKKwW/8h36yQ5mRtw9+CiH3xfYpUD65xmso2WB69UEBam + jUzIRK8ltk0N2qjyrqgiIvksmon78L+f3AJZjp4dfOiwvr6rIJWt32YngHhxlZRT + K6hIihxfgPQ0ykque5gDk1fdXmhcBe5HEnyeqEXGeXqXdzZvh2Kr8+1dVrZJ2iHs + NPQPPsnsAkWCe9VJyS0mcdv0IS1AEPvvEjvPHf8juYJRfv+jknllPagLjL1fa1Gz + e9p/VCguswwewp1LYtuhUF4atX36YKaL0c1NcnPYYAFKc8mmElCNaFK/V8YTOmWk + OvDDcxBNlFKv8GO/vrAi4wTc8bkE1k+RMK78fPcv+Q2Y39vERZ2CpA6QWGcSCkBx + MfordIRj3zEUz2ZVL8B3sbdcmTfUGvO9RZJdBb9JGUlsfxw7slSRxejQRHCsnZHS + XgHtjB9nynq50IYygoiXRxB00JSwuvkz2pwRlWRlzWfYAMHwUZDeoRcP5VhBRXTu + zEdcArNfsyKbqSymWkEaI01UBHoWzGO3mRwpwlzzzO328CT8e+d/Shlfr5rFgzs= + =C/Qz -----END PGP MESSAGE----- fp: CD8CE78CB0B3BDD4 - - created_at: "2024-01-19T19:08:57Z" + - created_at: "2024-03-19T02:39:12Z" enc: |- -----BEGIN PGP MESSAGE----- - hQEMA2W9MER3HLb7AQf/bNiEr/4QggEnmB7uRoLatYt9HqZiL3CaFuT9zzEndwZy - wAAiBj+Wvc+nCZfdBpntPvzeexFABJUhVbxC9x/DYLaThmXds1TrODL/7zC7l/Ta - aL/C8JFj0U2zolmQ17mL6AyITJFbEnoLuHwcqRA6GHLHUf4wWp8m9bIbw2qem32d - 40QSmt6+zYjMjvVCJ3+nXHz4hv4Djld6FYKAQvLqzDi5l5xDTHmPtT2R58ZOwzs5 - uuknL/B6WCSfBdKEJElcKY32yc2sy24qPlISfYlRgHK+YM3tHD9iNUlaQU1YZCrR - la4p70YfFxw8zsPMtmkbrnx+LuhCJJx/VQrbnG32DNJeAYm6LZSdqszbz73GyCRL - gtxd/Ka1AzGBnxVpqKMjghujomSf2AvaAhY+0xSr8ImY/CgSmfEprd+b+1naok4f - ARVCCSZEQW1j3MLE2W5An4z2hdIaB0YNp2RUGAL9Jg== - =EXaM + hQEMA2W9MER3HLb7AQf/c8LLLVhZ2Oax5gtFfnAbw3b9k7T/fNmxazzImzES5jIN + Bu8MIwyVGmPAqEsREMyiDMMsj0cWVOKQev5AxVX8UYWyw8PS8yR3/j5nZKhqWNnf + pQ6lgxRKElc+31kNbOZwnTc7dplRdq0LxQQCHYi+5bGeAY5YPlJRLYSh65AqjyA/ + 0iHDsGBfaJ/+ayzNQ8RGrEzCxkL62v5k8a88rPDt5MDy9M8zMOgXdip2InJ5SMCx + EbsD2a7eEltFct+cAiBpgeKUjGa7e0+jthA5TIPD5UQLaanu328n0K1I/mn79J19 + VY/g/MA3OGCyDd1Buhc2inz2Aa4K8miCh2E0I4La/9JeAWOI08o/PRn0mjLlINk8 + qtmTAJP+CEcsIkW8pphzk5w66YfAUPUWKDPHHlG581EknIhXg2M8ecUIMSUNGsCm + PrgY+5Mc07ttJmxO/uAmh+LTimWfdcCOFrozyebr4w== + =Hodp -----END PGP MESSAGE----- fp: 65BD3044771CB6FB unencrypted_suffix: _unencrypted diff --git a/systems/hakurei/nixos.nix b/systems/hakurei/nixos.nix index 6f6e9854..96eed1dd 100644 --- a/systems/hakurei/nixos.nix +++ b/systems/hakurei/nixos.nix @@ -10,7 +10,7 @@ mediabox = access.nixosFor "mediabox"; tei = access.nixosFor "tei"; inherit (mediabox.services) plex; - inherit (tei.services) kanidm vouch-proxy; + inherit (keycloak.services) vouch-proxy; inherit (config.services) nginx tailscale; in { imports = let @@ -32,7 +32,6 @@ in { nixos.access.global nixos.access.gensokyo nixos.access.vouch - nixos.access.kanidm nixos.access.freeipa nixos.access.freepbx nixos.access.unifi @@ -72,22 +71,6 @@ in { ]) ]; }; - ${access.kanidm.domain} = { - inherit (nginx) group; - extraDomainNames = mkMerge [ - [access.kanidm.localDomain] - (mkIf access.kanidm.ldapEnable [ - access.kanidm.ldapDomain - access.kanidm.ldapLocalDomain - ]) - (mkIf tailscale.enable [ - access.kanidm.tailDomain - ]) - (mkIf (access.kanidm.ldapEnable && tailscale.enable) [ - access.kanidm.ldapTailDomain - ]) - ]; - }; ${access.unifi.domain} = { inherit (nginx) group; extraDomainNames = mkMerge [ @@ -159,9 +142,6 @@ in { ]) ]; }; - "sso.${config.networking.domain}" = { - inherit (nginx) group; - }; }; services.nginx = let @@ -172,14 +152,9 @@ in { externalPort = 41324; }; access.vouch = assert vouch-proxy.enable; { - url = "http://${tei.lib.access.hostnameForNetwork.tail}:${toString vouch-proxy.settings.vouch.port}"; + url = "http://${keycloak.lib.access.hostnameForNetwork.local}:${toString vouch-proxy.settings.vouch.port}"; useACMEHost = access.vouch.localDomain; }; - access.kanidm = assert kanidm.enableServer; { - inherit (kanidm.server.frontend) domain port; - host = tei.lib.access.hostnameForNetwork.local; - ldapEnable = false; - }; access.unifi = { host = tei.lib.access.hostnameForNetwork.local; useACMEHost = access.unifi.domain; @@ -200,14 +175,6 @@ in { url = "http://${mediabox.lib.access.hostnameForNetwork.local}:${toString mediabox.services.invidious.port}"; }; virtualHosts = { - "sso.${config.networking.domain}" = { - useACMEHost = "sso.${config.networking.domain}"; - locations."/".proxyPass = "http://${keycloak.lib.access.hostnameForNetwork.local}:80"; - forceSSL = true; - }; - ${access.kanidm.domain} = { - useACMEHost = access.kanidm.domain; - }; ${access.freepbx.domain} = { local.enable = true; }; diff --git a/systems/keycloak/lxc.json b/systems/keycloak/lxc.json new file mode 100644 index 00000000..277ebf9b --- /dev/null +++ b/systems/keycloak/lxc.json @@ -0,0 +1,19 @@ +{ + "lxc": { + "lxc.mount.entry": [ + "/dev/net/tun dev/net/tun none bind,optional,create=file" + ], + "lxc.idmap": [ + "u 0 100000 8000", + "g 0 100000 8000", + "u 8000 8000 128", + "g 8000 8000 256", + "u 8128 108128 57406", + "g 8256 108256 57278", + "u 65534 65534 1", + "g 65534 65534 1", + "u 65535 165535 1", + "g 65535 165535 1" + ] + } +} diff --git a/systems/keycloak/nixos.nix b/systems/keycloak/nixos.nix index ec541de6..9f297c72 100644 --- a/systems/keycloak/nixos.nix +++ b/systems/keycloak/nixos.nix @@ -1,4 +1,4 @@ -{meta, ...}: { +{meta, config, ...}: { imports = let inherit (meta) nixos; in [ @@ -6,8 +6,33 @@ nixos.base nixos.reisen-ct nixos.keycloak + nixos.cloudflared + nixos.vouch ]; + services.cloudflared = let + tunnelId = "c9a4b8c9-42d9-4566-8cff-eb63ca26809d"; + inherit (config.services) keycloak vouch-proxy; + in { + tunnels.${tunnelId} = { + default = "http_status:404"; + credentialsFile = config.sops.secrets.cloudflared-tunnel-keycloak.path; + ingress = { + ${keycloak.settings.hostname} = assert keycloak.enable; let + scheme = if keycloak.sslCertificate != null then "https" else "http"; + port = keycloak.settings."${scheme}-port"; + in { + service = "${scheme}://localhost:${toString port}"; + originRequest.${if scheme == "https" then "noTLSVerify" else null} = true; + }; + ${vouch-proxy.domain}.service = assert vouch-proxy.enable; "http://localhost:${toString vouch-proxy.settings.vouch.port}"; + }; + }; + }; + sops.secrets.cloudflared-tunnel-keycloak = { + owner = config.services.cloudflared.user; + }; + sops.defaultSopsFile = ./secrets.yaml; systemd.network.networks.eth0 = { diff --git a/systems/keycloak/secrets.yaml b/systems/keycloak/secrets.yaml index c23cda72..9a4f5a36 100644 --- a/systems/keycloak/secrets.yaml +++ b/systems/keycloak/secrets.yaml @@ -1,4 +1,4 @@ -hello: ENC[AES256_GCM,data:RUCrfjPq790szP+p/etEBYjsJbVq+wGaquYc5EBEEeGH6lrxo7mQwmgtDtxEOQ==,iv:aNOzr8HjPVTADpWZS1J7LlSGM5cWW2dgYUPvsrQuOvM=,tag:aQoPsIqUmVaa6pEBAdxxxw==,type:str] +cloudflared-tunnel-keycloak: ENC[AES256_GCM,data:nXqz6gys7c9UsOy1oiFGFIl/ra/Cf2hb+LLjXI4agEy9mXCAJlKKg7YzuNaHGAXkTKlrpp2lC0P7qNmI3zryTQKBa+LHTq5Lcj9ZSbSW9zhVVS6e155RcdDv/7j1lcZnVmynX+Dz5m8bz490IEuVme985+L9W/5/ksCnjNzUFiCkaxKwe/w2gGv6GdBVYqCFv1j4XBTNAA9D62uZLM5IATtbaam3yZvygWcDLZLpnI+D1Cd5UvOMpgEvdyvKxfaZEzbgkX6BP2mcw+jC9XM=,iv:1rJgyfj+0vIO9hi5U1IarWlaK/tlpAFHn/q7bhtqogg=,tag:fCCY9lxnFt/ImqDeBH0hvw==,type:str] sops: shamir_threshold: 1 kms: [] @@ -15,8 +15,8 @@ sops: WkhIeEh1amh5K0hIb2FKZ0ppSGpBZlEKjF9ysJCX40H5vH4UuZSXryAThk3ipdlP RML2if3bz+uMXgw+zdEx8Ac6IcOM25K0gco6g/6r20WYbKz9og5JuA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-03-13T22:39:15Z" - mac: ENC[AES256_GCM,data:14X+ClZ3Rsvi9aETzjSvjIiKKq6cPOe7t3LrB+ln3FTB4Wf7Fsbhd8aOdYff3yKqTfcnZU2VzEAEFJGNNlkCLQe9PgbKwzfKMH2i5dc9WpgJ6wY2btAUMRp3ocLwGwiRj0Nx8XsvTBL/8qzccHZL0A7I/MmwMiqsIyVWycj679c=,iv:zL8/3+XdVbvWrC5ODKurwtVoY921kQqwocc/hPgDLWI=,tag:HSDA4nCyoKaYBdNNg0+9bA==,type:str] + lastmodified: "2024-03-19T02:38:20Z" + mac: ENC[AES256_GCM,data:OqqsVE2xKsCpIZqszpdBWl9jEToImVW/Vdb5p0HyqjUOL1NSdyRThxx7fft7RlL9Iqd340WrQ/F4kmQHr+4pIEBsKkwrWUh0sbVNz1uLXFasr1nXuhB32zCu6/gxW9fofT11aHBjnH6rLy6KTnXK56jiyaXKPc25EgzKC9aomR4=,iv:hmADJiouxO4dznlSbKXJcAJgRJKtiR5QlypWt3/I7o0=,tag:HBP0G5o30rZsj+2YpM5gkw==,type:str] pgp: - created_at: "2024-03-13T22:39:09Z" enc: |- diff --git a/systems/tei/cloudflared.nix b/systems/tei/cloudflared.nix index 4549fd52..2728260e 100644 --- a/systems/tei/cloudflared.nix +++ b/systems/tei/cloudflared.nix @@ -40,27 +40,6 @@ nameValuePair host { service = "http://${accessHostFor args}:${toString port}"; }; - ingressForVouch = { - host ? system.services.vouch-proxy.domain, - port ? system.services.vouch-proxy.settings.vouch.port, - hostName, - system ? nixosFor hostName, - ... - } @ args: - nameValuePair host { - service = "http://${accessHostFor args}:${toString port}"; - }; - ingressForKanidm = { - host ? system.services.kanidm.server.frontend.domain, - port ? system.services.kanidm.server.frontend.port, - hostName, - system ? nixosFor hostName, - ... - } @ args: - nameValuePair host { - service = "https://${accessHostFor args}:${toString port}"; - originRequest.noTLSVerify = true; - }; in { sops.secrets.cloudflared-tunnel-apartment.owner = cfg.user; services.cloudflared = { @@ -78,8 +57,6 @@ in { inherit hostName; }) (ingressForHass {inherit hostName;}) - (ingressForVouch {inherit hostName;}) - (ingressForKanidm {inherit hostName;}) ]; }; }; diff --git a/systems/tei/lxc.json b/systems/tei/lxc.json index 0da32168..9b7c6a80 100644 --- a/systems/tei/lxc.json +++ b/systems/tei/lxc.json @@ -6,7 +6,6 @@ "/rpool/shared/mosquitto mnt/shared/mosquitto none bind,optional,create=dir", "/rpool/shared/hass mnt/shared/hass none bind,optional,create=dir", "/rpool/shared/postgresql mnt/shared/postgresql none bind,optional,create=dir", - "/rpool/shared/kanidm mnt/shared/kanidm none bind,optional,create=dir", "/rpool/shared/unifi mnt/shared/unifi none bind,optional,create=dir", "/dev/ttyZigbee dev/ttyZigbee none bind,optional,create=file", "/dev/net/tun dev/net/tun none bind,optional,create=file" diff --git a/systems/tei/nixos.nix b/systems/tei/nixos.nix index 7984e3f8..4690dac4 100644 --- a/systems/tei/nixos.nix +++ b/systems/tei/nixos.nix @@ -5,7 +5,7 @@ ... }: let inherit (lib.modules) mkIf mkMerge; - inherit (config.services) kanidm mosquitto home-assistant; + inherit (config.services) mosquitto home-assistant; in { imports = let inherit (meta) nixos; @@ -19,8 +19,6 @@ in { nixos.access.zigbee2mqtt nixos.access.home-assistant nixos.access.unifi - nixos.vouch - nixos.kanidm nixos.unifi nixos.mosquitto nixos.home-assistant @@ -43,10 +41,6 @@ in { networking.firewall = { interfaces.local.allowedTCPPorts = mkMerge [ - (mkIf kanidm.enableServer [ - kanidm.server.frontend.port - (mkIf kanidm.server.ldap.enable kanidm.server.ldap.port) - ]) (mkIf home-assistant.enable [ home-assistant.config.http.server_port ]) diff --git a/tf/cloudflare_idp_records.tf b/tf/cloudflare_idp_records.tf index 09ebe805..e360bcd5 100644 --- a/tf/cloudflare_idp_records.tf +++ b/tf/cloudflare_idp_records.tf @@ -3,177 +3,177 @@ locals { } resource "cloudflare_record" "kerberos_master_tcp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "@" - type = "SRV" - ttl = 3600 + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "@" + type = "SRV" + ttl = 3600 data { - service = "_kerberos-master" - proto = "_tcp" - name = cloudflare_zone.gensokyo-zone_zone.zone + service = "_kerberos-master" + proto = "_tcp" + name = cloudflare_zone.gensokyo-zone_zone.zone priority = 0 - weight = 100 - port = 88 - target = local.idp_fqdn + weight = 100 + port = 88 + target = local.idp_fqdn } } resource "cloudflare_record" "kerberos_master_udp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "@" - type = "SRV" - ttl = 3600 + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "@" + type = "SRV" + ttl = 3600 data { - service = "_kerberos-master" - proto = "_udp" - name = cloudflare_zone.gensokyo-zone_zone.zone + service = "_kerberos-master" + proto = "_udp" + name = cloudflare_zone.gensokyo-zone_zone.zone priority = 0 - weight = 100 - port = 88 - target = local.idp_fqdn + weight = 100 + port = 88 + target = local.idp_fqdn } } resource "cloudflare_record" "kerberos_tcp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "@" - type = "SRV" - ttl = 3600 + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "@" + type = "SRV" + ttl = 3600 data { - service = "_kerberos" - proto = "_tcp" - name = cloudflare_zone.gensokyo-zone_zone.zone + service = "_kerberos" + proto = "_tcp" + name = cloudflare_zone.gensokyo-zone_zone.zone priority = 0 - weight = 100 - port = 88 - target = local.idp_fqdn + weight = 100 + port = 88 + target = local.idp_fqdn } } resource "cloudflare_record" "kerberos_udp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "@" - type = "SRV" - ttl = 3600 + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "@" + type = "SRV" + ttl = 3600 data { - service = "_kerberos" - proto = "_udp" - name = cloudflare_zone.gensokyo-zone_zone.zone + service = "_kerberos" + proto = "_udp" + name = cloudflare_zone.gensokyo-zone_zone.zone priority = 0 - weight = 100 - port = 88 - target = local.idp_fqdn + weight = 100 + port = 88 + target = local.idp_fqdn } } resource "cloudflare_record" "kerberos_txt" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "_kerberos" - type = "TXT" - ttl = 3600 - value = "GENSOKYO.ZONE" + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "_kerberos" + type = "TXT" + ttl = 3600 + value = "GENSOKYO.ZONE" } resource "cloudflare_record" "kerberos_uri_tcp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "_kerberos" - type = "URI" + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "_kerberos" + type = "URI" priority = 0 data { - weight = 100 + weight = 100 content = "krb5srv:m:tcp:${local.idp_fqdn}." } ttl = 3600 } resource "cloudflare_record" "kerberos_uri_udp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "_kerberos" - type = "URI" + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "_kerberos" + type = "URI" priority = 0 data { - weight = 100 + weight = 100 content = "krb5srv:m:udp:${local.idp_fqdn}." } ttl = 3600 } resource "cloudflare_record" "kpasswd_tcp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "@" - type = "SRV" - ttl = 3600 + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "@" + type = "SRV" + ttl = 3600 data { - service = "_kpasswd" - proto = "_tcp" - name = cloudflare_zone.gensokyo-zone_zone.zone + service = "_kpasswd" + proto = "_tcp" + name = cloudflare_zone.gensokyo-zone_zone.zone priority = 0 - weight = 100 - port = 464 - target = local.idp_fqdn + weight = 100 + port = 464 + target = local.idp_fqdn } } resource "cloudflare_record" "kpasswd_udp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "@" - type = "SRV" - ttl = 3600 + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "@" + type = "SRV" + ttl = 3600 data { - service = "_kpasswd" - proto = "_udp" - name = cloudflare_zone.gensokyo-zone_zone.zone + service = "_kpasswd" + proto = "_udp" + name = cloudflare_zone.gensokyo-zone_zone.zone priority = 0 - weight = 100 - port = 464 - target = local.idp_fqdn + weight = 100 + port = 464 + target = local.idp_fqdn } } resource "cloudflare_record" "kpasswd_uri_tcp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "_kpasswd" - type = "URI" + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "_kpasswd" + type = "URI" priority = 0 data { - weight = 100 + weight = 100 content = "krb5srv:m:tcp:${local.idp_fqdn}." } ttl = 3600 } resource "cloudflare_record" "kpasswd_uri_udp" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "_kpasswd" - type = "URI" + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "_kpasswd" + type = "URI" priority = 0 data { - weight = 100 + weight = 100 content = "krb5srv:m:udp:${local.idp_fqdn}." } ttl = 3600 } resource "cloudflare_record" "ldap" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "@" - type = "SRV" - ttl = 3600 + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "@" + type = "SRV" + ttl = 3600 data { - service = "_ldap" - proto = "_tcp" - name = cloudflare_zone.gensokyo-zone_zone.zone + service = "_ldap" + proto = "_tcp" + name = cloudflare_zone.gensokyo-zone_zone.zone priority = 0 - weight = 100 - port = 389 - target = local.idp_fqdn + weight = 100 + port = 389 + target = local.idp_fqdn } } resource "cloudflare_record" "idp-ca" { - zone_id = cloudflare_zone.gensokyo-zone_zone.id - name = "idp-ca" - type = "CNAME" - ttl = 60 - value = local.idp_fqdn + zone_id = cloudflare_zone.gensokyo-zone_zone.id + name = "idp-ca" + type = "CNAME" + ttl = 60 + value = local.idp_fqdn } diff --git a/tf/cloudflare_records.tf b/tf/cloudflare_records.tf index 447b57c8..955bea8e 100644 --- a/tf/cloudflare_records.tf +++ b/tf/cloudflare_records.tf @@ -33,7 +33,6 @@ module "hakurei_system_records" { "freeipa", "ldap", "pbx", - "sso", "smb", "kitchen", "yt", @@ -54,11 +53,12 @@ module "reimu_system_records" { } module "keycloak_system_records" { - source = "./system/records" - name = "keycloak" - zone_id = cloudflare_zone.gensokyo-zone_zone.id - zone_zone = cloudflare_zone.gensokyo-zone_zone.zone - local_v4 = "10.1.1.48" + source = "./system/records" + name = "keycloak" + zone_id = cloudflare_zone.gensokyo-zone_zone.id + zone_zone = cloudflare_zone.gensokyo-zone_zone.zone + local_v4 = "10.1.1.48" + local_v6 = "fd0a::be24:11ff:fec4:66ac" } module "aya_system_records" { diff --git a/tf/cloudflare_tunnels.tf b/tf/cloudflare_tunnels.tf index 24702d02..c76feb20 100644 --- a/tf/cloudflare_tunnels.tf +++ b/tf/cloudflare_tunnels.tf @@ -28,6 +28,36 @@ output "cloudflare_tunnel_cname_hakurei" { value = module.hakurei.cname } +variable "cloudflare_tunnel_secret_keycloak" { + type = string + sensitive = true +} + +module "keycloak" { + source = "./tunnel" + name = "keycloak" + secret = var.cloudflare_tunnel_secret_keycloak + account_id = var.cloudflare_account_id + zone_id = cloudflare_zone.gensokyo-zone_zone.id + subdomains = [ + "sso", + "login", + ] +} + +output "cloudflare_tunnel_id_keycloak" { + value = module.keycloak.id +} + +output "cloudflare_tunnel_token_keycloak" { + value = module.keycloak.token + sensitive = true +} + +output "cloudflare_tunnel_cname_keycloak" { + value = module.keycloak.cname +} + variable "cloudflare_tunnel_secret_tewi" { type = string sensitive = true @@ -42,7 +72,6 @@ module "tewi" { subdomains = [ "home", "id", - "login", "z2m", "unifi", ] diff --git a/tf/proxmox_vms.tf b/tf/proxmox_vms.tf index abe7e1e2..29fb9828 100644 --- a/tf/proxmox_vms.tf +++ b/tf/proxmox_vms.tf @@ -4,9 +4,10 @@ variable "proxmox_container_template" { } locals { - proxmox_keycloak_vm_id = 107 - proxmox_litterbox_vm_id = 106 - proxmox_litterbox_config = jsondecode(file("${path.root}/../systems/litterbox/lxc.json")) + proxmox_keycloak_vm_id = 107 + proxmox_keycloak_config = jsondecode(file("${path.root}/../systems/keycloak/lxc.json")) + proxmox_litterbox_vm_id = 106 + proxmox_litterbox_config = jsondecode(file("${path.root}/../systems/litterbox/lxc.json")) proxmox_aya_vm_id = 105 proxmox_aya_config = jsondecode(file("${path.root}/../systems/aya/lxc.json")) proxmox_reimu_vm_id = 104 @@ -367,7 +368,7 @@ EOT } network_device { - bridge = "vmbr0" + bridge = "vmbr0" mac_address = "BC:24:11:3D:39:91" } @@ -493,7 +494,7 @@ EOT } network_device { - bridge = "vmbr0" + bridge = "vmbr0" mac_address = "BC:24:11:33:19:04" } @@ -573,3 +574,10 @@ EOT ignore_changes = [started, unprivileged, initialization[0].dns, operating_system[0].template_file_id] } } + +module "keycloak_config" { + source = "./system/proxmox/lxc/config" + connection = local.proxmox_reisen_connection + container = proxmox_virtual_environment_container.keycloak + config = local.proxmox_keycloak_config.lxc +} diff --git a/tf/terraform.tfvars.sops b/tf/terraform.tfvars.sops index c7efa64c..e4f95839 100644 --- a/tf/terraform.tfvars.sops +++ b/tf/terraform.tfvars.sops @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data:uZ2jedT/YvjZMyHpTsueV1pR03ftduNH874inWoVogZ+OxEHyhhomI2Li1WYxIuAkALAKe2SHEfbksn2EXAJgJ5nta4nWssaNVclhhxjb/pJecbawz4Th/zBVEqX0ys5ydAqGJRJxb6sCg7q6RMewTxNyZ3fP4/WBVrMLngtJW+eYsMl4la8GGhj5JmGtryAHxNKgj/1R1w2fUDP+QFUgs284mncJfkaEgnF/KUlscqWX2rv3s+dey2bAOzTG+0prBDrL5TdgyITzR18FpSFt7IIsPES+Y8ru1wuwswvQ6hlbgdI1cUBlAbh5+RRTlZLYXw3yTKD6i6fWFtyPryqj4fQpo/KT5yL9UtEVzbgIdOJc/1K0D39TcdxEjcGMGDBilZg88ZwFXkHxhfdSAW14IK7YlGOhmSB23cGkxBXM8vvI1KyX9Ouhi11lInAyF7hhKr7FFClIPduInjmB37SBxG0+kIDfu3PbkLnWTybw2vtjao7iv3AK6jrLbbeViTQP+ryCrRLdaDBNJwid/KRcmnasrorbZ8vCAVBEKOf1qbA3dSsGXTtDcqzCZStPuBxmO9/ECVaaZRJ3HL0B8RL6djmTcvqFHal6NCmfX6pNtTfcQBAJ45C+g+nmPkDke8EMDX4v7pM/K+3ZkczUe9ineadQFMoUGJsvXWdv0cohEoNjz3WSZ0VJnEIBQ9SawMkKAQNrWgpqRBlbXk0wW7bvcEFRSbSTJnl5W8t9n6BTPWTzjgGomnp20a56Au2kZcpt4duxbtMaBn/FWCwY3QIHXXYyZkbwTNgOFZy7CarAdbfmzmhZMeGcj0zoN7Y+psd6u3IzV1ZrYbZ5haXmOnqrBVz9f247JfYMN7JAqETnJ4sTvEFPhACjWnB6Xw0DVA7hzT4e+S9t3TNx0mE59O/cLTnN1M5kIDF20YaIkDvAka/3eOHHE5j3BypDhOcU/VPG9OODc3fcqARcFo3cR8d785KyI58LaVgwM1OdmpAQjgdQ9YdKnS4tZOzVRWoJ8O413paiic7QAbVptBst1QoLO2uSO8rCn+qk4COWJyvD3sjWyf4191t+9k2vveSLbSLAufs0hm4if7kEiBP37uWdqhyORr7Y1F2Q/Ahb8Xe0CQAJYVX/ieYSxNBD7fvl65car8oWNRA0VOfQkXkbCPctdM/u97EOcptREOJhEDV3vGolkSiHNAAASk6cJBlnP9ViCL+zfQWFZ5xIigmXkD7nstUaIPJ/yF3CaxPyXRf5MNOv4+u+luRPEgTekGcQPMe7PgZRidQHEgVTeo8Kgi0w/wOBveCEBKpb1E2PIVM9zcWbuMaK4z/Z0Rq4lk2cHfAqD9Lx0sfxarB+GBZg4wa/krqAr16kdBgeMUwi63WXULk8cGh7EiCatmqvTNuuh6cXM3+juzoWKCh+RsOcN7sg0uv9R4CI/T/p9iFoL/O+C5QrWYKEzBpqfnnFqsnCd1P5zGJ9XgY/3wi4jBZ5NxHM6EQ7NzeykgPTnF2bZdR1Xw+uzQpKO3mkRfyo1yW3Tt2VxxRqkPd5hKHCqla0DMVMlVwEbjx3HWcKRdQoBfl2acBaj1Qchu2SGJXIH+1JemoZaN64mQZteUjX+qDnrzXKuwMG+cAmPq15X7F4bhmPnIvhDNLwd+gCtYBaNrGqRjUAttnRwvPtjJFTDvkcr9Nxlgfa7tYCUYqfbqC5N6dUmsTO7IRNpAdU+OY2cnb+Xcd7abNFvDIMUsu3YlV1zX4cgYDFrlO1CKTykM7dcwEuPL30yxNACHbMDSf5Dt7edE/WMllfLaD6Hgydb6LFrgNBL8flOsz/1Rh/8f88oMqTlNHEUjOMmduLVlntjHyGKfgGRHehmPgO8AjP/i/z4hoSVjZprtqWAKUXZLfCxU61wDwyOli8BLof2khyb0E2DiGe7xZLgtyJKv6hYq8QDjmdv7DMJXoONtmQRiwwWBZgF42zSltETjethLSwz2ARv4HJQanYoIjpteDridHhBhW+40uKbvk4A6bHWz7vBKZtLHBdVIH9hYjYA==,iv:8whKSRvl1YFYXfZQpVTqrdUHcTg0Ar1vJygWG1cp2xc=,tag:uty8o9zad3AvS1teVSIDOg==,type:str]", + "data": "ENC[AES256_GCM,data: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,iv:6vdvCs0371Zr1d/C6KHZkATVLFJRyyWuwtqEP8SkouU=,tag:QYh+Ufu8YIvvziHGLt/FZw==,type:str]", "sops": { "shamir_threshold": 1, "kms": null, @@ -7,8 +7,8 @@ "azure_kv": null, "hc_vault": null, "age": null, - "lastmodified": "2024-03-04T16:53:42Z", - "mac": "ENC[AES256_GCM,data:5L+DYEvVmO8RCQ7+dQVf9FT8Fud2Xys/xoo3s8UDS4a1H/dNTbPa9F4M5Tj8zVkVzms0+yerivpgl//LWteuXFWjHuT39Tcg8g5HCtHjijQz3bMcxp7Tx3CbrylK71ljO0LK6IeMF96s7B8VmfpueC5lmzmPUGFqaKZFtHGXhlg=,iv:bOjioDXBsQ0O+W5gArDm7W91LZWCzRAat0NYHnoqSEg=,tag:gIj85XVMKHt9zuPdZw15mQ==,type:str]", + "lastmodified": "2024-03-19T01:44:48Z", + "mac": "ENC[AES256_GCM,data:c+4WUmXEs1r6C1riHHsMAwRyjf5Z58l1/f03Jc8L+komJevGpbSNTxBad3GOHnvFHB4M7ONZehlkEmaXEmTMJUN2LUs4ULU3wsRe/tD1BXs06Ktx8zuW3ym8ND/kfsu17/O5v951iZpDWWuk+ACsu4dnEDeIg27yXviUg4k3BVw=,iv:cVUlvEsXv8AAeDkw+B7aPNo+TQtNzUjO4lZHKge7pg8=,tag:WSRAk1xlVw8TaCxToAYr1g==,type:str]", "pgp": [ { "created_at": "2024-01-14T19:49:29Z",