Files
wild-central/web/src/services/api/networking.ts

286 lines
6.5 KiB
TypeScript

import { apiClient } from './client';
// Services
export interface RegisteredService {
domain: string;
source: string;
subdomains: boolean;
backend: {
address: string;
type: string;
health?: string;
};
public: boolean;
tls?: string;
}
export const servicesApi = {
async list(): Promise<{ services: RegisteredService[] }> {
return apiClient.get('/api/v1/services');
},
async register(svc: { domain: string; backend: { address: string; type: string; health?: string }; public?: boolean; subdomains?: boolean; source?: string }): Promise<{ message: string; service: RegisteredService }> {
return apiClient.post('/api/v1/services', svc);
},
async deregister(domain: string): Promise<{ message: string }> {
return apiClient.delete(`/api/v1/services/${domain}`);
},
};
// HAProxy
export interface HaproxyInstanceRoute {
domain: string;
backendIP: string;
}
export interface HaproxyStatus {
status: string;
pid?: number;
configFile?: string;
lastRestart?: string;
routes?: HaproxyInstanceRoute[];
}
export interface HaproxyGenerateResult {
message: string;
config?: string;
routes?: HaproxyInstanceRoute[];
customRoutes?: number;
}
export const haproxyApi = {
async getStatus(): Promise<HaproxyStatus> {
return apiClient.get('/api/v1/haproxy/status');
},
async getConfig(): Promise<{ content: string; config_file: string }> {
return apiClient.get('/api/v1/haproxy/config');
},
async generate(): Promise<HaproxyGenerateResult> {
return apiClient.post('/api/v1/haproxy/generate');
},
async restart(): Promise<{ message: string }> {
return apiClient.post('/api/v1/haproxy/restart');
},
async getStats(): Promise<{ backends: BackendStat[] }> {
return apiClient.get('/api/v1/haproxy/stats');
},
};
export interface BackendStat {
name: string;
status: string;
activeConns: number;
rate: number;
peakRate: number;
totalConns: number;
errors: number;
}
// DDNS
export interface DdnsRecordStatus {
name: string;
ip?: string;
ok: boolean;
error?: string;
}
export interface DdnsStatus {
enabled: boolean;
currentIP?: string;
lastChecked?: string;
lastUpdated?: string;
lastError?: string;
records?: DdnsRecordStatus[];
message?: string;
}
export const ddnsApi = {
async getStatus(): Promise<DdnsStatus> {
return apiClient.get('/api/v1/ddns/status');
},
async trigger(): Promise<{ message: string }> {
return apiClient.post('/api/v1/ddns/trigger');
},
};
// DHCP
export interface DhcpLease {
expiry: string;
mac: string;
ip: string;
hostname?: string;
}
export interface DhcpStaticLease {
mac: string;
ip: string;
hostname?: string;
}
export const dhcpApi = {
async getLeases(): Promise<{ leases: DhcpLease[] }> {
return apiClient.get('/api/v1/dnsmasq/dhcp/leases');
},
async addStatic(lease: DhcpStaticLease): Promise<{ message: string }> {
return apiClient.post('/api/v1/dnsmasq/dhcp/static', lease);
},
async deleteStatic(mac: string): Promise<{ message: string }> {
return apiClient.delete(`/api/v1/dnsmasq/dhcp/static/${encodeURIComponent(mac)}`);
},
};
// nftables
export interface NftablesStatus {
rulesFile: string;
rules: string;
}
export interface NetworkInterface {
name: string;
addresses: string[];
}
export const nftablesApi = {
async getStatus(): Promise<NftablesStatus> {
return apiClient.get('/api/v1/nftables/status');
},
async apply(): Promise<{ message: string }> {
return apiClient.post('/api/v1/nftables/apply');
},
async getInterfaces(): Promise<{ interfaces: NetworkInterface[] }> {
return apiClient.get('/api/v1/nftables/interfaces');
},
};
// CrowdSec LAPI
export interface CrowdSecMachine {
machineId: string;
isValidated: boolean;
last_push?: string;
last_heartbeat?: string;
ipAddress?: string;
version?: string;
}
export interface CrowdSecBanSummary {
total: number;
byReason: Record<string, number>;
}
export interface CrowdSecBouncer {
name: string;
revoked: boolean;
ipAddress?: string;
type?: string;
version?: string;
lastPull?: string;
}
export interface CrowdSecDecision {
id: number;
value: string;
type: string;
scope: string;
reason: string;
origin: string;
duration?: string;
}
export interface CrowdSecAlert {
id: number;
scenario: string;
message: string;
createdAt: string;
machineId?: string;
sourceIP?: string;
country?: string;
asName?: string;
}
export interface AddDecisionRequest {
ip: string;
type: 'ban' | 'allow';
reason?: string;
duration?: string;
}
export interface CrowdSecStatus {
active: boolean;
firewallBouncer: boolean;
machines: CrowdSecMachine[];
bouncers: CrowdSecBouncer[];
}
export const crowdSecApi = {
async getStatus(): Promise<CrowdSecStatus> {
return apiClient.get('/api/v1/crowdsec/status');
},
async getDecisions(): Promise<{ decisions: CrowdSecDecision[] }> {
return apiClient.get('/api/v1/crowdsec/decisions');
},
async deleteDecision(id: number): Promise<{ message: string }> {
return apiClient.delete(`/api/v1/crowdsec/decisions/${id}`);
},
async getMachines(): Promise<{ machines: CrowdSecMachine[] }> {
return apiClient.get('/api/v1/crowdsec/machines');
},
async deleteMachine(name: string): Promise<{ message: string }> {
return apiClient.delete(`/api/v1/crowdsec/machines/${encodeURIComponent(name)}`);
},
async getBouncers(): Promise<{ bouncers: CrowdSecBouncer[] }> {
return apiClient.get('/api/v1/crowdsec/bouncers');
},
async deleteBouncer(name: string): Promise<{ message: string }> {
return apiClient.delete(`/api/v1/crowdsec/bouncers/${encodeURIComponent(name)}`);
},
async getSummary(): Promise<CrowdSecBanSummary> {
return apiClient.get('/api/v1/crowdsec/summary');
},
async getAlerts(limit = 50): Promise<{ alerts: CrowdSecAlert[] }> {
return apiClient.get(`/api/v1/crowdsec/alerts?limit=${limit}`);
},
async addDecision(req: AddDecisionRequest): Promise<{ message: string }> {
return apiClient.post('/api/v1/crowdsec/decisions', req);
},
async deleteDecisionByIP(ip: string): Promise<{ message: string }> {
return apiClient.delete(`/api/v1/crowdsec/decisions/ip/${encodeURIComponent(ip)}`);
},
};
// Global Secrets
export const secretsApi = {
async get(raw?: boolean): Promise<Record<string, unknown>> {
const path = raw ? '/api/v1/secrets?raw=true' : '/api/v1/secrets';
return apiClient.get(path);
},
async update(values: Record<string, unknown>): Promise<{ message: string }> {
return apiClient.put('/api/v1/secrets', values);
},
};