feat: create ldap fixture for e2e test authentication setup
This commit is contained in:
186
frontend/e2e/fixtures/ldap.ts
Normal file
186
frontend/e2e/fixtures/ldap.ts
Normal file
@@ -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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<boolean> {
|
||||
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<void> {
|
||||
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',
|
||||
});
|
||||
Reference in New Issue
Block a user