test: helpers.js — безопасные тестовые CIDR, проверка коллизий, удаление аудита + fix compliance
This commit is contained in:
+50
-28
@@ -9,6 +9,7 @@
|
||||
require('dotenv').config();
|
||||
const supertest = require('supertest');
|
||||
const { pool } = require('../src/db');
|
||||
const { deleteTestAudit, softDeleteByCIDR } = require('./helpers');
|
||||
let pass = 0, fail = 0;
|
||||
const errors = [];
|
||||
|
||||
@@ -18,12 +19,39 @@ function log(ok, name, detail = '') {
|
||||
}
|
||||
|
||||
function bearer(t) { return { Authorization: 'Bearer ' + t }; }
|
||||
function cidr(ip) { return ip.includes('/') ? ip : ip + '/32'; }
|
||||
|
||||
(async () => {
|
||||
console.log('\n══════════════════════════════════════════');
|
||||
console.log(' ТЗ Compliance Check — v0.5.0');
|
||||
console.log('══════════════════════════════════════════\n');
|
||||
|
||||
// ── Тестовые CIDR из «кривых» диапазонов ──
|
||||
// Фиксированные — cleanup всегда работает, даже между разными прогонами.
|
||||
// Проверка коллизий: если реальная запись существует, тест её не трогает.
|
||||
const C = {
|
||||
A: '37.19.199.1/32', B: '46.18.188.2/32', C: '79.133.177.3/32',
|
||||
SUB: '91.210.166.4/32', // для нормализации host bits
|
||||
M22: '176.120.0.0/22', M24: '185.50.0.0/24', M32: '212.8.155.7/32',
|
||||
ADM: '37.19.199.8/32',
|
||||
};
|
||||
// /30 для overlap — C.A=37.19.199.1, /30 покрывает 37.19.199.0-3 → включает C.A
|
||||
const overlapCIDR = C.A.replace(/\/32$/, '/30');
|
||||
// Нормализация: 91.210.166.5/24 → 91.210.166.0/24
|
||||
const subParts = C.SUB.replace(/\/32$/, '').split('.').map(Number);
|
||||
const subNormalized = subParts.slice(0,3).join('.') + '.0/24';
|
||||
|
||||
const allTestCIDRs = [C.A, C.B, C.C, C.SUB, C.M22, C.M24, C.M32, C.ADM,
|
||||
subNormalized, overlapCIDR];
|
||||
|
||||
console.log(' Тестовые CIDR:', C.A, C.B, C.C, '...');
|
||||
|
||||
console.log(' Тестовые CIDR:', C.A, C.B, C.C, '...');
|
||||
|
||||
// ── Pre-cleanup ──
|
||||
await softDeleteByCIDR(allTestCIDRs);
|
||||
console.log(' Pre-cleanup: тестовые CIDR очищены\n');
|
||||
|
||||
const mod = require('../server');
|
||||
const app = await mod.start();
|
||||
const auth = await require('../src/auth').initAuth();
|
||||
@@ -35,18 +63,6 @@ function bearer(t) { return { Authorization: 'Bearer ' + t }; }
|
||||
const tokAdmin = auth.issueMockToken({ clientId: admin.clientId, companyId: admin.companyId, companyName: admin.companyName, email: admin.email });
|
||||
const tokUser = auth.issueMockToken({ clientId: user.clientId, companyId: user.companyId, companyName: user.companyName, email: user.email });
|
||||
|
||||
const C = { A: '8.8.4.1', B: '8.8.4.2', C: '8.8.4.3', SUB: '9.9.9.0/24' };
|
||||
function cidr(ip) { return ip.includes('/') ? ip : ip + '/32'; }
|
||||
|
||||
// ── Pre-cleanup — удаляем только тестовые CIDR ──
|
||||
const testCIDRs = [cidr(C.A), cidr(C.B), cidr(C.C), cidr(C.SUB), '9.9.9.0/24',
|
||||
'85.0.0.0/22', '85.0.0.0/24', '85.0.0.0/32', '86.0.0.0/24', '87.0.0.1/32', '1.2.4.1/32',
|
||||
'85.0.0.0/21', '85.0.0.0/33', '::1', '192.168.1.1'];
|
||||
for (const c of testCIDRs) {
|
||||
await pool.query("UPDATE whitelist_entries SET deleted_at=NOW(), deleted_by='tz-cleanup' WHERE value_cidr=$1 AND deleted_at IS NULL", [c]);
|
||||
}
|
||||
console.log(' Pre-cleanup: тестовые CIDR удалены\n');
|
||||
|
||||
// ══════════════════════════════════════════════════
|
||||
// 4.1. Просмотр списка записей
|
||||
// ══════════════════════════════════════════════════
|
||||
@@ -141,12 +157,14 @@ function bearer(t) { return { Authorization: 'Bearer ' + t }; }
|
||||
|
||||
// 4.3d: Редактирование с пересечением → 409
|
||||
{
|
||||
// Создаём вторую запись
|
||||
await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: C.C, comment: 'for-overlap' });
|
||||
// Пытаемся обновить вторую на пересекающуюся с первой
|
||||
const r = await req.patch('/api/v1/entries/' + entryId).set(bearer(tokUser)).send({ value: '8.8.4.2/31', comment: '' });
|
||||
// Создаём две записи: entryA с C.A, entryB с C.C
|
||||
const rA = await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: C.A, comment: 'keep-A' });
|
||||
const rB = await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: C.C, comment: 'keep-C' });
|
||||
const idB = rB.body?.entry?.id;
|
||||
// Пытаемся обновить entryB на overlapCIDR (пересекается с C.A из entryA)
|
||||
const r = await req.patch('/api/v1/entries/' + idB).set(bearer(tokUser)).send({ value: overlapCIDR, comment: '' });
|
||||
log(r.status === 409, '4.3d: пересечение при edit → 409', `status=${r.status}`);
|
||||
await pool.query('UPDATE whitelist_entries SET deleted_at=NOW() WHERE value_cidr=$1 AND deleted_at IS NULL', [cidr(C.C)]);
|
||||
await pool.query('UPDATE whitelist_entries SET deleted_at=NOW() WHERE value_cidr IN ($1,$2) AND deleted_at IS NULL', [cidr(C.A), cidr(C.C)]);
|
||||
}
|
||||
|
||||
// 4.3e: Чужой пользователь не может редактировать
|
||||
@@ -238,23 +256,28 @@ function bearer(t) { return { Authorization: 'Bearer ' + t }; }
|
||||
// ══════════════════════════════════════════════════
|
||||
console.log('── ТЗ 5 + Приложение А: Валидация ──');
|
||||
|
||||
// 5a: Маски /22-/32 (разные префиксы чтобы не пересекались)
|
||||
// 5a: Маски /22-/32
|
||||
{
|
||||
for (const [m, prefix] of [[22, '85.0.0.0'], [24, '86.0.0.0'], [32, '87.0.0.1']]) {
|
||||
const r = await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: `${prefix}/${m}`, comment: `mask-${m}` });
|
||||
for (const [m, cidrVal] of [[22, C.M22], [24, C.M24], [32, C.M32]]) {
|
||||
const r = await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: cidrVal, comment: `mask-${m}` });
|
||||
log(r.status === 201, `5.m${m}: /${m} → 201`, `status=${r.status}`);
|
||||
}
|
||||
for (const m of [21, 33]) {
|
||||
const r = await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: `85.0.0.0/${m}`, comment: `bad-${m}` });
|
||||
const badCIDR = C.M22.replace(/\/22$/, `/${m}`);
|
||||
const r = await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: badCIDR, comment: `bad-${m}` });
|
||||
log(r.status === 400, `5.m${m}: /${m} → 400`, `status=${r.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 5b: Нормализация host bits
|
||||
{
|
||||
const r = await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: '9.9.9.5/24', comment: 'normalize' });
|
||||
log(r.status === 201, '5.na: 9.9.9.5/24 → 201');
|
||||
log(r.body?.entry?.value_cidr === '9.9.9.0/24', '5.nb: нормализован в 9.9.9.0/24', `got=${r.body?.entry?.value_cidr}`);
|
||||
const subParts = C.SUB.split('/')[0].split('.');
|
||||
subParts[3] = '5'; // host=5, должен нормализоваться в .0
|
||||
const unnormalized = subParts.join('.') + '/24';
|
||||
const r = await req.post('/api/v1/entries').set(bearer(tokUser)).send({ value: unnormalized, comment: 'normalize' });
|
||||
log(r.status === 201, '5.na: нормализация → 201');
|
||||
const expectedNet = subParts.slice(0,3).join('.') + '.0/24';
|
||||
log(r.body?.entry?.value_cidr === expectedNet, '5.nb: нормализован в ' + expectedNet, `got=${r.body?.entry?.value_cidr}`);
|
||||
log(r.body?.wasNormalized === true, '5.nc: wasNormalized=true');
|
||||
}
|
||||
|
||||
@@ -299,7 +322,7 @@ function bearer(t) { return { Authorization: 'Bearer ' + t }; }
|
||||
{
|
||||
const userCo = (await pool.query('SELECT id FROM companies WHERE client_id=$1', [user.clientId])).rows[0];
|
||||
if (userCo) {
|
||||
const r = await req.post('/api/v1/entries?company=' + userCo.id).set(bearer(tokAdmin)).send({ value: '1.2.4.1', comment: 'admin-crud' });
|
||||
const r = await req.post('/api/v1/entries?company=' + userCo.id).set(bearer(tokAdmin)).send({ value: C.ADM, comment: 'admin-crud' });
|
||||
log(r.status === 201, '3.ba: admin POST /entries?company= → 201', `status=${r.status}`);
|
||||
const eid = r.body?.entry?.id;
|
||||
if (eid) {
|
||||
@@ -318,9 +341,8 @@ function bearer(t) { return { Authorization: 'Bearer ' + t }; }
|
||||
// CLEANUP
|
||||
// ══════════════════════════════════════════════════
|
||||
console.log('\n── Cleanup ──');
|
||||
for (const c of [C.A, C.B, C.C, C.SUB, '9.9.9.0/24', '85.0.0.0/22', '85.0.0.0/24', '85.0.0.0/32', '86.0.0.0/24', '87.0.0.1/32', '1.2.4.1']) {
|
||||
await pool.query('UPDATE whitelist_entries SET deleted_at=NOW() WHERE value_cidr=$1 AND deleted_at IS NULL', [cidr(c)]);
|
||||
}
|
||||
await softDeleteByCIDR(allTestCIDRs);
|
||||
await deleteTestAudit();
|
||||
await pool.end();
|
||||
|
||||
console.log('\n══════════════════════════════════════════');
|
||||
|
||||
Reference in New Issue
Block a user