WIP: feat/automated-account-deletion #174

Draft
b12f wants to merge 34 commits from feat/automated-account-deletion into main
11 changed files with 129 additions and 210 deletions
Showing only changes of commit c1226c2456 - Show all commits

View file

@ -7,8 +7,8 @@ Per GDPR legislation, accounts should be automatically deleted after a period of
Some services hold on to a session for a very long time. We'll have to query their APIs to see if the account is still in use:
* Matrix via the admin api: https://matrix-org.github.io/synapse/v1.48/admin_api/user_admin_api.html#query-current-sessions-for-a-user
* Mastodon via the admin api: https://docs.joinmastodon.org/methods/admin/accounts/#200-ok
* Nextcloud only gives the last login, not the last active time like a sync via `nextcloud-occ user:lastseen`
* Keycloak
* We can ignore Forgejo, since the sessions there are valid for a maximum of one year, regardless of how they got created
- Matrix via the admin api: https://matrix-org.github.io/synapse/v1.48/admin_api/user_admin_api.html#query-current-sessions-for-a-user
- Mastodon via the admin api: https://docs.joinmastodon.org/methods/admin/accounts/#200-ok
- Nextcloud only gives the last login, not the last active time like a sync via `nextcloud-occ user:lastseen`
- Keycloak
- We can ignore Forgejo, since the sessions there are valid for a maximum of one year, regardless of how they got created

View file

@ -1,4 +1,5 @@
{ config, flake, ... }: {
{ config, flake, ... }:
{
age.secrets.mail-hensoko.file = "${flake.self}/secrets/mail/hensoko.age";
age.secrets.mail-teutat3s.file = "${flake.self}/secrets/mail/teutat3s.age";
age.secrets.mail-admins.file = "${flake.self}/secrets/mail/admins.age";

View file

@ -1,4 +1,6 @@
{ lib }: users: lib.lists.foldl (
{ lib }:
users:
lib.lists.foldl (
wireguardDevices: userConfig:
wireguardDevices ++ (if userConfig ? "wireguardDevices" then userConfig.wireguardDevices else [ ])
) [ ] (lib.attrsets.attrValues users)

View file

@ -1,4 +1,9 @@
{ flake, lib, config, ... }:
{
flake,
lib,
config,
...
}:
{
home-manager.users = (
lib.attrsets.foldlAttrs (

View file

@ -14,27 +14,31 @@
users = mkOption {
description = "Administrative users to add";
type = types.attrsOf (types.submodule {
options = {
sshPubKeys = mkOption {
type = types.attrsOf types.str;
default = {};
type = types.attrsOf (
types.submodule {
options = {
sshPubKeys = mkOption {
type = types.attrsOf types.str;
default = { };
};
secretEncryptionKeys = mkOption {
type = types.attrsOf types.str;
default = { };
};
wireguardDevices = mkOption {
type = types.listOf (
types.submodule {
options = {
publicKey = mkOption { type = types.str; };
allowedIPs = mkOption { type = types.listOf types.str; };
};
}
);
default = { };
};
};
secretEncryptionKeys = mkOption {
type = types.attrsOf types.str;
default = {};
};
wireguardDevices = mkOption {
type = types.listOf (types.submodule {
options = {
publicKey = mkOption { type = types.str; };
allowedIPs = mkOption { type = types.listOf types.str; };
};
});
default = {};
};
};
});
}
);
default = flake.self.logins.admins;
};

View file

@ -1,4 +1,5 @@
{ config, ... }: {
{ config, ... }:
{
mailserver = {
enable = true;
fqdn = "mail.${config.pub-solar-os.networking.domain}";

View file

@ -2,12 +2,14 @@
pkgs,
flake,
...
}:let
}:
let
ca-cert = pkgs.writeTextFile {
name = "ca-cert";
text = builtins.readFile ./step/certs/root_ca.crt;
};
in {
in
{
imports = [
flake.self.inputs.agenix.nixosModules.default
flake.self.nixosModules.home-manager

View file

@ -3,7 +3,8 @@
flake,
lib,
...
}: {
}:
{
imports = [
flake.self.nixosModules.home-manager
flake.self.nixosModules.core
@ -11,16 +12,16 @@
];
networking.nameservers = lib.mkForce [
"193.110.81.0" #dns0.eu
"2a0f:fc80::" #dns0.eu
"185.253.5.0" #dns0.eu
"2a0f:fc81::" #dns0.eu
"193.110.81.0" # dns0.eu
"2a0f:fc80::" # dns0.eu
"185.253.5.0" # dns0.eu
"2a0f:fc81::" # dns0.eu
];
services.resolved.enable = lib.mkForce false;
networking.firewall.allowedUDPPorts = [53];
networking.firewall.allowedTCPPorts = [53];
networking.firewall.allowedUDPPorts = [ 53 ];
networking.firewall.allowedTCPPorts = [ 53 ];
networking.interfaces.eth1.ipv4.addresses = [
{

View file

@ -5,7 +5,7 @@
...
}:
{
pub-solar-os.authentication.users.test-user = {};
pub-solar-os.authentication.users.test-user = { };
pub-solar-os.networking.domain = "test.pub.solar";
@ -34,4 +34,3 @@
pkgs.dig
];
}

View file

@ -61,15 +61,9 @@
"description": "${role_default-roles}",
"composite": true,
"composites": {
"realm": [
"offline_access",
"uma_authorization"
],
"realm": ["offline_access", "uma_authorization"],
"client": {
"account": [
"view-profile",
"manage-account"
]
"account": ["view-profile", "manage-account"]
}
},
"clientRole": false,
@ -132,10 +126,7 @@
"composite": true,
"composites": {
"client": {
"realm-management": [
"query-users",
"query-groups"
]
"realm-management": ["query-users", "query-groups"]
}
},
"clientRole": true,
@ -167,9 +158,7 @@
"composite": true,
"composites": {
"client": {
"realm-management": [
"query-clients"
]
"realm-management": ["query-clients"]
}
},
"clientRole": true,
@ -349,9 +338,7 @@
"composite": true,
"composites": {
"client": {
"account": [
"manage-account-links"
]
"account": ["manage-account-links"]
}
},
"clientRole": true,
@ -401,9 +388,7 @@
"composite": true,
"composites": {
"client": {
"account": [
"view-consent"
]
"account": ["view-consent"]
}
},
"clientRole": true,
@ -440,9 +425,7 @@
"clientRole": false,
"containerId": "8cd6ddbb-d0d3-40ff-9f1e-efdfce05fa6e"
},
"requiredCredentials": [
"password"
],
"requiredCredentials": ["password"],
"otpPolicyType": "totp",
"otpPolicyAlgorithm": "HmacSHA1",
"otpPolicyInitialCounter": 0,
@ -457,9 +440,7 @@
],
"localizationTexts": {},
"webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": [
"ES256"
],
"webAuthnPolicySignatureAlgorithms": ["ES256"],
"webAuthnPolicyRpId": "",
"webAuthnPolicyAttestationConveyancePreference": "not specified",
"webAuthnPolicyAuthenticatorAttachment": "not specified",
@ -470,9 +451,7 @@
"webAuthnPolicyAcceptableAaguids": [],
"webAuthnPolicyExtraOrigins": [],
"webAuthnPolicyPasswordlessRpEntityName": "keycloak",
"webAuthnPolicyPasswordlessSignatureAlgorithms": [
"ES256"
],
"webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"],
"webAuthnPolicyPasswordlessRpId": "",
"webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
"webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
@ -484,29 +463,29 @@
"webAuthnPolicyPasswordlessExtraOrigins": [],
"users": [
{
"id" : "49fcf95e-6fb3-4430-a29a-506a8b20e77c",
"createdTimestamp" : 1673444664000,
"username" : "existing-user",
"enabled" : true,
"totp" : false,
"emailVerified" : true,
"firstName" : "Existing",
"lastName" : "Tester",
"email" : "existing-user@test.pub.solar",
"credentials" : [ {
"id" : "b9fbc30d-4269-49cc-a0ea-9170dc44a30c",
"type" : "password",
"createdDate" : 1673444664000,
"secretData" : "{\"value\":\"yxEZKVTeZlKufE5q4v0Hvxlggg2EaRta5zBtIMxialgwOHrQ3h4Hmre//uk9SlrEv2eqo4aH4bFgPDoktOTyHQ==\",\"salt\":\"d3mk1F43bvQrbV1D+jC1NQ==\",\"additionalParameters\":{}}",
"credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
} ],
"disableableCredentialTypes" : [ ],
"requiredActions" : [ ],
"realmRoles" : [
"default-roles-test.pub.solar"
"id": "49fcf95e-6fb3-4430-a29a-506a8b20e77c",
"createdTimestamp": 1673444664000,
"username": "existing-user",
"enabled": true,
"totp": false,
"emailVerified": true,
"firstName": "Existing",
"lastName": "Tester",
"email": "existing-user@test.pub.solar",
"credentials": [
{
"id": "b9fbc30d-4269-49cc-a0ea-9170dc44a30c",
"type": "password",
"createdDate": 1673444664000,
"secretData": "{\"value\":\"yxEZKVTeZlKufE5q4v0Hvxlggg2EaRta5zBtIMxialgwOHrQ3h4Hmre//uk9SlrEv2eqo4aH4bFgPDoktOTyHQ==\",\"salt\":\"d3mk1F43bvQrbV1D+jC1NQ==\",\"additionalParameters\":{}}",
"credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
}
],
"notBefore" : 0,
"groups" : [ ]
"disableableCredentialTypes": [],
"requiredActions": [],
"realmRoles": ["default-roles-test.pub.solar"],
"notBefore": 0,
"groups": []
},
{
"id": "a0a10fbb-2d1d-4bf1-918d-86659f7dcef1",
@ -518,9 +497,7 @@
"serviceAccountClientId": "admin-cli",
"disableableCredentialTypes": [],
"requiredActions": [],
"realmRoles": [
"default-roles-test.pub.solar"
],
"realmRoles": ["default-roles-test.pub.solar"],
"clientRoles": {
"realm-management": [
"query-realms",
@ -557,13 +534,9 @@
"serviceAccountClientId": "matrix",
"disableableCredentialTypes": [],
"requiredActions": [],
"realmRoles": [
"default-roles-test.pub.solar"
],
"realmRoles": ["default-roles-test.pub.solar"],
"clientRoles": {
"matrix": [
"uma_protection"
]
"matrix": ["uma_protection"]
},
"notBefore": 0,
"groups": []
@ -572,19 +545,14 @@
"scopeMappings": [
{
"clientScope": "offline_access",
"roles": [
"offline_access"
]
"roles": ["offline_access"]
}
],
"clientScopeMappings": {
"account": [
{
"client": "account-console",
"roles": [
"manage-account",
"view-groups"
]
"roles": ["manage-account", "view-groups"]
}
]
},
@ -601,9 +569,7 @@
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [
"/realms/test.pub.solar/account/*"
],
"redirectUris": ["/realms/test.pub.solar/account/*"],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
@ -658,9 +624,7 @@
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [
"/realms/test.pub.solar/account/*"
],
"redirectUris": ["/realms/test.pub.solar/account/*"],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
@ -862,12 +826,8 @@
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "secret",
"redirectUris": [
"https://git.test.pub.solar/*"
],
"webOrigins": [
"https://git.test.pub.solar"
],
"redirectUris": ["https://git.test.pub.solar/*"],
"webOrigins": ["https://git.test.pub.solar"],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
@ -923,12 +883,8 @@
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "secret",
"redirectUris": [
"https://grafana.test.pub.solar/login/generic_oauth"
],
"webOrigins": [
"https://grafana.test.pub.solar"
],
"redirectUris": ["https://grafana.test.pub.solar/login/generic_oauth"],
"webOrigins": ["https://grafana.test.pub.solar"],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
@ -1147,9 +1103,7 @@
"redirectUris": [
"http://[::]:8080/upstream/callback/01HHWGFGBGGCT7HFHD0R4K0AZF"
],
"webOrigins": [
"+"
],
"webOrigins": ["+"],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
@ -1199,12 +1153,8 @@
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "secret",
"redirectUris": [
"https://wiki.test.pub.solar/*"
],
"webOrigins": [
"https://wiki.test.pub.solar"
],
"redirectUris": ["https://wiki.test.pub.solar/*"],
"webOrigins": ["https://wiki.test.pub.solar"],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
@ -1254,12 +1204,8 @@
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "secret",
"redirectUris": [
"https://cloud.test.pub.solar/apps/user_oidc/code"
],
"webOrigins": [
"https://cloud.test.pub.solar"
],
"redirectUris": ["https://cloud.test.pub.solar/apps/user_oidc/code"],
"webOrigins": ["https://cloud.test.pub.solar"],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
@ -1316,12 +1262,8 @@
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "secret",
"redirectUris": [
"https://obs-portal.test.pub.solar/*"
],
"webOrigins": [
"+"
],
"redirectUris": ["https://obs-portal.test.pub.solar/*"],
"webOrigins": ["+"],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
@ -1412,12 +1354,8 @@
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [
"/admin/test.pub.solar/console/*"
],
"webOrigins": [
"+"
],
"redirectUris": ["/admin/test.pub.solar/console/*"],
"webOrigins": ["+"],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
@ -1479,9 +1417,7 @@
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "secret",
"redirectUris": [
"https://login.tailscale.com/a/oauth_response"
],
"redirectUris": ["https://login.tailscale.com/a/oauth_response"],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
@ -1531,12 +1467,8 @@
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "secret",
"redirectUris": [
"https://rss.test.pub.solar"
],
"webOrigins": [
"https://rss.test.pub.solar"
],
"redirectUris": ["https://rss.test.pub.solar"],
"webOrigins": ["https://rss.test.pub.solar"],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
@ -2138,9 +2070,7 @@
"adminTheme": "pub.solar",
"emailTheme": "pub.solar",
"eventsEnabled": false,
"eventsListeners": [
"jboss-logging"
],
"eventsListeners": ["jboss-logging"],
"enabledEventTypes": [],
"adminEventsEnabled": true,
"adminEventsDetailsEnabled": false,
@ -2155,12 +2085,8 @@
"subType": "anonymous",
"subComponents": {},
"config": {
"host-sending-registration-request-must-match": [
"true"
],
"client-uris-must-match": [
"true"
]
"host-sending-registration-request-must-match": ["true"],
"client-uris-must-match": ["true"]
}
},
{
@ -2170,9 +2096,7 @@
"subType": "anonymous",
"subComponents": {},
"config": {
"max-clients": [
"200"
]
"max-clients": ["200"]
}
},
{
@ -2182,9 +2106,7 @@
"subType": "anonymous",
"subComponents": {},
"config": {
"allow-default-scopes": [
"true"
]
"allow-default-scopes": ["true"]
}
},
{
@ -2221,9 +2143,7 @@
"subType": "authenticated",
"subComponents": {},
"config": {
"allow-default-scopes": [
"true"
]
"allow-default-scopes": ["true"]
}
},
{
@ -2273,9 +2193,7 @@
"providerId": "aes-generated",
"subComponents": {},
"config": {
"priority": [
"100"
]
"priority": ["100"]
}
},
{
@ -2284,12 +2202,8 @@
"providerId": "hmac-generated",
"subComponents": {},
"config": {
"priority": [
"100"
],
"algorithm": [
"HS256"
]
"priority": ["100"],
"algorithm": ["HS256"]
}
},
{
@ -2298,9 +2212,7 @@
"providerId": "rsa-generated",
"subComponents": {},
"config": {
"priority": [
"100"
]
"priority": ["100"]
}
},
{
@ -2309,12 +2221,8 @@
"providerId": "rsa-enc-generated",
"subComponents": {},
"config": {
"priority": [
"100"
],
"algorithm": [
"RSA-OAEP"
]
"priority": ["100"],
"algorithm": ["RSA-OAEP"]
}
},
{
@ -2323,21 +2231,14 @@
"providerId": "hmac-generated",
"subComponents": {},
"config": {
"priority": [
"-100"
],
"algorithm": [
"HS512"
]
"priority": ["-100"],
"algorithm": ["HS512"]
}
}
]
},
"internationalizationEnabled": true,
"supportedLocales": [
"de",
"en"
],
"supportedLocales": ["de", "en"],
"defaultLocale": "en",
"authenticationFlows": [
{

View file

@ -2,7 +2,8 @@
config,
flake,
...
}: {
}:
{
imports = [
flake.inputs.simple-nixos-mailserver.nixosModule
flake.self.nixosModules.home-manager
@ -13,7 +14,9 @@
];
# password is password
systemd.tmpfiles.rules = [ "f /tmp/emailpw 1777 root root 10d $2b$11$NV75HGZzMcIwrnVUZKXtxexX9DN52HayDW4eKrD1A8O3uIPnCquQ2" ];
systemd.tmpfiles.rules = [
"f /tmp/emailpw 1777 root root 10d $2b$11$NV75HGZzMcIwrnVUZKXtxexX9DN52HayDW4eKrD1A8O3uIPnCquQ2"
];
mailserver = {
loginAccounts = {