Files
tfm_ainventory/frontend/e2e/fixtures/ldap.ts

187 lines
4.5 KiB
TypeScript

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',
});