From 2c92c343d94f47cf2caa58a620410ff8b74efdc0 Mon Sep 17 00:00:00 2001 From: Daniel Bedeleanu Date: Sun, 19 Apr 2026 07:51:18 +0300 Subject: [PATCH] feat: create ldap fixture for e2e test authentication setup --- frontend/e2e/fixtures/ldap.ts | 186 ++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 frontend/e2e/fixtures/ldap.ts diff --git a/frontend/e2e/fixtures/ldap.ts b/frontend/e2e/fixtures/ldap.ts new file mode 100644 index 00000000..9090f758 --- /dev/null +++ b/frontend/e2e/fixtures/ldap.ts @@ -0,0 +1,186 @@ +import { execSync } from 'child_process'; + +/** + * LDAP fixture for E2E tests + * Manages OpenLDAP Docker container lifecycle + */ + +export interface LdapConfig { + container_name: string; + port: number; + domain: string; + base_dn: string; + admin_password: string; + config_password: string; +} + +/** + * Start OpenLDAP container for a test workflow + */ +export async function startLdapServer(config: LdapConfig): Promise { + const { + container_name, + port, + domain, + base_dn, + admin_password, + config_password, + } = config; + + try { + // Start container using docker-compose + execSync( + `docker run -d --name ${container_name} -p ${port}:389 ` + + `-e LDAP_ORGANISATION="aInventory Test" ` + + `-e LDAP_DOMAIN="${domain}" ` + + `-e LDAP_BASE_DN="${base_dn}" ` + + `-e LDAP_ADMIN_PASSWORD="${admin_password}" ` + + `-e LDAP_CONFIG_PASSWORD="${config_password}" ` + + `osixia/openldap:1.5.0`, + { stdio: 'ignore' } + ); + + // Wait for server to be ready + await waitForLdapReady(config); + } catch (error) { + console.warn(`LDAP startup warning: ${error}`); + } +} + +/** + * Stop and remove OpenLDAP container + */ +export async function stopLdapServer(containerName: string): Promise { + try { + execSync(`docker stop ${containerName}`, { stdio: 'ignore' }); + execSync(`docker rm ${containerName}`, { stdio: 'ignore' }); + } catch (error) { + console.warn(`LDAP cleanup warning: ${error}`); + } +} + +/** + * Wait for LDAP server to be ready + */ +export async function waitForLdapReady(config: LdapConfig, maxRetries: number = 30): Promise { + const { base_dn, admin_password } = config; + let retries = 0; + + while (retries < maxRetries) { + try { + // Test LDAP connectivity using ldapwhoami + execSync( + `docker exec ${config.container_name} ldapwhoami -H ldap://localhost:389 ` + + `-D "cn=admin,${base_dn}" -w "${admin_password}"`, + { stdio: 'ignore' } + ); + return; // Server is ready + } catch { + retries++; + await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1 second + } + } + + throw new Error(`LDAP server did not become ready after ${maxRetries} seconds`); +} + +/** + * Create LDAP user for testing + */ +export async function createLdapUser( + config: LdapConfig, + username: string, + password: string, + email: string +): Promise { + const { container_name, base_dn, admin_password } = config; + + const ldif = ` +dn: uid=${username},ou=users,${base_dn} +objectClass: inetOrgPerson +objectClass: posixAccount +objectClass: shadowAccount +uid: ${username} +cn: ${username} +sn: ${username} +userPassword: ${password} +mail: ${email} +uidNumber: 1001 +gidNumber: 1001 +homeDirectory: /home/${username} +`; + + try { + execSync( + `docker exec -i ${container_name} ldapadd -x -D "cn=admin,${base_dn}" -w "${admin_password}"`, + { + input: ldif, + stdio: ['pipe', 'ignore', 'ignore'], + } + ); + } catch (error) { + console.warn(`LDAP user creation warning: ${error}`); + } +} + +/** + * Verify LDAP user exists and password is correct + */ +export async function verifyLdapUser( + config: LdapConfig, + username: string, + password: string +): Promise { + try { + const { container_name, base_dn } = config; + execSync( + `docker exec ${container_name} ldapwhoami -H ldap://localhost:389 ` + + `-D "uid=${username},ou=users,${base_dn}" -w "${password}"`, + { stdio: 'ignore' } + ); + return true; + } catch { + return false; + } +} + +/** + * Seed LDAP directory with test users + */ +export async function seedLdapUsers( + config: LdapConfig, + users: Array<{ username: string; password: string; email: string }> +): Promise { + for (const user of users) { + await createLdapUser(config, user.username, user.password, user.email); + } +} + +/** + * Get LDAP container status + */ +export async function getLdapStatus(containerName: string): Promise<'running' | 'stopped' | 'not_found'> { + try { + const result = execSync(`docker ps --filter name=${containerName} --format "{{.State}}"`, { + encoding: 'utf-8', + }).trim(); + + if (result === 'running') return 'running'; + if (result === '') return 'not_found'; + return 'stopped'; + } catch { + return 'not_found'; + } +} + +/** + * Default LDAP configuration + */ +export const DEFAULT_LDAP_CONFIG = (workflowId: string, port: number): LdapConfig => ({ + container_name: `ldap-test-${workflowId}`, + port, + domain: 'ainventory.local', + base_dn: 'dc=ainventory,dc=local', + admin_password: 'admin', + config_password: 'config', +});