Files
EvoFirewall/docs/openapi.yaml
T
Denozordec 43f5ac2525
Build and Push EvoFirewall Docker Image / build-and-push (push) Successful in 1m43s
Build and Push EvoFirewall Docker Image / create-release (push) Skipped
feat(api, web): implement port ACL and host firewall snapshot features
- Added support for managing desired L4 port ACL rules for Linux agents, allowing for open/close actions on specified ports.
- Introduced a new endpoint for CRUD operations on port rules, enhancing the API's capabilities for agent management.
- Implemented functionality to collect and report host firewall snapshots, capturing observed rules and listeners for better monitoring.
- Updated the agent detail view to include tabs for managing port ACLs and viewing host firewall data, improving user experience.
- Enhanced documentation to reflect the new features and API changes, ensuring clarity for users and developers.

These changes significantly improve the management and visibility of firewall rules and port access control for agents.
2026-08-11 15:08:00 +07:00

887 lines
24 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.0.3
info:
title: EvoFirewall API
version: 0.2.0
description: |
Centralized firewall control plane.
**HTTP SoT:** this OpenAPI document.
**Runtime validation:** Zod schemas in `@evofw/shared` (authoritative for request bodies).
servers:
- url: http://localhost:8080
description: Local API
security: []
paths:
/health:
get:
summary: Liveness
tags: [system]
responses:
'200':
description: OK
/api/v1/dashboard:
get:
summary: Dashboard KPI
tags: [ops]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Stats
/api/v1/install-context:
get:
summary: Public install base URL + enroll seed hint
tags: [ops]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Install context
/api/v1/install-links:
get:
summary: List install links
tags: [agents]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Links
post:
summary: Create install link + invited agent
tags: [agents]
security: [{ bearerAuth: [] }]
responses:
'201':
description: Created
/api/v1/install-links/{id}:
delete:
summary: Revoke install link
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Revoked
/api/v1/agents:
get:
summary: List agents
tags: [agents]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Agents
/api/v1/agents/{id}:
get:
summary: Get agent
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Agent
patch:
summary: Update agent
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Updated
delete:
summary: Delete agent
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Deleted
/api/v1/agents/{id}/approve:
post:
summary: Approve pending/invited agent
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Approved
/api/v1/agents/{id}/revoke:
post:
summary: Revoke agent
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Revoked
/api/v1/agents/{id}/preview:
get:
summary: Policy preview (truncated CIDRs)
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
- name: limit_cidrs
in: query
schema: { type: integer, default: 50, maximum: 5000 }
responses:
'200':
description: Preview
/api/v1/agents/{id}/policy-sets:
get:
summary: Assigned policy sets
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Sets
put:
summary: Replace assigned policy sets (order = sort)
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Updated
/api/v1/agents/{id}/overrides:
get:
summary: List IP overrides
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Overrides
post:
summary: Create override
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Created
/api/v1/agents/{id}/overrides/{overrideId}:
delete:
summary: Delete override
tags: [agents]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
- name: overrideId
in: path
required: true
schema: { type: string }
responses:
'200':
description: Deleted
/api/v1/lists:
get:
summary: List IP lists
tags: [lists]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Lists
post:
summary: Create IP list
tags: [lists]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Created
/api/v1/lists/{id}:
get:
summary: List detail + entries
tags: [lists]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Detail
delete:
summary: Delete list
tags: [lists]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Deleted
/api/v1/lists/{id}/refresh:
post:
summary: Refresh remote/json/evobgp list
tags: [lists]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Refreshed
/api/v1/lists/{id}/entries:
post:
summary: Add manual entries
tags: [lists]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Updated
delete:
summary: Delete entry
tags: [lists]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Deleted
/api/v1/policy-sets:
get:
summary: List policy sets
tags: [policies]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Sets
post:
summary: Create policy set
tags: [policies]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Created
/api/v1/policy-sets/{id}:
get:
summary: Get policy set
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Set
patch:
summary: Patch policy set
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Updated
delete:
summary: Delete policy set
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Deleted
/api/v1/policy-sets/{id}/rules:
get:
summary: Rules in set
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Rules
/api/v1/policy-sets/{id}/rules/reorder:
put:
summary: Reorder rules in a set
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Reordered
/api/v1/rules:
get:
summary: List policy rules (optional set filter)
tags: [policies]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Rules
post:
summary: Create policy rule
tags: [policies]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Created
/api/v1/rules/{id}:
patch:
summary: Patch rule
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Updated
delete:
summary: Delete rule
tags: [policies]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Deleted
/api/v1/stats/recent:
get:
summary: Recent apply samples
tags: [ops]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Samples
/api/v1/agents/{id}/stats:
get:
summary: Apply samples for one agent
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Samples
/api/v1/agents/{id}/stats/reset:
post:
summary: Reset packet totals, samples, and per-IP block stats
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Agent after reset
/api/v1/agents/{id}/blocked-ips:
get:
summary: Per-IP/CIDR drop counters (Linux nft/ipset; MikroTik HITS)
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Top blocked IPs by accumulated packets (+ optional top ports per IP on Linux)
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
required: [ip, packets, first_seen_at, last_seen_at]
properties:
ip: { type: string }
packets: { type: integer }
first_seen_at: { type: string, format: date-time }
last_seen_at: { type: string, format: date-time }
ports:
type: array
description: Top destination ports for this IP (Linux nft)
items:
type: object
required: [port, protocol, packets]
properties:
port: { type: integer, minimum: 1, maximum: 65535 }
protocol: { type: string, enum: [tcp, udp] }
packets: { type: integer }
/api/v1/agents/{id}/blocked-ports:
get:
summary: Aggregate destination ports hit by denied sources (Linux nft)
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Top ports by accumulated packets across all blocked IPs
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
type: object
required: [port, protocol, packets, last_seen_at]
properties:
port: { type: integer, minimum: 1, maximum: 65535 }
protocol: { type: string, enum: [tcp, udp] }
packets: { type: integer }
last_seen_at: { type: string, format: date-time }
/api/v1/agents/{id}/port-rules:
get:
summary: Desired Port ACL rules (Linux)
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Port ACL rules
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/AgentPortRule'
post:
summary: Create Port ACL rule
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateAgentPortRule'
responses:
'200':
description: Created rule
content:
application/json:
schema:
$ref: '#/components/schemas/AgentPortRule'
'400':
description: Validation / non-linux
/api/v1/agents/{id}/port-rules/import:
post:
summary: Import Port ACL from IP list or policy set sources
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [from, action, ports]
properties:
from: { type: string, enum: [list, set] }
list_id: { type: string }
set_id: { type: string }
action: { type: string, enum: [open, close] }
protocol: { type: string, enum: [tcp, udp, both], default: tcp }
ports:
type: array
minItems: 1
maxItems: 50
items:
type: object
required: [port_start]
properties:
port_start: { type: integer, minimum: 1, maximum: 65535 }
port_end: { type: integer, minimum: 1, maximum: 65535 }
enabled: { type: boolean, default: true }
comment: { type: string, maxLength: 500 }
responses:
'200':
description: Created rules
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/AgentPortRule'
/api/v1/agents/{id}/port-rules/{ruleId}:
patch:
summary: Update Port ACL rule
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
- name: ruleId
in: path
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAgentPortRule'
responses:
'200':
description: Updated rule
content:
application/json:
schema:
$ref: '#/components/schemas/AgentPortRule'
delete:
summary: Delete Port ACL rule
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
- name: ruleId
in: path
required: true
schema: { type: string }
responses:
'200':
description: Deleted
/api/v1/agents/{id}/host-firewall:
get:
summary: Last observed host firewall snapshot (Linux)
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Snapshot (empty if never reported)
content:
application/json:
schema:
type: object
properties:
collected_at:
type: string
format: date-time
nullable: true
raw_digest:
type: string
nullable: true
rules:
type: array
items:
$ref: '#/components/schemas/HostFwRule'
listeners:
type: array
items:
$ref: '#/components/schemas/HostListener'
/api/v1/integrations/evobgp/communities:
get:
summary: Proxy EvoBGP communities
tags: [integrations]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Communities
/api/v1/settings:
get:
summary: Settings map (token masked)
tags: [settings]
security: [{ bearerAuth: [] }]
responses:
'200':
description: Settings
put:
summary: Update whitelisted settings keys
tags: [settings]
security: [{ bearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties:
type: string
description: Keys — enroll_seed, evobgp_api_url, evobgp_api_token, agent_sync_interval_sec, show_quick_actions
responses:
'200':
description: Saved
'400':
description: Unknown key / validation
/api/v1/audit:
get:
summary: Local audit log
tags: [ops]
security: [{ bearerAuth: [] }]
parameters:
- name: action
in: query
schema: { type: string }
- name: severity
in: query
schema: { type: string, enum: [info, warning, critical] }
- name: limit
in: query
schema: { type: integer, default: 200 }
responses:
'200':
description: Audit entries
/v1/agent/install.sh:
get:
summary: Agent install script
tags: [agent-public]
responses:
'200':
description: Shell script
/v1/agent/enroll:
post:
summary: Enroll agent (X-EvoFW-Seed)
tags: [agent-public]
responses:
'201':
description: Pending agent
/v1/agent/policy:
get:
summary: Evaluated policy for agent
tags: [agent]
security: [{ agentToken: [] }]
responses:
'200':
description: Policy
/v1/agent/policy.rsc:
get:
summary: MikroTik RSC policy
tags: [agent]
security: [{ agentToken: [] }]
responses:
'200':
description: RSC text
/v1/agent/heartbeat:
post:
summary: Agent heartbeat
tags: [agent]
security: [{ agentToken: [] }]
responses:
'200':
description: OK
/v1/agent/apply-report:
post:
summary: Apply report + packet stats (+ optional ip_hits / port_hits / host_firewall)
tags: [agent]
security: [{ agentToken: [] }]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [status]
properties:
status: { type: string }
prefix_count: { type: integer }
packets_dropped: { type: integer }
packets_accepted: { type: integer }
kernel_method: { type: string }
error: { type: string }
source: { type: string }
ip_hits:
type: array
maxItems: 200
description: Linux per-element drop counters (packets > 0)
items:
type: object
required: [ip, packets]
properties:
ip: { type: string, maxLength: 64 }
packets: { type: integer, minimum: 0 }
port_hits:
type: array
maxItems: 500
description: Linux nft deny_port_hits (ip × proto × dport, packets > 0)
items:
type: object
required: [ip, port, protocol, packets]
properties:
ip: { type: string, maxLength: 64 }
port: { type: integer, minimum: 1, maximum: 65535 }
protocol: { type: string, enum: [tcp, udp] }
packets: { type: integer, minimum: 0 }
host_firewall:
$ref: '#/components/schemas/HostFirewallPayload'
responses:
'200':
description: OK
components:
parameters:
Id:
name: id
in: path
required: true
schema: { type: string }
schemas:
AgentPortRule:
type: object
required:
[
id,
agent_id,
action,
protocol,
port_start,
port_end,
src_kind,
enabled,
priority,
created_at,
updated_at,
]
properties:
id: { type: string }
agent_id: { type: string }
action: { type: string, enum: [open, close] }
protocol: { type: string, enum: [tcp, udp, both] }
port_start: { type: integer, minimum: 1, maximum: 65535 }
port_end: { type: integer, minimum: 1, maximum: 65535 }
src_kind: { type: string, enum: [all, cidr, list] }
src_cidr: { type: string, nullable: true }
list_id: { type: string, nullable: true }
list_name: { type: string, nullable: true }
enabled: { type: boolean }
comment: { type: string, nullable: true }
priority: { type: integer }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
CreateAgentPortRule:
type: object
required: [action, port_start]
properties:
action: { type: string, enum: [open, close] }
protocol: { type: string, enum: [tcp, udp, both], default: tcp }
port_start: { type: integer, minimum: 1, maximum: 65535 }
port_end: { type: integer, minimum: 1, maximum: 65535 }
src_kind: { type: string, enum: [all, cidr, list], default: all }
src_cidr: { type: string }
list_id: { type: string }
enabled: { type: boolean, default: true }
comment: { type: string, maxLength: 500 }
priority: { type: integer, default: 100 }
UpdateAgentPortRule:
type: object
properties:
action: { type: string, enum: [open, close] }
protocol: { type: string, enum: [tcp, udp, both] }
port_start: { type: integer, minimum: 1, maximum: 65535 }
port_end: { type: integer, minimum: 1, maximum: 65535 }
src_kind: { type: string, enum: [all, cidr, list] }
src_cidr: { type: string, nullable: true }
list_id: { type: string, nullable: true }
enabled: { type: boolean }
comment: { type: string, maxLength: 500, nullable: true }
priority: { type: integer }
HostFwRule:
type: object
required: [ownership, backend, raw]
properties:
ownership: { type: string, enum: [evofw, foreign] }
backend:
type: string
enum: [nft, iptables, ufw, firewalld, listener]
table: { type: string }
chain: { type: string }
action: { type: string }
protocol: { type: string }
dport: { type: string }
sport: { type: string }
saddr: { type: string }
daddr: { type: string }
comment: { type: string }
raw: { type: string, maxLength: 512 }
HostListener:
type: object
required: [protocol, port, address]
properties:
protocol: { type: string }
port: { type: integer, minimum: 0, maximum: 65535 }
address: { type: string }
process: { type: string }
HostFirewallPayload:
type: object
properties:
rules:
type: array
maxItems: 500
items:
$ref: '#/components/schemas/HostFwRule'
listeners:
type: array
maxItems: 200
items:
$ref: '#/components/schemas/HostListener'
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: Portal JWT (app id fw)
agentToken:
type: http
scheme: bearer
description: Agent enroll token
tags:
- name: system
- name: ops
- name: agents
- name: lists
- name: policies
- name: settings
- name: integrations
- name: agent-public
- name: agent