From ffac1727b92167ca6847b7ae3adc71f091d8048f Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Sun, 10 Jul 2022 11:51:34 +0200 Subject: ... --- hosts/surtr/default.nix | 2 +- hosts/surtr/dns/default.nix | 2 +- .../surtr/dns/keys/mta-sts.bouncy.email_acme.yaml | 26 ++++++ hosts/surtr/dns/zones/email.bouncy.soa | 10 ++- hosts/surtr/email/default.nix | 20 ++++- hosts/surtr/http.nix | 99 ---------------------- hosts/surtr/http/default.nix | 67 +++++++++++++++ hosts/surtr/http/webdav/default.nix | 96 +++++++++++++++++++++ hosts/surtr/http/webdav/py-webdav/.gitignore | 1 + hosts/surtr/http/webdav/py-webdav/VERSION | 1 + hosts/surtr/http/webdav/py-webdav/setup.py | 17 ++++ .../surtr/http/webdav/py-webdav/webdav/__init__.py | 1 + hosts/surtr/http/webdav/py-webdav/webdav/webdav.py | 5 ++ hosts/surtr/matrix/default.nix | 8 +- hosts/surtr/tls/tsig_keys/mta-sts.bouncy.email | 26 ++++++ 15 files changed, 272 insertions(+), 109 deletions(-) create mode 100644 hosts/surtr/dns/keys/mta-sts.bouncy.email_acme.yaml delete mode 100644 hosts/surtr/http.nix create mode 100644 hosts/surtr/http/default.nix create mode 100644 hosts/surtr/http/webdav/default.nix create mode 100644 hosts/surtr/http/webdav/py-webdav/.gitignore create mode 100644 hosts/surtr/http/webdav/py-webdav/VERSION create mode 100644 hosts/surtr/http/webdav/py-webdav/setup.py create mode 100644 hosts/surtr/http/webdav/py-webdav/webdav/__init__.py create mode 100644 hosts/surtr/http/webdav/py-webdav/webdav/webdav.py create mode 100644 hosts/surtr/tls/tsig_keys/mta-sts.bouncy.email (limited to 'hosts/surtr') diff --git a/hosts/surtr/default.nix b/hosts/surtr/default.nix index c9ecc945..87dd27b0 100644 --- a/hosts/surtr/default.nix +++ b/hosts/surtr/default.nix @@ -2,7 +2,7 @@ { imports = with flake.nixosModules.systemProfiles; [ qemu-guest openssh rebuild-machines zfs - ./zfs.nix ./dns ./tls ./http.nix ./bifrost ./matrix ./postgresql.nix ./prometheus ./email + ./zfs.nix ./dns ./tls ./http ./bifrost ./matrix ./postgresql.nix ./prometheus ./email ]; config = { diff --git a/hosts/surtr/dns/default.nix b/hosts/surtr/dns/default.nix index 5b439a8f..808c56da 100644 --- a/hosts/surtr/dns/default.nix +++ b/hosts/surtr/dns/default.nix @@ -184,7 +184,7 @@ in { addACLs = { "rheperire.org" = ["ymir_acme_acl"]; }; } { domain = "bouncy.email"; - acmeDomains = ["mailin.bouncy.email" "mailsub.bouncy.email" "imap.bouncy.email" "spm.bouncy.email" "bouncy.email"]; + acmeDomains = ["mailin.bouncy.email" "mailsub.bouncy.email" "imap.bouncy.email" "spm.bouncy.email" "mta-sts.bouncy.email" "bouncy.email"]; } ]} ''; diff --git a/hosts/surtr/dns/keys/mta-sts.bouncy.email_acme.yaml b/hosts/surtr/dns/keys/mta-sts.bouncy.email_acme.yaml new file mode 100644 index 00000000..ee78810d --- /dev/null +++ b/hosts/surtr/dns/keys/mta-sts.bouncy.email_acme.yaml @@ -0,0 +1,26 @@ +{ + "data": "ENC[AES256_GCM,data:MKHoCzI9odlwPov5Ci9r2IaFCCT7DhOB8EJIFNdgG8xLwdk67SkTQ3kMGXM52EDPWdZ6a90HyKVDgL3O2vl8wbRu49jAIxCYr4t3QhLserNpMikxvAqItivtJKvBL0ah8B4mbjEH1KLou8DZgpDPdL8s+MxTOuYuLBvu/LPGRyabhKVSXmSRIL1iYx7RShe6r2PxiHN6wPmISj9YcwuuWygQRxkEqpybjUQzJe8tYFzuJ19rIUCZ26hI+k3khtFVET4TnouQAdTYXx6I/t/8Q8P7oILPFq4c,iv:w85RawhDWoLtTpWcbHo8W7bXCMa6apQNa4pQLd/whZc=,tag:z3WELFieEDeP9Zrna5brfQ==,type:str]", + "sops": { + "kms": null, + "gcp_kms": null, + "azure_kv": null, + "hc_vault": null, + "age": null, + "lastmodified": "2022-07-10T09:38:55Z", + "mac": "ENC[AES256_GCM,data:w2Ir2YQgkH0+5jNFW7mHyFVW2VEh98ADI99v6e55U7jKdEn70oF8cv787kMHNqpbwYamO9pSAz14is5Po+n11MH0UxESuU0cE7tfvoaUDIDgHNFVENB9dlKrKmnzXyEbN0+p33EP+/QmKYu4yLGc8t33NqoeD7Mc2McnmXJUvm0=,iv:7N480RaBLjIBXWJZG76VzIEyxm2eIxOi9GoZbGm2H50=,tag:JceWZoMQMwqxTYBRMPRnzA==,type:str]", + "pgp": [ + { + "created_at": "2022-07-10T09:38:54Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DyFKFNkTVG5oSAQdAYwPoDNsPVr3pUAih0sMWoebzWi8KQk6nthYKrBvc5mAw\nnuAjBhLc6Tzr8/vf5JbYcPiopd4qgIbPwqW8KAK28EdAz1+VrfM/mpI3wy0lO2YT\n0l4BQBjlvteoUfgV3nYDVbma7hh78Ip7vn0ebzeYCXbGqfCmhZXuZVG9k9rQ+v5t\nenIL1aLxLOBZSbcuDF415MZvKndU5LoQdciVfsFrex8TVzrYKQ62dBr00uysEgTz\n=TPo8\n-----END PGP MESSAGE-----\n", + "fp": "7ED22F4AA7BB55728B643DC5471B7D88E4EF66F8" + }, + { + "created_at": "2022-07-10T09:38:54Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DXxoViZlp6dISAQdAxFqsAJsqWvEmwQiLdSmcVP29dwQF9uLgGCwQCTtjuQYw\njFRrmwCYoCAMM0J7jExm6h7bVwy3pyGeIuya8X1sf6ZRJczGXvGwByK16kVdfgN2\n0l4BAlEaxS/5F6pMNJ0TMdYBMMGJWEa4H0xSE8DkF4Ep5bdxjaY3Pz09m8HWzJRA\nelshtXB8QcFLRG9BQRcPYd4ZEM+HqUCWF1C+7hBJ2SytDSHNZlXtxfd7ey3Jxg8+\n=oqf0\n-----END PGP MESSAGE-----\n", + "fp": "30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51" + } + ], + "unencrypted_suffix": "_unencrypted", + "version": "3.7.3" + } +} \ No newline at end of file diff --git a/hosts/surtr/dns/zones/email.bouncy.soa b/hosts/surtr/dns/zones/email.bouncy.soa index 77acee8b..271a061e 100644 --- a/hosts/surtr/dns/zones/email.bouncy.soa +++ b/hosts/surtr/dns/zones/email.bouncy.soa @@ -1,7 +1,7 @@ $ORIGIN bouncy.email. $TTL 3600 @ IN SOA ns.yggdrasil.li. root.yggdrasil.li. ( - 2022051500 ; serial + 2022071000 ; serial 10800 ; refresh 3600 ; retry 604800 ; expire @@ -63,3 +63,11 @@ spm IN AAAA 2a03:4000:52:ada:: spm IN MX 0 mailin.bouncy.email. spm IN TXT "v=spf1 redirect=bouncy.email" _acme-challenge.spm IN NS ns.yggdrasil.li. + +_mta-sts IN TXT "v=STSv1; id=2022071000" +_smtp._tls IN TXT "v=TLSRPTv1; rua=mailto:postmaster@bouncy.email" +mta-sts IN A 202.61.241.61 +mta-sts IN AAAA 2a03:4000:52:ada:: +mta-sts IN MX 0 mailin.bouncy.email. +mta-sts IN TXT "v=spf1 redirect=bouncy.email" +_acme-challenge.mta-sts IN NS ns.yggdrasil.li. diff --git a/hosts/surtr/email/default.nix b/hosts/surtr/email/default.nix index b952070b..e3437a6b 100644 --- a/hosts/surtr/email/default.nix +++ b/hosts/surtr/email/default.nix @@ -580,6 +580,7 @@ in { "mailin.bouncy.email" = {}; "mailsub.bouncy.email" = {}; "imap.bouncy.email" = {}; + "mta-sts.bouncy.email" = {}; "surtr.yggdrasil.li" = {}; } // listToAttrs (map (domain: nameValuePair "spm.${domain}" {}) spmDomains); @@ -637,13 +638,28 @@ in { proxy_set_header SPM-DOMAIN "${domain}"; ''; }; - }) spmDomains); + }) spmDomains) // { + "mta-sts.bouncy.email" = { + locations."/".root = pkgs.runCommand "mta-sts" {} '' + mkdir -p $out/.well-known + cp ${pkgs.writeText "mta-sts.txt" '' + version: STSv1 + mode: testing + mx: mailin.bouncy.email + max_age: 604800 + ''} $out/.well-known/mta-sts.txt + ''; + }; + }; }; systemd.services.nginx.serviceConfig.LoadCredential = concatMap (domain: [ "spm.${domain}.key.pem:${config.security.acme.certs."spm.${domain}".directory}/key.pem" "spm.${domain}.pem:${config.security.acme.certs."spm.${domain}".directory}/fullchain.pem" - ]) spmDomains; + ]) spmDomains ++ [ + "mta-sts.bouncy.email.key.pem:${config.security.acme.certs."mta-sts.bouncy.email".directory}/key.pem" + "mta-sts.bouncy.email.pem:${config.security.acme.certs."mta-sts.bouncy.email".directory}/fullchain.pem" + ]; systemd.services.spm = { serviceConfig = { diff --git a/hosts/surtr/http.nix b/hosts/surtr/http.nix deleted file mode 100644 index af27f178..00000000 --- a/hosts/surtr/http.nix +++ /dev/null @@ -1,99 +0,0 @@ -{ config, lib, pkgs, ... }: -{ - config = { - security.pam.services."webdav".text = '' - auth requisite pam_succeed_if.so user ingroup webdav quiet_success - auth required pam_unix.so likeauth nullok nodelay quiet - account sufficient pam_unix.so quiet - ''; - users.groups."webdav" = {}; - - services.nginx = { - enable = true; - # package = pkgs.nginxQuic; - recommendedGzipSettings = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - sslDhparam = config.security.dhparams.params.nginx.path; - commonHttpConfig = '' - ssl_ecdh_curve X25519:prime256v1:secp521r1:secp384r1; - - log_format main - '$remote_addr "$remote_user" ' - '"$host" "$request" $status $bytes_sent ' - '"$http_referer" "$http_user_agent" ' - '$gzip_ratio'; - - access_log syslog:server=unix:/dev/log main; - error_log syslog:server=unix:/dev/log info; - - client_body_temp_path /run/nginx-client-bodies; - ''; - additionalModules = with pkgs.nginxModules; [ dav pam ]; - virtualHosts = { - "webdav.141.li" = { - forceSSL = true; - sslCertificate = "/run/credentials/nginx.service/webdav.141.li.pem"; - sslCertificateKey = "/run/credentials/nginx.service/webdav.141.li.key.pem"; - sslTrustedCertificate = "/run/credentials/nginx.service/webdav.141.li.chain.pem"; - locations."/".extraConfig = '' - root /srv/files/$remote_user; - - auth_pam "WebDAV"; - auth_pam_service_name "webdav"; - ''; - extraConfig = '' - dav_methods PUT DELETE MKCOL COPY MOVE; - dav_ext_methods PROPFIND OPTIONS; - dav_access user:rw; - autoindex on; - - client_max_body_size 0; - create_full_put_path on; - - add_header Strict-Transport-Security "max-age=63072000" always; - ''; - }; - }; - }; - security.acme.domains."webdav.141.li" = { - zone = "141.li"; - certCfg = { - postRun = '' - ${pkgs.systemd}/bin/systemctl try-restart nginx.service - ''; - }; - }; - systemd.services.nginx = { - preStart = lib.mkForce config.services.nginx.preStart; - serviceConfig = { - SupplementaryGroups = [ "shadow" ]; - ExecReload = lib.mkForce "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; - LoadCredential = [ - "webdav.141.li.key.pem:${config.security.acme.certs."webdav.141.li".directory}/key.pem" - "webdav.141.li.pem:${config.security.acme.certs."webdav.141.li".directory}/fullchain.pem" - "webdav.141.li.chain.pem:${config.security.acme.certs."webdav.141.li".directory}/chain.pem" - ]; - RuntimeDirectory = lib.mkForce [ "nginx" "nginx-client-bodies" ]; - RuntimeDirectoryMode = "0750"; - - NoNewPrivileges = lib.mkForce false; - PrivateDevices = lib.mkForce false; - ProtectHostname = lib.mkForce false; - ProtectKernelTunables = lib.mkForce false; - ProtectKernelModules = lib.mkForce false; - RestrictAddressFamilies = lib.mkForce [ ]; - LockPersonality = lib.mkForce false; - MemoryDenyWriteExecute = lib.mkForce false; - RestrictRealtime = lib.mkForce false; - RestrictSUIDSGID = lib.mkForce false; - SystemCallArchitectures = lib.mkForce ""; - ProtectClock = lib.mkForce false; - ProtectKernelLogs = lib.mkForce false; - RestrictNamespaces = lib.mkForce false; - SystemCallFilter = lib.mkForce ""; - ReadWritePaths = [ "/srv/files" ]; - }; - }; - }; -} diff --git a/hosts/surtr/http/default.nix b/hosts/surtr/http/default.nix new file mode 100644 index 00000000..a77252ff --- /dev/null +++ b/hosts/surtr/http/default.nix @@ -0,0 +1,67 @@ +{ config, lib, pkgs, ... }: +{ + imports = [ + ./webdav + ]; + + config = { + services.nginx = { + enable = true; + # package = pkgs.nginxQuic; + recommendedGzipSettings = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + sslDhparam = config.security.dhparams.params.nginx.path; + commonHttpConfig = '' + ssl_ecdh_curve X25519:prime256v1:secp521r1:secp384r1; + + log_format main + '$remote_addr "$remote_user" ' + '"$host" "$request" $status $bytes_sent ' + '"$http_referer" "$http_user_agent" ' + '$gzip_ratio'; + + access_log syslog:server=unix:/dev/log main; + error_log syslog:server=unix:/dev/log info; + + client_body_temp_path /run/nginx-client-bodies; + ''; + additionalModules = with pkgs.nginxModules; [ dav pam ]; + }; + systemd.services.nginx = { + preStart = lib.mkForce config.services.nginx.preStart; + serviceConfig = { + SupplementaryGroups = [ "shadow" ]; + ExecReload = lib.mkForce "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + RuntimeDirectory = lib.mkForce [ "nginx" "nginx-client-bodies" ]; + RuntimeDirectoryMode = "0750"; + + NoNewPrivileges = lib.mkForce false; + PrivateDevices = lib.mkForce false; + ProtectHostname = lib.mkForce false; + ProtectKernelTunables = lib.mkForce false; + ProtectKernelModules = lib.mkForce false; + RestrictAddressFamilies = lib.mkForce [ ]; + LockPersonality = lib.mkForce false; + MemoryDenyWriteExecute = lib.mkForce false; + RestrictRealtime = lib.mkForce false; + RestrictSUIDSGID = lib.mkForce false; + SystemCallArchitectures = lib.mkForce ""; + ProtectClock = lib.mkForce false; + ProtectKernelLogs = lib.mkForce false; + RestrictNamespaces = lib.mkForce false; + SystemCallFilter = lib.mkForce ""; + ReadWritePaths = [ "/srv/files" ]; + }; + }; + + services.uwsgi = { + enable = true; + plugins = ["python3"]; + instance = { + type = "emperor"; + vassals = {}; + }; + }; + }; +} diff --git a/hosts/surtr/http/webdav/default.nix b/hosts/surtr/http/webdav/default.nix new file mode 100644 index 00000000..f0aec1e9 --- /dev/null +++ b/hosts/surtr/http/webdav/default.nix @@ -0,0 +1,96 @@ +{ config, libs, pkgs, flakeInputs, ... }: +let + webdavSocket = config.services.uwsgi.runDir + "/webdav.sock"; + + webdavApp = flakeInputs.mach-nix.lib.${config.nixpkgs.system}.buildPythonPackage { + ignoreDataOutdated = true; + pname = "py-webdav"; + version = builtins.readFile ./py-webdav/VERSION; + src = ./py-webdav; + python = "python3"; + requirements = '' + PyNaCl ==1.5.* + psycopg ==3.0.* + WsgiDAV ==4.0.* + ''; + }; +in { + config = { + security.pam.services."webdav".text = '' + auth requisite pam_succeed_if.so user ingroup webdav quiet_success + auth required pam_unix.so likeauth nullok nodelay quiet + account sufficient pam_unix.so quiet + ''; + users.groups."webdav" = {}; + + services.nginx = { + upstreams."py-webdav" = { + servers = { + "unix://${webdavSocket}" = {}; + }; + }; + + virtualHosts."webdav.141.li" = { + forceSSL = true; + sslCertificate = "/run/credentials/nginx.service/webdav.141.li.pem"; + sslCertificateKey = "/run/credentials/nginx.service/webdav.141.li.key.pem"; + sslTrustedCertificate = "/run/credentials/nginx.service/webdav.141.li.chain.pem"; + locations = { + "/".extraConfig = '' + root /srv/files/$remote_user; + + auth_pam "WebDAV"; + auth_pam_service_name "webdav"; + ''; + + "/py/".extraConfig = '' + rewrite ^/py(.*) $1 break; + + include ${config.services.nginx.package}/conf/uwsgi_params; + uwsgi_param SCRIPT_NAME /py; + uwsgi_pass py-webdav; + ''; + }; + extraConfig = '' + dav_methods PUT DELETE MKCOL COPY MOVE; + dav_ext_methods PROPFIND OPTIONS; + dav_access user:rw; + autoindex on; + + client_max_body_size 0; + create_full_put_path on; + + add_header Strict-Transport-Security "max-age=63072000" always; + ''; + }; + }; + security.acme.domains."webdav.141.li" = { + certCfg = { + postRun = '' + ${pkgs.systemd}/bin/systemctl try-restart nginx.service + ''; + }; + }; + + systemd.services.nginx.serviceConfig.LoadCredential = [ + "webdav.141.li.key.pem:${config.security.acme.certs."webdav.141.li".directory}/key.pem" + "webdav.141.li.pem:${config.security.acme.certs."webdav.141.li".directory}/fullchain.pem" + "webdav.141.li.chain.pem:${config.security.acme.certs."webdav.141.li".directory}/chain.pem" + ]; + + + services.uwsgi.instance.vassals.webdav = { + type = "normal"; + socket = webdavSocket; + listen = 1024; + master = true; + vacuum = true; + chown-socket = "${config.services.nginx.user}:${config.services.uwsgi.group}"; + + plugins = ["python3"]; + pythonPackages = self: [webdavApp]; + module = "webdav"; + callable = "app"; + }; + }; +} diff --git a/hosts/surtr/http/webdav/py-webdav/.gitignore b/hosts/surtr/http/webdav/py-webdav/.gitignore new file mode 100644 index 00000000..ed8ebf58 --- /dev/null +++ b/hosts/surtr/http/webdav/py-webdav/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/hosts/surtr/http/webdav/py-webdav/VERSION b/hosts/surtr/http/webdav/py-webdav/VERSION new file mode 100644 index 00000000..6e8bf73a --- /dev/null +++ b/hosts/surtr/http/webdav/py-webdav/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/hosts/surtr/http/webdav/py-webdav/setup.py b/hosts/surtr/http/webdav/py-webdav/setup.py new file mode 100644 index 00000000..dbe345c1 --- /dev/null +++ b/hosts/surtr/http/webdav/py-webdav/setup.py @@ -0,0 +1,17 @@ +import setuptools + +with open('VERSION', 'r', encoding='utf-8') as version_file: + version = version_file.read().strip() + +setuptools.setup( + name="py-webdav", + version=version, + package_dir={"": "."}, + packages=setuptools.find_packages(), + python_requires=">=3.8", + install_requires=[ + "PyNaCl ==1.5.*", + "psycopg ==3.0.*", + "WsgiDAV ==4.0.*", + ], +) diff --git a/hosts/surtr/http/webdav/py-webdav/webdav/__init__.py b/hosts/surtr/http/webdav/py-webdav/webdav/__init__.py new file mode 100644 index 00000000..398378e2 --- /dev/null +++ b/hosts/surtr/http/webdav/py-webdav/webdav/__init__.py @@ -0,0 +1 @@ +from .webdav import app diff --git a/hosts/surtr/http/webdav/py-webdav/webdav/webdav.py b/hosts/surtr/http/webdav/py-webdav/webdav/webdav.py new file mode 100644 index 00000000..783f5d82 --- /dev/null +++ b/hosts/surtr/http/webdav/py-webdav/webdav/webdav.py @@ -0,0 +1,5 @@ +def app(env, start_response): + start_response('200 Success', [('Content-Type', 'text/plain; charset=utf-8')]) + return [ bytes(f'{key}: {value}\n', 'utf8') + for key, value in env.items() + ] diff --git a/hosts/surtr/matrix/default.nix b/hosts/surtr/matrix/default.nix index 9c9c3565..a469be69 100644 --- a/hosts/surtr/matrix/default.nix +++ b/hosts/surtr/matrix/default.nix @@ -140,11 +140,9 @@ with lib; services.nginx = { recommendedProxySettings = true; - upstreams = { - "matrix-synapse" = { - servers = { - "127.0.0.1:8008" = {}; - }; + upstreams."matrix-synapse" = { + servers = { + "127.0.0.1:8008" = {}; }; }; diff --git a/hosts/surtr/tls/tsig_keys/mta-sts.bouncy.email b/hosts/surtr/tls/tsig_keys/mta-sts.bouncy.email new file mode 100644 index 00000000..ce10db57 --- /dev/null +++ b/hosts/surtr/tls/tsig_keys/mta-sts.bouncy.email @@ -0,0 +1,26 @@ +{ + "data": "ENC[AES256_GCM,data:v0QhyJhcbR+ouKYAxvTYWltoA7vmltvb8oTYs0vecTVMx2j2+UkAjw8xJ4qD,iv:007nDkrj4kvYJMa+W3YysDOXws9UZspC3w5vaTGI/II=,tag:Gzpj7bubRknVBNOfQYvoYg==,type:str]", + "sops": { + "kms": null, + "gcp_kms": null, + "azure_kv": null, + "hc_vault": null, + "age": null, + "lastmodified": "2022-07-10T09:39:02Z", + "mac": "ENC[AES256_GCM,data:7dvWXtZd++BwWH6Qaw0WzRhxVVT9U8PFyE9MJ1E/NssSfkAZHaxDpV1kgRaHJav4lIjvUq83oWxBkEcnasfg6zF12xawxbCckf597r3ctndGtyyHLk0b0xBciiJRR8rFKeB81nKTiDzEA7ydfgbkPIktB/4xgi4vke5WHWPQ2Xs=,iv:NTTWRPUFvhDL5KndTwPEB4c3NCw6X9nDdWVPcowVN+Y=,tag:BO+TEaTY0RvptmlF9yhQfQ==,type:str]", + "pgp": [ + { + "created_at": "2022-07-10T09:39:02Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DyFKFNkTVG5oSAQdA1eY+DFYwuexG+2C53SzO1qsn60d1UOeBgeBojLbKwSQw\n55k9cM4vYE50bRrnqEfEXn45u2qYj4NIl2WhfJ4luwvNcmLmqvQCKDOKblOEe6Qi\n0l4B6zMGpHNTSkbaKB/Y2zRpczJxRBJz/cEuimbHs57nMQKpFGst5tMvsGilq4tq\nE8iC77K6S+OFJmJulJ/Rw4Yrg+raZ0KkpVKo+hOOKEi2QaWdBLf6dL+NdH2Qpxqu\n=iJRT\n-----END PGP MESSAGE-----\n", + "fp": "7ED22F4AA7BB55728B643DC5471B7D88E4EF66F8" + }, + { + "created_at": "2022-07-10T09:39:02Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DXxoViZlp6dISAQdAMl+sivtfp0HDutQ2ENSGsoqeIG1//4F0TrmX3GlFVysw\nSA3Env4jdFAtHplG9/6J6PTtnRZNvnqlwoq3Gz1kEIdf8DhQP7/8uPzi2mJz916n\n0l4BOuQfwtJn/M6a7T4xWW4fPh/CgTD8e0TNV4lYboW/YwAhCgOSaRKnObMzGquR\nJ6Fx6q7+y2Be3zpHdOMHpQ1OmEVmysLRo4DeuV6WYDqSOqSklNMVi6D9b+KIQAJo\n=jbRk\n-----END PGP MESSAGE-----\n", + "fp": "30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51" + } + ], + "unencrypted_suffix": "_unencrypted", + "version": "3.7.3" + } +} \ No newline at end of file -- cgit v1.2.3