WIP: feat/automated-account-deletion #174
5 changed files with 160 additions and 38 deletions
flake.lock
tests
8
flake.lock
generated
8
flake.lock
generated
|
@ -335,11 +335,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1724595780,
|
||||
"narHash": "sha256-c6XxFH+qo3SbstKAFLcvGn3GHVJxbuXE2VtBnrjBk10=",
|
||||
"lastModified": 1737810569,
|
||||
"narHash": "sha256-b3ymxmPuMPnAG6Z8FNErmKzjmUcQkXiTs6WkAE1qBkk=",
|
||||
"ref": "main",
|
||||
"rev": "f2a3da5f2637a859897c136e650b88046a89f9fd",
|
||||
"revCount": 4,
|
||||
"rev": "af99e9e38fcbdd691c12aa6044cf831c8eea28b4",
|
||||
"revCount": 6,
|
||||
"type": "git",
|
||||
"url": "https://git.pub.solar/pub-solar/keycloak-event-listener"
|
||||
},
|
||||
|
|
|
@ -44,8 +44,11 @@ in
|
|||
import re
|
||||
import sys
|
||||
|
||||
def puppeteer_run(cmd):
|
||||
client.succeed(f'puppeteer-run \'{cmd}\' ')
|
||||
def puppeteer_succeed(cmd):
|
||||
return client.succeed(f'puppeteer-run \'{cmd}\' ')
|
||||
|
||||
def puppeteer_execute(cmd):
|
||||
return client.execute(f'puppeteer-run \'{cmd}\' ')
|
||||
|
||||
start_all()
|
||||
|
||||
|
@ -69,32 +72,39 @@ in
|
|||
client.wait_for_unit("system.slice")
|
||||
client.wait_for_file("/tmp/puppeteer.sock")
|
||||
|
||||
puppeteer_run('page.goto("https://auth.test.pub.solar")')
|
||||
puppeteer_run('page.waitForNetworkIdle()')
|
||||
####### Registration #######
|
||||
|
||||
puppeteer_succeed('page.goto("https://auth.test.pub.solar")')
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("initial")
|
||||
puppeteer_run('page.locator("::-p-text(Sign in)").click()')
|
||||
puppeteer_run('page.waitForNetworkIdle()')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign in)").click()')
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("sign-in")
|
||||
puppeteer_run('page.locator("::-p-text(Register)").click()')
|
||||
puppeteer_run('page.waitForNetworkIdle()')
|
||||
puppeteer_succeed('page.locator("::-p-text(Register)").click()')
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("register")
|
||||
puppeteer_run('page.locator("[name=username]").fill("test-user")')
|
||||
puppeteer_run('page.locator("[name=email]").fill("test-user@test.pub.solar")')
|
||||
puppeteer_run('page.locator("[name=password]").fill("Password1234")')
|
||||
puppeteer_run('page.locator("[name=password-confirm]").fill("Password1234")')
|
||||
puppeteer_succeed('page.locator("[name=username]").fill("test-user")')
|
||||
puppeteer_succeed('page.locator("[name=email]").fill("test-user@test.pub.solar")')
|
||||
puppeteer_succeed('page.locator("[name=password]").fill("Password1234")')
|
||||
puppeteer_succeed('page.locator("[name=password-confirm]").fill("Password1234")')
|
||||
client.screenshot("register-filled-in")
|
||||
puppeteer_run('page.locator("input[type=submit][value=Register]").click()')
|
||||
puppeteer_run('page.waitForNetworkIdle()')
|
||||
client.screenshot("after-register")
|
||||
puppeteer_succeed('page.locator("input[type=submit][value=Register]").click()')
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("before-email-confirm")
|
||||
|
||||
# Sometimes offlineimap errors out
|
||||
# ERROR: [Errno 2] No such file or directory: '/home/test-user/.local/share/offlineimap'
|
||||
client.succeed("${su "mkdir -p ~/.local/share/offlineimap"}")
|
||||
|
||||
client.succeed("${su "offlineimap"}")
|
||||
client.succeed("${su "[ $(messages -s ~/Maildir/test-user@test.pub.solar/INBOX) -eq 1 ]"}")
|
||||
|
||||
puppeteer_run('page.locator("a::-p-text(Click here)").click()')
|
||||
puppeteer_run('page.waitForNetworkIdle()')
|
||||
puppeteer_succeed('page.locator("a::-p-text(Click here)").click()')
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
|
||||
client.succeed("${su "offlineimap"}")
|
||||
client.succeed("${su "[ $(messages -s ~/Maildir/test-user@test.pub.solar/INBOX) -eq 2 ]"}")
|
||||
|
||||
mail_text = client.execute("${su "echo p | mail -Nf ~/Maildir/test-user@test.pub.solar/INBOX"}")[1]
|
||||
boundary_match = re.search('boundary="(.*)"', mail_text, flags=re.M)
|
||||
if not boundary_match:
|
||||
|
@ -105,11 +115,94 @@ in
|
|||
print(url_match)
|
||||
if not url_match:
|
||||
sys.exit(1)
|
||||
puppeteer_run(f'page.goto("{url_match.group(1)}")')
|
||||
puppeteer_run('page.waitForNetworkIdle()')
|
||||
client.screenshot("email-confirmed")
|
||||
puppeteer_succeed(f'page.goto("{url_match.group(1)}")')
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("registration-complete")
|
||||
|
||||
sys.exit(0)
|
||||
time.sleep(1)
|
||||
####### Logout #######
|
||||
|
||||
puppeteer_succeed('page.locator("[data-testid=options-toggle]").click()')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign out)").click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("logged-out")
|
||||
|
||||
####### Login plain #######
|
||||
|
||||
puppeteer_succeed('page.locator("[name=username]").fill("test-user")')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
|
||||
puppeteer_succeed('page.locator("::-p-text(Restart login)").click()')
|
||||
|
||||
puppeteer_succeed('page.locator("[name=username]").fill("test-user")')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
|
||||
puppeteer_succeed('page.locator("[name=password]").fill("Password1234")')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("logged-in")
|
||||
|
||||
####### Add TOTP #######
|
||||
|
||||
puppeteer_succeed('page.locator("::-p-text(Account security)").click()')
|
||||
puppeteer_succeed('page.locator("::-p-text(Signing in)").click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("signing-in-settings")
|
||||
|
||||
puppeteer_succeed('page.locator(`[data-testid="otp/create"]`).click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("TOTP-setup-qr")
|
||||
|
||||
puppeteer_succeed('page.locator("::-p-text(Unable to scan?)").click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("TOTP-setup-manual")
|
||||
|
||||
totp_secret_key = puppeteer_execute('(async () => { const el = await page.waitForSelector("#kc-totp-secret-key"); return el.evaluate(e => e.textContent); })()')[1]
|
||||
|
||||
totp = client.execute(f'oathtool --totp -b "{totp_secret_key}"')[1].replace("\n", "")
|
||||
|
||||
puppeteer_succeed(f'page.locator("[name=totp]").fill("{totp}")')
|
||||
puppeteer_succeed('page.locator("[name=userLabel]").fill("My TOTP")')
|
||||
client.screenshot("TOTP-form-filled")
|
||||
puppeteer_succeed('page.locator("input[type=submit][value=Submit]").click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("TOTP-added")
|
||||
|
||||
####### Login w/ TOTP #######
|
||||
|
||||
puppeteer_succeed('page.locator("[data-testid=options-toggle]").click()')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign out)").click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("logged-out")
|
||||
|
||||
puppeteer_succeed('page.locator("[name=username]").fill("test-user")')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
|
||||
puppeteer_succeed('page.locator("[name=password]").fill("Password1234")')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("TOTP-login-form")
|
||||
|
||||
print("Sleeping 30s to make sure we roll over into the next TOTP token")
|
||||
time.sleep(30)
|
||||
|
||||
totp = client.execute(f'oathtool --totp -b "{totp_secret_key}"')[1].replace("\n", "")
|
||||
puppeteer_succeed(f'page.locator("[name=otp]").fill("{totp}")')
|
||||
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
|
||||
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
client.screenshot("TOTP-signed-in")
|
||||
|
||||
####### Delete TOTP #######
|
||||
|
||||
puppeteer_succeed('page.locator(`[data-testid="otp/credential-list"] button::-p-text(Delete)`).click()')
|
||||
puppeteer_succeed('page.waitForNetworkIdle()')
|
||||
|
||||
puppeteer_succeed('page.locator("main").scroll({ scrollTop: 200 })')
|
||||
client.screenshot("TOTP-deleted")
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -17,16 +17,13 @@ in
|
|||
];
|
||||
|
||||
security.polkit.enable = true;
|
||||
services.xserver.enable = true;
|
||||
services.xserver.displayManager.gdm.enable = true;
|
||||
services.xserver.desktopManager.gnome.enable = true;
|
||||
services.xserver.displayManager.autoLogin.enable = true;
|
||||
services.xserver.displayManager.autoLogin.user = "test-user";
|
||||
|
||||
environment.systemPackages = [
|
||||
puppeteer-run
|
||||
pkgs.alacritty
|
||||
pkgs.mailutils
|
||||
pkgs.oath-toolkit
|
||||
pkgs.firefox
|
||||
];
|
||||
|
||||
services.getty.autologinUser = "test-user";
|
||||
|
@ -41,6 +38,7 @@ in
|
|||
|
||||
wayland.windowManager.sway = {
|
||||
enable = true;
|
||||
systemd.enable = true;
|
||||
extraSessionCommands = ''
|
||||
export WLR_RENDERER=pixman
|
||||
'';
|
||||
|
|
|
@ -483,6 +483,31 @@
|
|||
"webAuthnPolicyPasswordlessAcceptableAaguids": [],
|
||||
"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"
|
||||
],
|
||||
"notBefore" : 0,
|
||||
"groups" : [ ]
|
||||
},
|
||||
{
|
||||
"id": "a0a10fbb-2d1d-4bf1-918d-86659f7dcef1",
|
||||
"username": "service-account-admin-cli",
|
||||
|
|
|
@ -16,12 +16,18 @@ const EXECUTABLE = process.env.EXECUTABLE || 'firefox';
|
|||
});
|
||||
|
||||
const page = await firefoxBrowser.newPage();
|
||||
page.on('request', request => {
|
||||
console.log(request.url());
|
||||
});
|
||||
// page.on('request', request => {
|
||||
// console.log(`[puppeteer req] ${request.url()}`);
|
||||
// });
|
||||
|
||||
page.on('response', response => {
|
||||
console.log(response.url());
|
||||
// page.on('response', response => {
|
||||
// console.log(`[puppeteer res] ${response.url()}`);
|
||||
// });
|
||||
|
||||
await page.setViewport({
|
||||
width: 1200,
|
||||
height: 600,
|
||||
deviceScaleFactor: 1,
|
||||
});
|
||||
|
||||
const server = http.createServer({});
|
||||
|
@ -41,9 +47,9 @@ const EXECUTABLE = process.env.EXECUTABLE || 'firefox';
|
|||
|
||||
const responseText = (() => {
|
||||
try {
|
||||
return JSON.stringify({ data: val });
|
||||
return val.toString();
|
||||
} catch (err) {
|
||||
return JSON.stringify({ data: val.toString() });
|
||||
return val;
|
||||
}
|
||||
})();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue