216 lines
6.1 KiB
JavaScript
216 lines
6.1 KiB
JavaScript
const { chromium } = require('playwright');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const dotenv = require('dotenv');
|
||
const speakeasy = require('speakeasy');
|
||
|
||
// Lade .env-Variablen
|
||
dotenv.config();
|
||
|
||
const {
|
||
USERNAME,
|
||
PASSWORD,
|
||
TESTNAME,
|
||
TOTP_SECRET,
|
||
LOGIN_URL = 'about:privatebrowsing',
|
||
LOGOUT_URL = 'about:privatebrowsing',
|
||
SUCCESS_TEXT = ""
|
||
} = process.env;
|
||
|
||
const nodemailer = require('nodemailer');
|
||
|
||
async function sendFailureMail(subject, text, attachments) {
|
||
const transporter = nodemailer.createTransport({
|
||
host: process.env.SMTP_HOST,
|
||
port: parseInt(process.env.SMTP_PORT, 10),
|
||
secure: false, // kein TLS
|
||
tls: {
|
||
rejectUnauthorized: false
|
||
}
|
||
});
|
||
|
||
await transporter.sendMail({
|
||
from: process.env.MAIL_FROM,
|
||
to: process.env.MAIL_TO,
|
||
subject,
|
||
text,
|
||
attachments
|
||
});
|
||
}
|
||
|
||
if (!USERNAME || !PASSWORD || !TOTP_SECRET) {
|
||
console.error('❌ Bitte .env mit USERNAME, PASSWORD und TOTP_SECRET konfigurieren');
|
||
process.exit(2);
|
||
}
|
||
|
||
(async () => {
|
||
const resultDir = '/app/test-results';
|
||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||
|
||
const browser = await chromium.launch({ headless: true });
|
||
const context = await browser.newContext({});
|
||
const page = await context.newPage();
|
||
|
||
console.log('${TESTNAME}: 1 Login aufrufen');
|
||
|
||
try {
|
||
await page.goto(LOGIN_URL);
|
||
await page.setViewportSize({ width: 1920, height: 937 });
|
||
|
||
// Click on <span> "Login with UVEK-Portal (e..."
|
||
await Promise.all([
|
||
page.click('span:nth-child(2)'),
|
||
page.waitForNavigation()
|
||
]);
|
||
|
||
await page.screenshot({ path: `/app/test-results/eiamselect-${timestamp}.png`, fullPage: true });
|
||
|
||
await Promise.all([
|
||
page.click('#social-eIAM'),
|
||
page.waitForNavigation()
|
||
]);
|
||
|
||
|
||
|
||
console.log('✅ Login eiam user eintragen');
|
||
|
||
await page.click('#isiwebuserid');
|
||
await page.fill('#isiwebuserid', USERNAME);
|
||
|
||
await page.screenshot({ path: `/app/test-results/userid-${timestamp}.png`, fullPage: true });
|
||
|
||
await Promise.all([
|
||
// page.click('text=Continue'),
|
||
page.press('#isiwebuserid', 'Enter'),
|
||
page.waitForNavigation()
|
||
]);
|
||
|
||
console.log('✅ Login eiam pw eintragen');
|
||
|
||
await page.click('#isiwebpasswd');
|
||
await page.fill('#isiwebpasswd', PASSWORD);
|
||
|
||
await page.screenshot({ path: `/app/test-results/pw-${timestamp}.png`, fullPage: true });
|
||
|
||
await Promise.all([
|
||
// page.click('text=Login'),
|
||
page.press('#isiwebpasswd', 'Enter'),
|
||
page.waitForNavigation()
|
||
]);
|
||
|
||
console.log('✅ Login eiam TOTP generieren');
|
||
|
||
|
||
const totp = speakeasy.totp({
|
||
secret: TOTP_SECRET,
|
||
encoding: 'base32'
|
||
});
|
||
|
||
|
||
|
||
console.log('✅ Login eiam TOTP ${totp}');
|
||
|
||
console.log('✅ Login eiam TOTP eintragen');
|
||
|
||
|
||
await page.fill('#code2FA', totp);
|
||
|
||
await page.screenshot({ path: `/app/test-results/totp-${timestamp}.png`, fullPage: true });
|
||
|
||
await Promise.all([
|
||
// page.click('text=Continue'),
|
||
page.press('#code2FA', 'Enter'),
|
||
page.waitForNavigation()
|
||
]);
|
||
|
||
console.log('✅ WhoAmI Webseite warten');
|
||
|
||
await page.waitForSelector(`text=${SUCCESS_TEXT}`, { timeout: 10000 });
|
||
|
||
await page.screenshot({ path: `/app/test-results/result-${timestamp}.png`, fullPage: true });
|
||
|
||
console.log(`🔎 Suche nach Benutzername: ${SUCCESS_TEXT}`);
|
||
const pageText = await page.textContent('body');
|
||
|
||
fs.writeFileSync(path.join(resultDir, `final-${timestamp}.html`), await page.content());
|
||
fs.writeFileSync(path.join(resultDir, `final-${timestamp}.txt`), pageText);
|
||
|
||
if (pageText.includes(SUCCESS_TEXT)) {
|
||
console.log('✅ Login erfolgreich – Benutzername sichtbar');
|
||
} else {
|
||
console.error('❌ Benutzername nicht gefunden – Login möglicherweise fehlerhaft');
|
||
await page.screenshot({ path: path.join(resultDir, `username-missing_${timestamp}.png`) });
|
||
fs.writeFileSync(path.join(resultDir, `page-username-missing_${timestamp}.html`), await page.content());
|
||
process.exit(1);
|
||
}
|
||
|
||
console.log('✅ Login erfolgreich - username sichtbar');
|
||
|
||
console.log('✅ Logout');
|
||
|
||
await page.goto(LOGOUT_URL);
|
||
|
||
await Promise.all([
|
||
page.click('#kc-logout'),
|
||
page.waitForNavigation()
|
||
]);
|
||
|
||
console.log('✅ Logout erfolgreich');
|
||
|
||
await page.screenshot({ path: `/app/test-results/logout-${timestamp}.png`, fullPage: true });
|
||
|
||
await browser.close();
|
||
|
||
|
||
|
||
|
||
} catch (err) {
|
||
console.error('❌ Fehler beim Login:', err.message);
|
||
|
||
const screenshotPath = path.join(resultDir, `error_${timestamp}.png`);
|
||
const htmlPath = path.join(resultDir, `page_${timestamp}.html`);
|
||
const textPath = path.join(resultDir, `page-${timestamp}.txt`);
|
||
|
||
await page.screenshot({ path: screenshotPath });
|
||
const pageText = await page.textContent('body');
|
||
fs.writeFileSync(htmlPath, await page.content());
|
||
fs.writeFileSync(textPath, pageText);
|
||
|
||
const captchaDetected = await page.evaluate(() => {
|
||
return document.body.innerText.toLowerCase().includes('captcha') ||
|
||
document.querySelector('input[name="captcha"]') !== null ||
|
||
document.querySelector('.g-recaptcha') !== null;
|
||
});
|
||
|
||
await sendFailureMail(
|
||
'❌ OIDC Login Monitoring fehlgeschlagen',
|
||
`Fehler beim Login:\n\n${err.message}\n\nZeitpunkt: ${timestamp}`,
|
||
[
|
||
{ filename: 'error.png', path: screenshotPath },
|
||
{ filename: 'page.html', path: htmlPath },
|
||
{ filename: 'page.txt', path: textPath }
|
||
]
|
||
);
|
||
|
||
if (captchaDetected) {
|
||
console.error('🚫 Captcha erkannt – Test wird abgebrochen');
|
||
|
||
const captchaPath = path.join(resultDir, `captcha_${timestamp}.png`);
|
||
const htmlPath = path.join(resultDir, `captcha_${timestamp}.html`);
|
||
const textPath = path.join(resultDir, `captcha_${timestamp}.txt`);
|
||
|
||
await page.screenshot({ path: captchaPath });
|
||
fs.writeFileSync(htmlPath, await page.content());
|
||
fs.writeFileSync(textPath, await page.evaluate(() => document.body.innerText));
|
||
|
||
process.exit(3); // spezieller Exit-Code für Captcha
|
||
}
|
||
|
||
|
||
process.exit(1);
|
||
} finally {
|
||
await browser.close();
|
||
}
|
||
})();
|
||
|