bekkalokk: set up idp + mediawiki #25

Merged
oysteikt merged 7 commits from mediawiki-on-bekkalokk into main 2024-04-02 00:00:24 +02:00
6 changed files with 1532 additions and 168 deletions
Showing only changes of commit d531419f35 - Show all commits

View File

@ -14,7 +14,7 @@
./services/gitea/default.nix ./services/gitea/default.nix
./services/kerberos ./services/kerberos
./services/webmail ./services/webmail
# ./services/mediawiki.nix ./services/mediawiki
./services/idp-simplesamlphp ./services/idp-simplesamlphp
]; ];

View File

@ -1,160 +0,0 @@
{ pkgs, lib, config, values, ... }: let
cfg = config.services.mediawiki;
# "mediawiki"
user = config.systemd.services.mediawiki-init.serviceConfig.User;
# "mediawiki"
group = config.users.users.${user}.group;
in {
sops.secrets = {
"mediawiki/password" = {
restartUnits = [ "mediawiki-init.service" "phpfpm-mediawiki.service" ];
owner = user;
group = group;
};
"keys/postgres/mediawiki" = {
restartUnits = [ "mediawiki-init.service" "phpfpm-mediawiki.service" ];
owner = user;
group = group;
};
};
services.mediawiki = {
enable = true;
name = "Programvareverkstedet";
passwordFile = config.sops.secrets."mediawiki/password".path;
passwordSender = "drift@pvv.ntnu.no";
database = {
type = "postgres";
host = "postgres.pvv.ntnu.no";
port = config.services.postgresql.port;
passwordFile = config.sops.secrets."keys/postgres/mediawiki".path;
createLocally = false;
# TODO: create a normal database and copy over old data when the service is production ready
name = "mediawiki_test";
};
# Host through nginx
webserver = "none";
poolConfig = let
listenUser = config.services.nginx.user;
listenGroup = config.services.nginx.group;
in {
inherit user group;
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 4;
"listen.owner" = listenUser;
"listen.group" = listenGroup;
"php_admin_value[error_log]" = "stderr";
"php_admin_flag[log_errors]" = "on";
"env[PATH]" = lib.makeBinPath [ pkgs.php ];
"catch_workers_output" = true;
# to accept *.html file
"security.limit_extensions" = "";
};
extensions = {
inherit (pkgs.mediawiki-extensions) DeleteBatch UserMerge PluggableAuth SimpleSAMLphp;
};
extraConfig = let
SimpleSAMLphpRepo = pkgs.stdenvNoCC.mkDerivation rec {
pname = "configuredSimpleSAML";
version = "2.0.4";
src = pkgs.fetchzip {
url = "https://github.com/simplesamlphp/simplesamlphp/releases/download/v${version}/simplesamlphp-${version}.tar.gz";
sha256 = "sha256-pfMV/VmqqxgtG7Nx4s8MW4tWSaxOkVPtCRJwxV6RDSE=";
};
buildPhase = ''
cat > config/authsources.php << EOF
<?php
$config = array(
'default-sp' => array(
'saml:SP',
'idp' => 'https://idp.pvv.ntnu.no/',
),
);
EOF
'';
installPhase = ''
cp -r . $out
'';
};
in ''
$wgServer = "https://bekkalokk.pvv.ntnu.no";
$wgLocaltimezone = "Europe/Oslo";
# Only allow login through SSO
$wgEnableEmail = false;
$wgEnableUserEmail = false;
$wgEmailAuthentication = false;
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['*']['autocreateaccount'] = true;
$wgPluggableAuth_EnableAutoLogin = true;
# Disable anonymous editing
$wgGroupPermissions['*']['edit'] = false;
# Styling
$wgLogo = "/PNG/PVV-logo.png";
$wgDefaultSkin = "monobook";
# Misc
$wgEmergencyContact = "${cfg.passwordSender}";
$wgShowIPinHeader = false;
$wgUseTeX = false;
$wgLocalInterwiki = $wgSitename;
# SimpleSAML
$wgSimpleSAMLphp_InstallDir = "${SimpleSAMLphpRepo}";
$wgSimpleSAMLphp_AuthSourceId = "default-sp";
$wgSimpleSAMLphp_RealNameAttribute = "cn";
$wgSimpleSAMLphp_EmailAttribute = "mail";
$wgSimpleSAMLphp_UsernameAttribute = "uid";
# Fix https://github.com/NixOS/nixpkgs/issues/183097
$wgDBserver = "${toString cfg.database.host}";
'';
};
# Override because of https://github.com/NixOS/nixpkgs/issues/183097
systemd.services.mediawiki-init.script = let
# According to module
stateDir = "/var/lib/mediawiki";
pkg = cfg.finalPackage;
mediawikiConfig = config.services.phpfpm.pools.mediawiki.phpEnv.MEDIAWIKI_CONFIG;
inherit (lib) optionalString mkForce;
in mkForce ''
if ! test -e "${stateDir}/secret.key"; then
tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c 64 > ${stateDir}/secret.key
fi
echo "exit( wfGetDB( DB_MASTER )->tableExists( 'user' ) ? 1 : 0 );" | \
${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/eval.php --conf ${mediawikiConfig} && \
${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/install.php \
--confpath /tmp \
--scriptpath / \
--dbserver "${cfg.database.host}" \
--dbport ${toString cfg.database.port} \
--dbname ${cfg.database.name} \
${optionalString (cfg.database.tablePrefix != null) "--dbprefix ${cfg.database.tablePrefix}"} \
--dbuser ${cfg.database.user} \
${optionalString (cfg.database.passwordFile != null) "--dbpassfile ${cfg.database.passwordFile}"} \
--passfile ${cfg.passwordFile} \
--dbtype ${cfg.database.type} \
${cfg.name} \
admin
${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/update.php --conf ${mediawikiConfig} --quick
'';
}

View File

@ -0,0 +1,216 @@
{ pkgs, lib, config, values, pkgs-unstable, ... }: let
cfg = config.services.mediawiki;
# "mediawiki"
user = config.systemd.services.mediawiki-init.serviceConfig.User;
# "mediawiki"
group = config.users.users.${user}.group;
simplesamlphp = pkgs.simplesamlphp.override {
extra_files = {
"metadata/saml20-idp-remote.php" = pkgs.writeText "mediawiki-saml20-idp-remote.php" (import ../idp-simplesamlphp/metadata.php.nix);
"config/authsources.php" = ./simplesaml-authsources.php;
"config/config.php" = pkgs.runCommandLocal "mediawiki-simplesamlphp-config.php" { } ''
cp ${./simplesaml-config.php} "$out"
substituteInPlace "$out" \
--replace '$SAML_COOKIE_SECURE' 'true' \
--replace '$SAML_COOKIE_SALT' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/cookie_salt".path}")' \
--replace '$SAML_ADMIN_NAME' '"Drift"' \
--replace '$SAML_ADMIN_EMAIL' '"drift@pvv.ntnu.no"' \
--replace '$SAML_ADMIN_PASSWORD' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/admin_password".path}")' \
--replace '$SAML_TRUSTED_DOMAINS' 'array( "wiki2.pvv.ntnu.no" )' \
--replace '$SAML_DATABASE_DSN' '"pgsql:host=postgres.pvv.ntnu.no;port=5432;dbname=mediawiki_simplesamlphp"' \
--replace '$SAML_DATABASE_USERNAME' '"mediawiki_simplesamlphp"' \
--replace '$SAML_DATABASE_PASSWORD' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/postgres_password".path}")' \
--replace '$CACHE_DIRECTORY' '/var/cache/mediawiki/idp'
oysteikt marked this conversation as resolved Outdated

It would be nice if we could find a better solution for this. Optimally it should

  • Use the upstream config as base
  • Override only specified options
  • Avoid writing a whole php parser in nix
  • Avoid maintaining a nixified copy of the upstream base config

Maybe it would be possible to use includes and some php magic to merge the two?

ping: @felixalb

It would be nice if we could find a better solution for this. Optimally it should - Use the upstream config as base - Override only specified options - Avoid writing a whole php parser in nix - Avoid maintaining a nixified copy of the upstream base config Maybe it would be possible to use includes and some php magic to merge the two? ping: @felixalb

Leaving as future issue.

Leaving as future issue.
'';
};
};
in {
services.idp.sp-remote-metadata = [ "https://wiki2.pvv.ntnu.no/simplesaml/" ];
sops.secrets = lib.pipe [
"mediawiki/password"
"mediawiki/postgres_password"
"mediawiki/simplesamlphp/postgres_password"
"mediawiki/simplesamlphp/cookie_salt"
"mediawiki/simplesamlphp/admin_password"
] [
(map (key: lib.nameValuePair key {
owner = user;
group = group;
}))
lib.listToAttrs
];
services.mediawiki = {
enable = true;
name = "Programvareverkstedet";
passwordFile = config.sops.secrets."mediawiki/password".path;
passwordSender = "drift@pvv.ntnu.no";
database = {
type = "mysql";
host = "mysql.pvv.ntnu.no";
port = 3306;
user = "mediawiki";
passwordFile = config.sops.secrets."mediawiki/postgres_password".path;
createLocally = false;
# TODO: create a normal database and copy over old data when the service is production ready
name = "mediawiki";
};
# Host through nginx
webserver = "none";
poolConfig = let
listenUser = config.services.nginx.user;
listenGroup = config.services.nginx.group;
in {
inherit user group;
"pm" = "dynamic";
"pm.max_children" = 32;
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 4;
"listen.owner" = listenUser;
"listen.group" = listenGroup;
"catch_workers_output" = true;
"php_admin_flag[log_errors]" = true;
# "php_admin_value[error_log]" = "stderr";
# to accept *.html file
"security.limit_extensions" = "";
};
extensions = {
inherit (pkgs.mediawiki-extensions) DeleteBatch UserMerge PluggableAuth SimpleSAMLphp;
oysteikt marked this conversation as resolved Outdated

Should we make some kind of services.mediawiki.debug: bool option? Or even debug.mediawiki: bool (as well as the other services)?

It's very nice to be able to remember how these options were set whenever we need to debug

Should we make some kind of `services.mediawiki.debug: bool` option? Or even `debug.mediawiki: bool` (as well as the other services)? It's very nice to be able to remember how these options were set whenever we need to debug

Leaving these on for now, since they are considered test setups. Let's leave this as a future issue.

Leaving these on for now, since they are considered test setups. Let's leave this as a future issue.
};
extraConfig = ''
$wgServer = "https://wiki2.pvv.ntnu.no";
$wgLocaltimezone = "Europe/Oslo";
# Only allow login through SSO
$wgEnableEmail = false;
$wgEnableUserEmail = false;
$wgEmailAuthentication = false;
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['*']['autocreateaccount'] = true;
$wgPluggableAuth_EnableAutoLogin = false;
# Misc. permissions
$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['*']['read'] = true;
# Misc. URL rules
$wgUsePathInfo = true;
$wgScriptExtension = ".php";
$wgNamespacesWithSubpages[NS_MAIN] = true;
# Styling
$wgLogos = array(
"2x" => "/PNG/PVV-logo.png",
"icon" => "/PNG/PVV-logo.svg",
);
$wgDefaultSkin = "vector-2022";
# from https://github.com/wikimedia/mediawiki-skins-Vector/blob/master/skin.json
$wgVectorDefaultSidebarVisibleForAnonymousUser = true;
$wgVectorResponsive = true;
# Misc
$wgEmergencyContact = "${cfg.passwordSender}";
$wgShowIPinHeader = false;
$wgUseTeX = false;
$wgLocalInterwiki = $wgSitename;
oysteikt marked this conversation as resolved Outdated

yeet

yeet
# SimpleSAML
$wgSimpleSAMLphp_InstallDir = "${simplesamlphp}/share/php/simplesamlphp/";
$wgPluggableAuth_Config['Log in using my SAML'] = [
'plugin' => 'SimpleSAMLphp',
'data' => [
'authSourceId' => 'default-sp',
'usernameAttribute' => 'uid',
'emailAttribute' => 'mail',
'realNameAttribute' => 'cn',
]
];
# Fix https://github.com/NixOS/nixpkgs/issues/183097
$wgDBserver = "${toString cfg.database.host}";
'';
};
# Cache directory for simplesamlphp
# systemd.services.phpfpm-mediawiki.serviceConfig.CacheDirectory = "mediawiki/simplesamlphp";
systemd.tmpfiles.settings."10-mediawiki"."/var/cache/mediawiki/simplesamlphp".d = {
user = "mediawiki";
group = "mediawiki";
mode = "0770";
};
users.groups.mediawiki.members = [ "nginx" ];
services.nginx.virtualHosts."wiki2.pvv.ntnu.no" = {
forceSSL = true;
enableACME = true;
root = "${config.services.mediawiki.finalPackage}/share/mediawiki";
locations = {
"/" = {
index = "index.php";
};
oysteikt marked this conversation as resolved Outdated

The issue this mentions is fixed. Is this still needed?

The issue this mentions is fixed. Is this still needed?

Indeed not needed, will fix

Indeed not needed, will fix
"~ /(.+\\.php)" = {
extraConfig = ''
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_pass unix:${config.services.phpfpm.pools.mediawiki.socket};
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
'';
};
# based on https://simplesamlphp.org/docs/stable/simplesamlphp-install.html#configuring-nginx
"^~ /simplesaml/" = {
alias = "${simplesamlphp}/share/php/simplesamlphp/public/";
index = "index.php";
extraConfig = ''
location ~ ^/simplesaml/(?<phpfile>.+?\.php)(?<pathinfo>/.*)?$ {
include ${pkgs.nginx}/conf/fastcgi_params;
fastcgi_pass unix:${config.services.phpfpm.pools.mediawiki.socket};
fastcgi_param SCRIPT_FILENAME ${simplesamlphp}/share/php/simplesamlphp/public/$phpfile;
# Must be prepended with the baseurlpath
fastcgi_param SCRIPT_NAME /simplesaml/$phpfile;
fastcgi_param PATH_INFO $pathinfo if_not_empty;
}
'';
};
"/images/".alias = "${config.services.mediawiki.uploadsDir}/";
"= /PNG/PVV-logo.svg".alias = ../../../../assets/logo_blue_regular.svg;
"= /PNG/PVV-logo.png".alias = ../../../../assets/logo_blue_regular.png;
"= /favicon.ico".alias = pkgs.runCommandLocal "mediawiki-favicon.ico" {
buildInputs = with pkgs; [ imagemagick ];
} ''
convert \
-resize x64 \
-gravity center \
-crop 64x64+0+0 \
${../../../../assets/logo_blue_regular.png} \
-flatten \
-colors 256 \
-background transparent \
$out
'';
};
};
}

View File

@ -0,0 +1,11 @@
<?php
$config = array(
'admin' => array(
'core:AdminPassword'
),
'default-sp' => array(
'saml:SP',
'entityID' => 'https://wiki2.pvv.ntnu.no/simplesaml/',
'idp' => 'https://idp2.pvv.ntnu.no/',
),
);

File diff suppressed because it is too large Load Diff

View File

@ -10,14 +10,18 @@ gitea:
epsilon: ENC[AES256_GCM,data:JMnZVBdiy+5oPyXgDpfYvy7qLzIEfHy09fQSBDpNG4zDXTil2pSKBKxk09h5xg==,iv:/8oXKJW6+sMBjDt51MqVAWjQPM5nk02Lv5QqbZsZ5ms=,tag:+Rx7ursfVWc0EcExCLgLhQ==,type:str] epsilon: ENC[AES256_GCM,data:JMnZVBdiy+5oPyXgDpfYvy7qLzIEfHy09fQSBDpNG4zDXTil2pSKBKxk09h5xg==,iv:/8oXKJW6+sMBjDt51MqVAWjQPM5nk02Lv5QqbZsZ5ms=,tag:+Rx7ursfVWc0EcExCLgLhQ==,type:str]
mediawiki: mediawiki:
password: ENC[AES256_GCM,data:HsBuA1E7187roGnKuFPfPDYxA16GFjAUucgUtrdUFmcOzmTNiFH+NWY2ZQ==,iv:vDYUmmZftcrkDtJxNYKAJSx9j+AQcmQarC62QRHR4IM=,tag:3TKjNrGRivFWoK3djC748g==,type:str] password: ENC[AES256_GCM,data:HsBuA1E7187roGnKuFPfPDYxA16GFjAUucgUtrdUFmcOzmTNiFH+NWY2ZQ==,iv:vDYUmmZftcrkDtJxNYKAJSx9j+AQcmQarC62QRHR4IM=,tag:3TKjNrGRivFWoK3djC748g==,type:str]
database: ENC[AES256_GCM,data:EvVK3Mo6cZiIZS+gTxixU4r9SXN41VqwaWOtortZRNH+WPJ4xcYvzYMJNg==,iv:JtFTRLn3fzKIfgAPRqRgQjct7EdkEHtiyQKPy8/sZ2Q=,tag:nqzseG6BC0X5UNI/3kZZ3A==,type:str] postgres_password: ENC[AES256_GCM,data:XIOmrOVXWvMMcPJtmovhdyZvLlhmrsrwjuMMkdEY1NIXWjevj5XEkp6Cpw==,iv:KMPTRzu3H/ewfEhc/O0q3o230QNkABfPYF/D1SYL2R8=,tag:sFZiFPHWxwzD9HndPmH3pQ==,type:str]
simplesamlphp:
postgres_password: ENC[AES256_GCM,data:FzykBVtJbA+Bey1GE5VqnSuv2GeobH1j,iv:wayQH3+y0FYFkr3JjmulI53SADk0Ikur/2mUS5kFrTk=,tag:d+nQ/se2bDA5aaQfBicnPQ==,type:str]
cookie_salt: ENC[AES256_GCM,data:BioRPAvL4F9ORBJDFdqHot81RhVpAOf32v1ah3pvOLq8E88bxGyKFQZxAwpIL3UkWQIsWMnEerm5MEMYL1C2OQ==,iv:yMVqiPTQ8hO1IVAax6PIkD0V9YTOEunwDTtnGcmy6Kc=,tag:Z4+bZF4olLlkx7YpXeQiUw==,type:str]
admin_password: ENC[AES256_GCM,data:4eUXvcO7NLOWke9XShfKzj+x3FvqPONa,iv:3iZ+BTBTZ7yMJ0HT14cEMebKZattWUcYEevRsl/6WOk=,tag:CU0iDhPP2ndztdX5U5A4cw==,type:str]
keycloak: keycloak:
database: ENC[AES256_GCM,data:76+AZnNR5EiturTP7BdOCKE90bFFkfGlRtviSP5NHxPbb3RfFPJEMlwtzA==,iv:nS7VTossHdlrHjPeethhX+Ysp9ukrb5JD7kjG28OFpY=,tag:OMpiEv9nQA7v6lWJfNxEEw==,type:str] database: ENC[AES256_GCM,data:76+AZnNR5EiturTP7BdOCKE90bFFkfGlRtviSP5NHxPbb3RfFPJEMlwtzA==,iv:nS7VTossHdlrHjPeethhX+Ysp9ukrb5JD7kjG28OFpY=,tag:OMpiEv9nQA7v6lWJfNxEEw==,type:str]
idp: idp:
cookie_salt: ENC[AES256_GCM,data:vwHF7graEq0QmELkfuoZtrlvKVoFtc9JJAYcHZKR87y4y6J5XUpnDt5OebjYGOGTNs9CWCIQQFNZWqwVN8neXw==,iv:9lTSmCBv5gTGPoRFBMhkvcRCQozDqIsf87ZQrmV2j/M=,tag:atqB4SMZ9oLilChh7BkheQ==,type:str] cookie_salt: ENC[AES256_GCM,data:cyV6HDCPHKQIa8T1+rFBFh6EuHtG5B508lg6uFYENK7qVpYuiTUIokdVQhY8SRLs2mECx/ampgnUHxCRB/Cc/A==,iv:QRrRUhzRQrLkmg38rrYtCEfF8U4/7ZHZUDSEq++BlbI=,tag:fLqFSLd+CKqJvmCh1fx8vg==,type:str]
admin_password: ENC[AES256_GCM,data:g8yWKsplviBxm2za20RyP/dJYOY70Lop,iv:LFoU7VvYjSu1pQPFtRsfJp/CWFk5Lf9EQHZmUVhKkFY=,tag:JMJYpkU0rbqttNTnLcrOiw==,type:str] admin_password: ENC[AES256_GCM,data:Vf33Oenk6x6BIij1uW8RQDjTPcKhUVYA,iv:RNeyCNpTAYdBPrZwE3Y6CCjoAML/3XUvjfJCrr06IEU=,tag:zVOrx1oXnEyr/VwFCFaCDQ==,type:str]
postgres_password: ENC[AES256_GCM,data:ilrtmEcfs3b2eQ1NhV33i49MT7G+oAxu,iv:tkT17fmyEcSWHI29JZusHItqT+wa6oKlfCPIX75Mlhk=,tag:YwZqRTFFWPpVle53fSqR+g==,type:str] postgres_password: ENC[AES256_GCM,data:HGwKLbn/umPLPgH+qpXtugvXzOcXdlhK,iv:ypTW0VLSape8K5aCYu3BdjG/oMmqvfDSLw9uGLthb0Q=,tag:qlDMGz59qzMwEwBYxsC0XQ==,type:str]
privatekey: ENC[AES256_GCM,data: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,iv:iKBBowiGSpzsI2rL8Ek1ONteMji5P9ai2yaaR6eAVTw=,tag:wzO3qrMintbzKyIgLLwgFA==,type:str] privatekey: ENC[AES256_GCM,data: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,iv:8cb1FcIm0oGkcrfLNqXamx4aDA3owBZoHur8+uFsdmA=,tag:oFPP/Yene6QrxFDKlmoVcA==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -51,8 +55,8 @@ sops:
akVjeTNTeGorZjJQOVlMeCtPRUVYL3MK+VMvGxrbzGz4Q3sdaDDWjal+OiK+JYKX akVjeTNTeGorZjJQOVlMeCtPRUVYL3MK+VMvGxrbzGz4Q3sdaDDWjal+OiK+JYKX
GHiMXVHQJZu/RrlxMjHKN6V3iaqxZpuvLAEJ2Lzy5EOHPtuiiRyeHQ== GHiMXVHQJZu/RrlxMjHKN6V3iaqxZpuvLAEJ2Lzy5EOHPtuiiRyeHQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-03-30T22:09:16Z" lastmodified: "2024-03-30T21:22:02Z"
mac: ENC[AES256_GCM,data:1YyPauVMocYQoedanK/wfcfWCqeW6rXz/ItjPbnJGIYp4EdQ3XDiga7fzv06XmuF6kthY4j/T+qyF8mrJQqrb9bXLRvctEySyWOa5dhw2QhPKIbsPa7GeI9nlBQCEGN5I8z2fsMDLb5sOrY1Qw0PA/eb/6yponqeIeIs6Sgo0Ss=,iv:qjnEvEAX7dZYeNHdFWdO7zzpysMncRmcwFz6fWTn1kc=,tag:ghMtRMkPDTfg/e2Y48gPxw==,type:str] mac: ENC[AES256_GCM,data:o3buZqOYZXiNyJ7zDtaBDFwbtP5i0QNvHxVVxtVWdLdRASVmau/ZXdQ8MNsExe6gUF4dS6Sv7QYXRfUO7ccmUDP4zABlIOcxjwsRTs5lE45S6pVIB98OIAODHdyl6LVsgxEkhdPmSoYRjLIWO56KlKArxPQGiprCI7AIBe6DYik=,iv:sAEeBMuJ8JwI3STZuy4miZhXA9Lopbof+3aaprtWVJ4=,tag:LBIRH7KwZ0CuuXuioVL10Q==,type:str]
pgp: pgp:
- created_at: "2023-05-21T00:28:40Z" - created_at: "2023-05-21T00:28:40Z"
enc: | enc: |