eec8c28fb3
Go Benchmark / Performance Regression Check (push) Has been cancelled
Cerberus Integration / Cerberus Security Stack Integration (push) Has been cancelled
Upload Coverage to Codecov / Backend Codecov Upload (push) Has been cancelled
Upload Coverage to Codecov / Frontend Codecov Upload (push) Has been cancelled
CodeQL - Analyze / CodeQL analysis (go) (push) Has been cancelled
CodeQL - Analyze / CodeQL analysis (javascript-typescript) (push) Has been cancelled
CrowdSec Integration / CrowdSec Bouncer Integration (push) Has been cancelled
Docker Build, Publish & Test / build-and-push (push) Has been cancelled
Quality Checks / Auth Route Protection Contract (push) Has been cancelled
Quality Checks / Codecov Trigger/Comment Parity Guard (push) Has been cancelled
Quality Checks / Backend (Go) (push) Has been cancelled
Quality Checks / Frontend (React) (push) Has been cancelled
Rate Limit integration / Rate Limiting Integration (push) Has been cancelled
Security Scan (PR) / Trivy Binary Scan (push) Has been cancelled
Supply Chain Verification (PR) / Verify Supply Chain (push) Has been cancelled
WAF integration / Coraza WAF Integration (push) Has been cancelled
Docker Build, Publish & Test / Security Scan PR Image (push) Has been cancelled
Repo Health Check / Repo health (push) Has been cancelled
History Rewrite Dry-Run / Dry-run preview for history rewrite (push) Has been cancelled
Prune Renovate Branches / prune (push) Has been cancelled
Renovate / renovate (push) Has been cancelled
Nightly Build & Package / sync-development-to-nightly (push) Has been cancelled
Nightly Build & Package / Trigger Nightly Validation Workflows (push) Has been cancelled
Nightly Build & Package / build-and-push-nightly (push) Has been cancelled
Nightly Build & Package / test-nightly-image (push) Has been cancelled
Nightly Build & Package / verify-nightly-supply-chain (push) Has been cancelled
Update GeoLite2 Checksum / update-checksum (push) Has been cancelled
Container Registry Prune / prune-ghcr (push) Has been cancelled
Container Registry Prune / prune-dockerhub (push) Has been cancelled
Container Registry Prune / summarize (push) Has been cancelled
Supply Chain Verification / Verify SBOM (push) Has been cancelled
Supply Chain Verification / Verify Release Artifacts (push) Has been cancelled
Supply Chain Verification / Verify Docker Image Supply Chain (push) Has been cancelled
Monitor Caddy Major Release / check-caddy-major (push) Has been cancelled
Weekly Nightly to Main Promotion / Verify Nightly Branch Health (push) Has been cancelled
Weekly Nightly to Main Promotion / Create Promotion PR (push) Has been cancelled
Weekly Nightly to Main Promotion / Trigger Missing Required Checks (push) Has been cancelled
Weekly Nightly to Main Promotion / Notify on Failure (push) Has been cancelled
Weekly Nightly to Main Promotion / Workflow Summary (push) Has been cancelled
Weekly Security Rebuild / Security Rebuild & Scan (push) Has been cancelled
254 lines
8.5 KiB
TypeScript
Executable File
254 lines
8.5 KiB
TypeScript
Executable File
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
|
|
import client from '../client'
|
|
import * as crowdsec from '../crowdsec'
|
|
|
|
vi.mock('../client')
|
|
|
|
describe('crowdsec API', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('startCrowdsec', () => {
|
|
it('should call POST /admin/crowdsec/start', async () => {
|
|
const mockData = { success: true }
|
|
vi.mocked(client.post).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.startCrowdsec()
|
|
|
|
expect(client.post).toHaveBeenCalledWith('/admin/crowdsec/start')
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('stopCrowdsec', () => {
|
|
it('should call POST /admin/crowdsec/stop', async () => {
|
|
const mockData = { success: true }
|
|
vi.mocked(client.post).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.stopCrowdsec()
|
|
|
|
expect(client.post).toHaveBeenCalledWith('/admin/crowdsec/stop')
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('statusCrowdsec', () => {
|
|
it('should call GET /admin/crowdsec/status', async () => {
|
|
const mockData = { running: true, pid: 1234 }
|
|
vi.mocked(client.get).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.statusCrowdsec()
|
|
|
|
expect(client.get).toHaveBeenCalledWith('/admin/crowdsec/status')
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('importCrowdsecConfig', () => {
|
|
it('should call POST /admin/crowdsec/import with FormData', async () => {
|
|
const mockFile = new File(['content'], 'config.tar.gz', { type: 'application/gzip' })
|
|
const mockData = { success: true }
|
|
vi.mocked(client.post).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.importCrowdsecConfig(mockFile)
|
|
|
|
expect(client.post).toHaveBeenCalledWith(
|
|
'/admin/crowdsec/import',
|
|
expect.any(FormData),
|
|
{ headers: { 'Content-Type': 'multipart/form-data' } }
|
|
)
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('exportCrowdsecConfig', () => {
|
|
it('should call GET /admin/crowdsec/export with blob responseType', async () => {
|
|
const mockBlob = new Blob(['data'], { type: 'application/gzip' })
|
|
vi.mocked(client.get).mockResolvedValue({ data: mockBlob })
|
|
|
|
const result = await crowdsec.exportCrowdsecConfig()
|
|
|
|
expect(client.get).toHaveBeenCalledWith('/admin/crowdsec/export', { responseType: 'blob' })
|
|
expect(result).toEqual(mockBlob)
|
|
})
|
|
})
|
|
|
|
describe('listCrowdsecFiles', () => {
|
|
it('should call GET /admin/crowdsec/files', async () => {
|
|
const mockData = { files: ['file1.yaml', 'file2.yaml'] }
|
|
vi.mocked(client.get).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.listCrowdsecFiles()
|
|
|
|
expect(client.get).toHaveBeenCalledWith('/admin/crowdsec/files')
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('readCrowdsecFile', () => {
|
|
it('should call GET /admin/crowdsec/file with encoded path', async () => {
|
|
const mockData = { content: 'file content' }
|
|
const path = '/etc/crowdsec/file.yaml'
|
|
vi.mocked(client.get).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.readCrowdsecFile(path)
|
|
|
|
expect(client.get).toHaveBeenCalledWith(
|
|
`/admin/crowdsec/file?path=${encodeURIComponent(path)}`
|
|
)
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('writeCrowdsecFile', () => {
|
|
it('should call POST /admin/crowdsec/file with path and content', async () => {
|
|
const mockData = { success: true }
|
|
const path = '/etc/crowdsec/file.yaml'
|
|
const content = 'new content'
|
|
vi.mocked(client.post).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.writeCrowdsecFile(path, content)
|
|
|
|
expect(client.post).toHaveBeenCalledWith('/admin/crowdsec/file', { path, content })
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('listCrowdsecDecisions', () => {
|
|
it('should call GET /admin/crowdsec/decisions and return data', async () => {
|
|
const mockData = {
|
|
decisions: [
|
|
{ id: '1', ip: '1.2.3.4', reason: 'bot', duration: '24h', created_at: '2024-01-01T00:00:00Z', source: 'crowdsec' },
|
|
],
|
|
}
|
|
vi.mocked(client.get).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.listCrowdsecDecisions()
|
|
|
|
expect(client.get).toHaveBeenCalledWith('/admin/crowdsec/decisions')
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('banIP', () => {
|
|
it('should call POST /admin/crowdsec/ban with ip, duration, and reason', async () => {
|
|
vi.mocked(client.post).mockResolvedValue({})
|
|
|
|
await crowdsec.banIP('1.2.3.4', '24h', 'manual ban')
|
|
|
|
expect(client.post).toHaveBeenCalledWith('/admin/crowdsec/ban', {
|
|
ip: '1.2.3.4',
|
|
duration: '24h',
|
|
reason: 'manual ban',
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('unbanIP', () => {
|
|
it('should call DELETE /admin/crowdsec/ban/{encoded ip}', async () => {
|
|
vi.mocked(client.delete).mockResolvedValue({})
|
|
|
|
await crowdsec.unbanIP('1.2.3.4')
|
|
|
|
expect(client.delete).toHaveBeenCalledWith('/admin/crowdsec/ban/1.2.3.4')
|
|
})
|
|
|
|
it('should URL-encode special characters in the IP', async () => {
|
|
vi.mocked(client.delete).mockResolvedValue({})
|
|
|
|
await crowdsec.unbanIP('::1')
|
|
|
|
expect(client.delete).toHaveBeenCalledWith('/admin/crowdsec/ban/%3A%3A1')
|
|
})
|
|
})
|
|
|
|
describe('getCrowdsecKeyStatus', () => {
|
|
it('should call GET /admin/crowdsec/key-status and return data', async () => {
|
|
const mockData = {
|
|
key_source: 'file' as const,
|
|
env_key_rejected: false,
|
|
current_key_preview: 'abc***xyz',
|
|
message: 'Key loaded from file',
|
|
}
|
|
vi.mocked(client.get).mockResolvedValue({ data: mockData })
|
|
|
|
const result = await crowdsec.getCrowdsecKeyStatus()
|
|
|
|
expect(client.get).toHaveBeenCalledWith('/admin/crowdsec/key-status')
|
|
expect(result).toEqual(mockData)
|
|
})
|
|
})
|
|
|
|
describe('listWhitelists', () => {
|
|
it('should call GET /admin/crowdsec/whitelist and return the whitelist array', async () => {
|
|
const mockWhitelist = [
|
|
{
|
|
uuid: 'uuid-1',
|
|
ip_or_cidr: '192.168.1.1',
|
|
reason: 'Home',
|
|
created_at: '2024-01-01T00:00:00Z',
|
|
updated_at: '2024-01-01T00:00:00Z',
|
|
},
|
|
]
|
|
vi.mocked(client.get).mockResolvedValue({ data: { whitelist: mockWhitelist } })
|
|
|
|
const result = await crowdsec.listWhitelists()
|
|
|
|
expect(client.get).toHaveBeenCalledWith('/admin/crowdsec/whitelist')
|
|
expect(result).toEqual(mockWhitelist)
|
|
})
|
|
})
|
|
|
|
describe('addWhitelist', () => {
|
|
it('should call POST /admin/crowdsec/whitelist and return the created entry', async () => {
|
|
const payload = { ip_or_cidr: '192.168.1.1', reason: 'Home' }
|
|
const mockEntry = {
|
|
uuid: 'uuid-1',
|
|
ip_or_cidr: '192.168.1.1',
|
|
reason: 'Home',
|
|
created_at: '2024-01-01T00:00:00Z',
|
|
updated_at: '2024-01-01T00:00:00Z',
|
|
}
|
|
vi.mocked(client.post).mockResolvedValue({ data: mockEntry })
|
|
|
|
const result = await crowdsec.addWhitelist(payload)
|
|
|
|
expect(client.post).toHaveBeenCalledWith('/admin/crowdsec/whitelist', payload)
|
|
expect(result).toEqual(mockEntry)
|
|
})
|
|
})
|
|
|
|
describe('deleteWhitelist', () => {
|
|
it('should call DELETE /admin/crowdsec/whitelist/{uuid}', async () => {
|
|
vi.mocked(client.delete).mockResolvedValue({})
|
|
|
|
await crowdsec.deleteWhitelist('uuid-1')
|
|
|
|
expect(client.delete).toHaveBeenCalledWith('/admin/crowdsec/whitelist/uuid-1')
|
|
})
|
|
})
|
|
|
|
describe('default export', () => {
|
|
it('should export all functions', () => {
|
|
expect(crowdsec.default).toHaveProperty('startCrowdsec')
|
|
expect(crowdsec.default).toHaveProperty('stopCrowdsec')
|
|
expect(crowdsec.default).toHaveProperty('statusCrowdsec')
|
|
expect(crowdsec.default).toHaveProperty('importCrowdsecConfig')
|
|
expect(crowdsec.default).toHaveProperty('exportCrowdsecConfig')
|
|
expect(crowdsec.default).toHaveProperty('listCrowdsecFiles')
|
|
expect(crowdsec.default).toHaveProperty('readCrowdsecFile')
|
|
expect(crowdsec.default).toHaveProperty('writeCrowdsecFile')
|
|
expect(crowdsec.default).toHaveProperty('listCrowdsecDecisions')
|
|
expect(crowdsec.default).toHaveProperty('banIP')
|
|
expect(crowdsec.default).toHaveProperty('unbanIP')
|
|
expect(crowdsec.default).toHaveProperty('getCrowdsecKeyStatus')
|
|
expect(crowdsec.default).toHaveProperty('listWhitelists')
|
|
expect(crowdsec.default).toHaveProperty('addWhitelist')
|
|
expect(crowdsec.default).toHaveProperty('deleteWhitelist')
|
|
})
|
|
})
|
|
|
|
})
|