feat: harden firewall policies telemetry and operations
quality / changes (push) Successful in 7s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 30s
quality / web (push) Successful in 1m3s
quality / api (push) Successful in 1m15s
quality / linux-agent-smoke (push) Failing after 27s
quality / docker-check (push) Failing after 2m28s
CD / quality (push) Failing after 5m52s
CD / publish (push) Skipped
quality / changes (push) Successful in 7s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 30s
quality / web (push) Successful in 1m3s
quality / api (push) Successful in 1m15s
quality / linux-agent-smoke (push) Failing after 27s
quality / docker-check (push) Failing after 2m28s
CD / quality (push) Failing after 5m52s
CD / publish (push) Skipped
Implement reliable agent apply, telemetry v2, analytics retention, guarded rollouts, enrollment, labels and webhooks. Improve ReUI frontend data safety and bounded list loading, and add Docker smoke, recovery and resource checks. Document local verification and pending native acceptance.
This commit is contained in:
1 parent
aa475848fd
commit
9fa6269174
242 files changed
+19872
-3057
No files matched your search
+214
-39
@@ -12,6 +12,98 @@ servers:
|
||||
description: Local API
|
||||
security: []
|
||||
paths:
|
||||
/v1/agent/credentials:
|
||||
$ref: './openapi.schemas.json#/paths/~1v1~1agent~1credentials'
|
||||
/v1/agent/token-rotation:
|
||||
$ref: './openapi.schemas.json#/paths/~1v1~1agent~1token-rotation'
|
||||
/api/v1/agents/{id}/token-rotation:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1agents~1{id}~1token-rotation'
|
||||
/api/v1/policies/snapshots:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1snapshots'
|
||||
/api/v1/policies/snapshots/{id}:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1snapshots~1{id}'
|
||||
/api/v1/policies/snapshots/{id}/diff:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1snapshots~1{id}~1diff'
|
||||
/api/v1/policies/rollouts:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1rollouts'
|
||||
/api/v1/policies/rollouts/{id}:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1rollouts~1{id}'
|
||||
/api/v1/policies/rollouts/{id}/confirm:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1rollouts~1{id}~1confirm'
|
||||
/api/v1/policies/rollouts/{id}/rollback:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1rollouts~1{id}~1rollback'
|
||||
/api/v1/agents/{id}/policy-pin/release:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1agents~1{id}~1policy-pin~1release'
|
||||
/api/v1/agent-labels:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1agent-labels'
|
||||
/api/v1/agent-labels/{id}:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1agent-labels~1{id}'
|
||||
/api/v1/agents/{id}/labels:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1agents~1{id}~1labels'
|
||||
/api/v1/agent-labels/preview-assignment:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1agent-labels~1preview-assignment'
|
||||
/api/v1/agent-labels/assign-policy-sets:
|
||||
$ref: './openapi.schemas.json#/paths/~1api~1v1~1agent-labels~1assign-policy-sets'
|
||||
/api/v1/webhooks:
|
||||
get:
|
||||
summary: List webhook endpoints and bounded queue counts (settings admin)
|
||||
tags: [ops]
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Endpoint metadata without secrets, configured flag, limits and queue counts
|
||||
'403':
|
||||
description: Settings administrator required
|
||||
post:
|
||||
summary: Create webhook endpoint (at most 20, settings admin)
|
||||
tags: [ops]
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: './openapi.schemas.json#/components/schemas/CreateWebhook'
|
||||
responses:
|
||||
'201':
|
||||
description: Endpoint metadata with secret_configured; secret never returned
|
||||
'503':
|
||||
description: EVOFW_SECRET_KEY missing or shorter than 32 characters
|
||||
/api/v1/webhooks/{id}:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Id'
|
||||
patch:
|
||||
summary: Update webhook endpoint; changed destination, signing secret or events cancel pending delivery
|
||||
tags: [ops]
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: './openapi.schemas.json#/components/schemas/PatchWebhook'
|
||||
responses:
|
||||
'200':
|
||||
description: Updated endpoint metadata without secret
|
||||
'503':
|
||||
description: EVOFW_SECRET_KEY unavailable
|
||||
delete:
|
||||
summary: Delete endpoint and cancel queued deliveries (settings admin)
|
||||
tags: [ops]
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Deleted
|
||||
/api/v1/webhooks/{id}/deliveries:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Id'
|
||||
get:
|
||||
summary: Last 100 pending or terminal deliveries, with sanitized error codes (settings admin)
|
||||
tags: [ops]
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Items and total count, excluding payload bytes and signing secrets
|
||||
/health:
|
||||
get:
|
||||
summary: Liveness
|
||||
@@ -20,6 +112,42 @@ paths:
|
||||
'200':
|
||||
description: OK
|
||||
|
||||
/ready:
|
||||
get:
|
||||
summary: SQLite-backed readiness
|
||||
tags: [system]
|
||||
responses:
|
||||
'200':
|
||||
description: Ready
|
||||
'503':
|
||||
description: Database unavailable
|
||||
|
||||
/api/v1/diagnostics:
|
||||
get:
|
||||
summary: Bounded runtime and delivery queue diagnostics
|
||||
description: Requires fw:settings:admin. Returns DB/WAL sizes, filesystem capacity, audit outbox and limiter counters, RSS/heap and uptime. Memory databases and unavailable filesystem metrics return null; no credentials or queued payloads are returned.
|
||||
tags: [ops]
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Runtime diagnostics
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [database, audit_outbox, limiter, process]
|
||||
properties:
|
||||
database: { type: object, additionalProperties: true }
|
||||
audit_outbox: { type: object, additionalProperties: true }
|
||||
limiter: { type: object, additionalProperties: true }
|
||||
process: { type: object, additionalProperties: true }
|
||||
'401':
|
||||
description: Authentication required
|
||||
'403':
|
||||
description: Missing settings administrator permission
|
||||
'429':
|
||||
description: Authenticated user request limit exceeded
|
||||
|
||||
/api/v1/dashboard:
|
||||
get:
|
||||
summary: Dashboard KPI
|
||||
@@ -29,6 +157,37 @@ paths:
|
||||
'200':
|
||||
description: Stats
|
||||
|
||||
/api/v1/ui/summary:
|
||||
get:
|
||||
summary: Permission-filtered navigation and dashboard summary
|
||||
tags: [ops]
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: Only sections visible to the authenticated user are included
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: './openapi.schemas.json#/components/schemas/UiSummary'
|
||||
|
||||
/api/v1/stats/timeseries:
|
||||
get:
|
||||
summary: Coverage-aware fleet or agent packet series
|
||||
tags: [ops]
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: from, in: query, schema: { type: string, format: date-time } }
|
||||
- { name: to, in: query, schema: { type: string, format: date-time } }
|
||||
- { name: resolution, in: query, schema: { type: string, enum: [1m, 1h, 1d] } }
|
||||
- { name: agent_ids, in: query, description: Comma-separated agent IDs (at most 100), schema: { type: string } }
|
||||
responses:
|
||||
'200':
|
||||
description: At most 1440 points and 100 agents; unknown counters are null
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: './openapi.schemas.json#/components/schemas/TimeseriesResponse'
|
||||
|
||||
/api/v1/install-context:
|
||||
get:
|
||||
summary: Public install base URL + enroll seed hint
|
||||
@@ -229,6 +388,10 @@ paths:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Limit'
|
||||
- $ref: '#/components/parameters/Offset'
|
||||
- name: view
|
||||
in: query
|
||||
description: Select summary to omit expanded source configuration and entries
|
||||
schema: { type: string, enum: [summary] }
|
||||
responses:
|
||||
'200':
|
||||
description: Lists (items + total)
|
||||
@@ -242,14 +405,30 @@ paths:
|
||||
|
||||
/api/v1/lists/{id}:
|
||||
get:
|
||||
summary: List detail + entries
|
||||
summary: List detail; use view=page for bounded entries and whole-list filtering
|
||||
tags: [lists]
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Id'
|
||||
- { name: view, in: query, schema: { type: string, enum: [page] } }
|
||||
- { name: limit, in: query, description: Requires view=page, schema: { type: integer, minimum: 1, maximum: 200, default: 100 } }
|
||||
- { name: offset, in: query, description: Requires view=page, schema: { type: integer, minimum: 0, maximum: 10000000, default: 0 } }
|
||||
- { name: q, in: query, description: Whole-list text search before pagination; requires view=page, schema: { type: string, maxLength: 256 } }
|
||||
- name: filters
|
||||
in: query
|
||||
description: >-
|
||||
JSON array (at most 10 filters), evaluated over the whole list before paging.
|
||||
Each filter has field value or kind, operator is/is_not/is_any_of/is_not_any_of/
|
||||
contains/not_contains/starts_with/ends_with/empty/not_empty and values array
|
||||
(at most 20 strings of at most 256 characters). Requires view=page.
|
||||
schema: { type: string }
|
||||
responses:
|
||||
'200':
|
||||
description: Detail
|
||||
description: >-
|
||||
Default retains full legacy detail. view=page returns metadata plus total,
|
||||
limit, offset, entries and items (at most limit). Each item has kind,
|
||||
value, list_name, resolved_count, resolved_cidrs and resolved_truncated;
|
||||
nested resolved previews are bounded. Invalid page/filter input returns 400.
|
||||
delete:
|
||||
summary: Delete list
|
||||
tags: [lists]
|
||||
@@ -278,15 +457,23 @@ paths:
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Id'
|
||||
- name: return
|
||||
in: query
|
||||
schema: { type: string, enum: [summary] }
|
||||
description: Opt in to bounded count/content_hash/changed response instead of expanded detail
|
||||
responses:
|
||||
'200':
|
||||
description: Updated
|
||||
description: Updated; return=summary uses ListImportSummary from generated contracts
|
||||
delete:
|
||||
summary: Delete entry
|
||||
tags: [lists]
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Id'
|
||||
- name: return
|
||||
in: query
|
||||
schema: { type: string, enum: [summary] }
|
||||
description: Opt in to bounded count/content_hash/changed response instead of expanded detail
|
||||
responses:
|
||||
'200':
|
||||
description: Deleted
|
||||
@@ -748,11 +935,28 @@ paths:
|
||||
|
||||
/v1/agent/enroll:
|
||||
post:
|
||||
summary: Enroll agent (X-EvoFW-Seed)
|
||||
summary: Enroll with single-use install-link credential (legacy global seed refused)
|
||||
tags: [agent-public]
|
||||
parameters:
|
||||
- name: X-EvoFW-Enrollment-Credential
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: './openapi.schemas.json#/components/schemas/EnrollWithCredential'
|
||||
responses:
|
||||
'200':
|
||||
description: Exact consumed enrollment retry; same client; no-store
|
||||
'201':
|
||||
description: Pending agent
|
||||
description: Newly enrolled pending agent; no-store
|
||||
'401':
|
||||
description: Scoped enrollment credential required
|
||||
'409':
|
||||
description: Credential already consumed with different enrollment
|
||||
|
||||
/v1/agent/policy:
|
||||
get:
|
||||
@@ -762,6 +966,10 @@ paths:
|
||||
responses:
|
||||
'200':
|
||||
description: Policy (includes script_sha256 for Linux self-update; not part of policy.hash)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: './openapi.schemas.json#/components/schemas/AgentPolicy'
|
||||
|
||||
/v1/agent/policy.rsc:
|
||||
get:
|
||||
@@ -791,40 +999,7 @@ paths:
|
||||
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'
|
||||
$ref: './openapi.schemas.json#/components/schemas/ApplyReport'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
|
||||
Reference in new issue
Block a user