import { test, expect } from '@playwright/test'; import { login, BASE_URL } from '../../helpers/auth'; import { markPartial } from '../../helpers/manual'; test.describe('pbx-calls-security', () => { test.beforeEach(async ({ page }) => { await login(page); }); test('pbx-calls-security-check-srtp_sdes_or_dtls_media_encryption', async ({ page }, testInfo) => { testInfo.annotations.push({ type: 'automationStatus', description: 'partial' }); testInfo.annotations.push({ type: 'testType', description: 'check' }); markPartial('Encryption configuration can be verified via admin portal; confirming that live RTP traffic is actually encrypted requires packet capture (Wireshark) during an active call'); testInfo.annotations.push({ type: 'description', description: 'Verify SRTP with SDES or DTLS-SRTP is enabled for media encryption on calls' }); await test.step('Navigate to Security → SIP / Media Encryption', async () => { await page.goto(`${BASE_URL}/admin/security/media-encryption`); }); await test.step('Verify media encryption settings page loads', async () => { await expect(page.locator('body')).not.toContainText(/500|not found/i); }); await test.step('Verify SRTP is enabled', async () => { const srtpToggle = page.locator('[name*="srtp"],[id*="srtp"],[data-field*="srtp"]').first(); if (await srtpToggle.count() > 0) { await expect(srtpToggle).toBeChecked(); } else { const pageText = await page.locator('body').textContent() ?? ''; expect(pageText).toMatch(/srtp.*enabled|srtp.*on|media.*encrypt/i); } }); await test.step('Verify encryption mode is SDES or DTLS', async () => { const pageText = await page.locator('body').textContent() ?? ''; expect(pageText).toMatch(/sdes|dtls/i); }); // TODO_MANUAL: While an active SRTP call is running, capture RTP packets with Wireshark. // Verify: no RTP packets are visible in plain text (audio payload is encrypted). // Confirm SDP shows a=crypto (SDES) or a=fingerprint (DTLS) attribute in INVITE/200 OK. }); test('pbx-calls-security-check-acl_ip_whitelisting_and_rate_limiting', async ({ page }, testInfo) => { testInfo.annotations.push({ type: 'automationStatus', description: 'partial' }); testInfo.annotations.push({ type: 'testType', description: 'check' }); markPartial('ACL rule configuration can be verified via admin portal; testing that the rules actually block traffic requires attempting connections from non-whitelisted IPs — a network-level functional test'); testInfo.annotations.push({ type: 'description', description: 'Verify ACL IP whitelisting rules and SIP rate limiting are configured and enforced' }); await test.step('Navigate to Security → ACL / Firewall', async () => { await page.goto(`${BASE_URL}/admin/security/acl`); }); await test.step('Verify ACL page loads', async () => { await expect(page.locator('body')).not.toContainText(/500|not found/i); }); await test.step('Verify at least one IP whitelist rule exists', async () => { const rules = page.locator('tr, .acl-entry').filter({ hasText: /allow|whitelist|permit/i }); await expect(rules.first()).toBeVisible(); }); await test.step('Navigate to rate limiting settings', async () => { await page.goto(`${BASE_URL}/admin/security/rate-limiting`); }); await test.step('Verify rate limit configuration is shown', async () => { await expect(page.locator('[name*="rate"],[id*="rate"],[class*="rate-limit"]').first()).toBeVisible(); }); // TODO_MANUAL: From a non-whitelisted IP address, attempt a SIP REGISTER. // Verify the attempt is rejected (403 Forbidden or no response). // Send > rate-limit threshold requests/sec; verify subsequent requests are blocked. }); test('pbx-calls-security-check-toll_fraud_prevention_rules_and_alerting', async ({ page }, testInfo) => { testInfo.annotations.push({ type: 'automationStatus', description: 'automated' }); testInfo.annotations.push({ type: 'testType', description: 'check' }); testInfo.annotations.push({ type: 'description', description: 'Verify toll fraud prevention rules are configured and alert notifications are enabled' }); await test.step('Navigate to Security → Toll Fraud Prevention', async () => { await page.goto(`${BASE_URL}/admin/security/toll-fraud`); }); await test.step('Verify toll fraud page loads', async () => { await expect(page.locator('body')).not.toContainText(/500|not found/i); }); await test.step('Verify call limit thresholds are configured', async () => { const limitField = page.locator('[name*="max_calls"],[name*="call_limit"],[id*="threshold"]').first(); if (await limitField.count() > 0) { const value = await limitField.inputValue(); expect(parseInt(value, 10)).toBeGreaterThan(0); } }); await test.step('Verify alerting email is configured', async () => { const emailField = page.locator('[name*="alert_email"],[name*="notification_email"]').first(); if (await emailField.count() > 0) { const value = await emailField.inputValue(); expect(value).toMatch(/@/); } }); await test.step('Verify geographic restrictions or blocked country codes are visible', async () => { const geoSection = page.locator('.geo-restriction, .country-block, [data-section="geo"]').first(); if (await geoSection.count() > 0) { await expect(geoSection).toBeVisible(); } }); }); });