137 lines
4.7 KiB
TypeScript
137 lines
4.7 KiB
TypeScript
import { expect } from '@push.rocks/tapbundle';
|
|
import { SharedSecurityManager } from '../../../ts/core/utils/shared-security-manager.js';
|
|
import type { IRouteConfig, IRouteContext } from '../../../ts/proxies/smart-proxy/models/route-types.js';
|
|
|
|
// Test security manager
|
|
expect.describe('Shared Security Manager', async () => {
|
|
let securityManager: SharedSecurityManager;
|
|
|
|
// Set up a new security manager before each test
|
|
expect.beforeEach(() => {
|
|
securityManager = new SharedSecurityManager({
|
|
maxConnectionsPerIP: 5,
|
|
connectionRateLimitPerMinute: 10
|
|
});
|
|
});
|
|
|
|
expect.it('should validate IPs correctly', async () => {
|
|
// Should allow IPs under connection limit
|
|
expect(securityManager.validateIP('192.168.1.1').allowed).to.be.true;
|
|
|
|
// Track multiple connections
|
|
for (let i = 0; i < 4; i++) {
|
|
securityManager.trackConnectionByIP('192.168.1.1', `conn_${i}`);
|
|
}
|
|
|
|
// Should still allow IPs under connection limit
|
|
expect(securityManager.validateIP('192.168.1.1').allowed).to.be.true;
|
|
|
|
// Add one more to reach the limit
|
|
securityManager.trackConnectionByIP('192.168.1.1', 'conn_4');
|
|
|
|
// Should now block IPs over connection limit
|
|
expect(securityManager.validateIP('192.168.1.1').allowed).to.be.false;
|
|
|
|
// Remove a connection
|
|
securityManager.removeConnectionByIP('192.168.1.1', 'conn_0');
|
|
|
|
// Should allow again after connection is removed
|
|
expect(securityManager.validateIP('192.168.1.1').allowed).to.be.true;
|
|
});
|
|
|
|
expect.it('should authorize IPs based on allow/block lists', async () => {
|
|
// Test with allow list only
|
|
expect(securityManager.isIPAuthorized('192.168.1.1', ['192.168.1.*'])).to.be.true;
|
|
expect(securityManager.isIPAuthorized('192.168.2.1', ['192.168.1.*'])).to.be.false;
|
|
|
|
// Test with block list
|
|
expect(securityManager.isIPAuthorized('192.168.1.5', ['*'], ['192.168.1.5'])).to.be.false;
|
|
expect(securityManager.isIPAuthorized('192.168.1.1', ['*'], ['192.168.1.5'])).to.be.true;
|
|
|
|
// Test with both allow and block lists
|
|
expect(securityManager.isIPAuthorized('192.168.1.1', ['192.168.1.*'], ['192.168.1.5'])).to.be.true;
|
|
expect(securityManager.isIPAuthorized('192.168.1.5', ['192.168.1.*'], ['192.168.1.5'])).to.be.false;
|
|
});
|
|
|
|
expect.it('should validate route access', async () => {
|
|
// Create test route with IP restrictions
|
|
const route: IRouteConfig = {
|
|
match: { ports: 443 },
|
|
action: { type: 'forward', target: { host: 'localhost', port: 8080 } },
|
|
security: {
|
|
ipAllowList: ['192.168.1.*'],
|
|
ipBlockList: ['192.168.1.5']
|
|
}
|
|
};
|
|
|
|
// Create test contexts
|
|
const allowedContext: IRouteContext = {
|
|
port: 443,
|
|
clientIp: '192.168.1.1',
|
|
serverIp: 'localhost',
|
|
isTls: true,
|
|
timestamp: Date.now(),
|
|
connectionId: 'test_conn_1'
|
|
};
|
|
|
|
const blockedContext: IRouteContext = {
|
|
port: 443,
|
|
clientIp: '192.168.1.5',
|
|
serverIp: 'localhost',
|
|
isTls: true,
|
|
timestamp: Date.now(),
|
|
connectionId: 'test_conn_2'
|
|
};
|
|
|
|
const outsideContext: IRouteContext = {
|
|
port: 443,
|
|
clientIp: '192.168.2.1',
|
|
serverIp: 'localhost',
|
|
isTls: true,
|
|
timestamp: Date.now(),
|
|
connectionId: 'test_conn_3'
|
|
};
|
|
|
|
// Test route access
|
|
expect(securityManager.isAllowed(route, allowedContext)).to.be.true;
|
|
expect(securityManager.isAllowed(route, blockedContext)).to.be.false;
|
|
expect(securityManager.isAllowed(route, outsideContext)).to.be.false;
|
|
});
|
|
|
|
expect.it('should validate basic auth', async () => {
|
|
// Create test route with basic auth
|
|
const route: IRouteConfig = {
|
|
match: { ports: 443 },
|
|
action: { type: 'forward', target: { host: 'localhost', port: 8080 } },
|
|
security: {
|
|
basicAuth: {
|
|
enabled: true,
|
|
users: [
|
|
{ username: 'user1', password: 'pass1' },
|
|
{ username: 'user2', password: 'pass2' }
|
|
],
|
|
realm: 'Test Realm'
|
|
}
|
|
}
|
|
};
|
|
|
|
// Test valid credentials
|
|
const validAuth = 'Basic ' + Buffer.from('user1:pass1').toString('base64');
|
|
expect(securityManager.validateBasicAuth(route, validAuth)).to.be.true;
|
|
|
|
// Test invalid credentials
|
|
const invalidAuth = 'Basic ' + Buffer.from('user1:wrongpass').toString('base64');
|
|
expect(securityManager.validateBasicAuth(route, invalidAuth)).to.be.false;
|
|
|
|
// Test missing auth header
|
|
expect(securityManager.validateBasicAuth(route)).to.be.false;
|
|
|
|
// Test malformed auth header
|
|
expect(securityManager.validateBasicAuth(route, 'malformed')).to.be.false;
|
|
});
|
|
|
|
// Clean up resources after tests
|
|
expect.afterEach(() => {
|
|
securityManager.clearIPTracking();
|
|
});
|
|
}); |