Files
Charon/docs/testing/security-helpers.md
akanealw eec8c28fb3
Some checks are pending
Go Benchmark / Performance Regression Check (push) Waiting to run
Cerberus Integration / Cerberus Security Stack Integration (push) Waiting to run
Upload Coverage to Codecov / Backend Codecov Upload (push) Waiting to run
Upload Coverage to Codecov / Frontend Codecov Upload (push) Waiting to run
CodeQL - Analyze / CodeQL analysis (go) (push) Waiting to run
CodeQL - Analyze / CodeQL analysis (javascript-typescript) (push) Waiting to run
CrowdSec Integration / CrowdSec Bouncer Integration (push) Waiting to run
Docker Build, Publish & Test / build-and-push (push) Waiting to run
Docker Build, Publish & Test / Security Scan PR Image (push) Blocked by required conditions
Quality Checks / Auth Route Protection Contract (push) Waiting to run
Quality Checks / Codecov Trigger/Comment Parity Guard (push) Waiting to run
Quality Checks / Backend (Go) (push) Waiting to run
Quality Checks / Frontend (React) (push) Waiting to run
Rate Limit integration / Rate Limiting Integration (push) Waiting to run
Security Scan (PR) / Trivy Binary Scan (push) Waiting to run
Supply Chain Verification (PR) / Verify Supply Chain (push) Waiting to run
WAF integration / Coraza WAF Integration (push) Waiting to run
changed perms
2026-04-22 18:19:14 +00:00

144 lines
4.2 KiB
Markdown
Executable File

# Security Test Helpers
Helper utilities for managing security module state during E2E tests.
## Overview
The security helpers module (`tests/utils/security-helpers.ts`) provides utilities for:
- Capturing and restoring security module state
- Toggling individual security modules (ACL, WAF, Rate Limiting, CrowdSec)
- Ensuring test isolation without ACL deadlock
## Problem Solved
During E2E testing, if ACL is left enabled from a previous test run (e.g., due to test failure), it creates a **deadlock**:
1. ACL blocks API requests → returns 403 Forbidden
2. Global cleanup can't run → API blocked
3. Auth setup fails → tests skip
4. Manual intervention required to reset volumes
The security helpers solve this by using Playwright's `test.afterAll()` fixture to guarantee cleanup even when tests fail.
## Usage
### Capture and Restore Pattern
```typescript
import { captureSecurityState, restoreSecurityState } from '../utils/security-helpers';
import { request } from '@playwright/test';
let originalState;
test.beforeAll(async ({ request: reqFixture }) => {
originalState = await captureSecurityState(reqFixture);
});
test.afterAll(async () => {
const cleanup = await request.newContext({ baseURL: '...' });
try {
await restoreSecurityState(cleanup, originalState);
} finally {
await cleanup.dispose();
}
});
```
### Toggle Security Module
```typescript
import { setSecurityModuleEnabled } from '../utils/security-helpers';
await setSecurityModuleEnabled(request, 'acl', true);
await setSecurityModuleEnabled(request, 'waf', false);
```
### With Guaranteed Cleanup
```typescript
import { withSecurityEnabled } from '../utils/security-helpers';
test.describe('ACL Tests', () => {
let cleanup: () => Promise<void>;
test.beforeAll(async ({ request }) => {
cleanup = await withSecurityEnabled(request, { acl: true, cerberus: true });
});
test.afterAll(async () => {
await cleanup();
});
test('should enforce ACL', async ({ page }) => {
// ACL is now enabled, test enforcement
});
});
```
## Functions
| Function | Purpose |
|----------|---------|
| `getSecurityStatus` | Fetch current security module states |
| `setSecurityModuleEnabled` | Toggle a specific module on/off |
| `captureSecurityState` | Snapshot all module states |
| `restoreSecurityState` | Restore to captured snapshot |
| `withSecurityEnabled` | Enable modules with guaranteed cleanup |
| `disableAllSecurityModules` | Emergency reset |
## API Endpoints Used
| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/v1/security/status` | GET | Returns current state of all security modules |
| `/api/v1/settings` | POST | Toggle settings with `{ key: "...", value: "true/false" }` |
## Settings Keys
| Key | Values | Description |
|-----|--------|-------------|
| `security.acl.enabled` | `"true"` / `"false"` | Toggle ACL enforcement |
| `security.waf.enabled` | `"true"` / `"false"` | Toggle WAF enforcement |
| `security.rate_limit.enabled` | `"true"` / `"false"` | Toggle Rate Limiting |
| `security.crowdsec.enabled` | `"true"` / `"false"` | Toggle CrowdSec |
| `feature.cerberus.enabled` | `"true"` / `"false"` | Master toggle for all security |
## Best Practices
1. **Always use `test.afterAll`** for cleanup - it runs even when tests fail
2. **Capture state before modifying** - enables precise restoration
3. **Enable Cerberus first** - it's the master toggle for all security modules
4. **Don't toggle back in individual tests** - let `afterAll` handle cleanup
5. **Use `withSecurityEnabled`** for the cleanest pattern
## Troubleshooting
### ACL Deadlock Recovery
If the test suite is stuck due to ACL deadlock:
```bash
# Check current security status
curl http://localhost:8080/api/v1/security/status
# Manually disable ACL (requires auth)
curl -X POST http://localhost:8080/api/v1/settings \
-H "Content-Type: application/json" \
-d '{"key": "security.acl.enabled", "value": "false"}'
```
### Complete Reset
Use `disableAllSecurityModules` in global setup to ensure clean slate:
```typescript
import { disableAllSecurityModules } from './utils/security-helpers';
async function globalSetup() {
const context = await request.newContext({ baseURL: '...' });
await disableAllSecurityModules(context);
await context.dispose();
}
```