feat(policy): именованные наборы правил с DNS и M:N привязкой к агентам
Build and Push EvoFirewall Docker Image / build-and-push (push) Successful in 1m44s
Build and Push EvoFirewall Docker Image / create-release (push) Skipped

Правила живут в policy_sets; evaluate мержит назначенные наборы; источник list|CIDR|hostname с кэшем DNS.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-07-20 22:11:03 +07:00
co-authored by Cursor
parent cad05659b1
commit 0bed4367c7
18 changed files with 1524 additions and 312 deletions
+51 -8
View File
@@ -51,16 +51,29 @@ export const ipListSchema = z.object({
export const policyRuleSchema = z.object({
id: z.string(),
agent_id: z.string().nullable().optional(),
set_id: z.string(),
priority: z.number().int(),
action: policyActionSchema,
list_id: z.string().nullable().optional(),
cidr: z.string().nullable().optional(),
hostname: z.string().nullable().optional(),
resolved_count: z.number().int().optional(),
comment: z.string().nullable().optional(),
created_at: z.string(),
updated_at: z.string(),
})
export const policySetSchema = z.object({
id: z.string(),
name: z.string(),
description: z.string().nullable().optional(),
enabled: z.boolean(),
rules_count: z.number().int().optional(),
agents_count: z.number().int().optional(),
created_at: z.string(),
updated_at: z.string(),
})
export const ipOverrideSchema = z.object({
id: z.string(),
agent_id: z.string(),
@@ -77,13 +90,42 @@ export const createIpListBodySchema = z.object({
entries: z.array(z.string()).optional(),
})
export const createPolicyRuleBodySchema = z.object({
agent_id: z.string().nullable().optional(),
priority: z.number().int().min(1).max(10000),
action: policyActionSchema,
list_id: z.string().nullable().optional(),
cidr: z.string().nullable().optional(),
comment: z.string().nullable().optional(),
export const createPolicySetBodySchema = z.object({
name: z.string().min(1),
description: z.string().nullable().optional(),
enabled: z.boolean().optional().default(true),
})
export const patchPolicySetBodySchema = z.object({
name: z.string().min(1).optional(),
description: z.string().nullable().optional(),
enabled: z.boolean().optional(),
})
export const createPolicyRuleBodySchema = z
.object({
set_id: z.string().min(1),
priority: z.number().int().min(1).max(10000),
action: policyActionSchema,
list_id: z.string().nullable().optional(),
cidr: z.string().nullable().optional(),
hostname: z.string().nullable().optional(),
comment: z.string().nullable().optional(),
})
.superRefine((v, ctx) => {
const sources = [v.list_id, v.cidr, v.hostname].filter(
(x) => typeof x === 'string' && x.trim().length > 0,
)
if (sources.length !== 1) {
ctx.addIssue({
code: 'custom',
message: 'Укажите ровно один источник: list_id, cidr или hostname',
})
}
})
export const putAgentPolicySetsBodySchema = z.object({
set_ids: z.array(z.string()),
})
export const createOverrideBodySchema = z.object({
@@ -142,6 +184,7 @@ export const dashboardStatsSchema = z.object({
export type Agent = z.infer<typeof agentSchema>
export type IpList = z.infer<typeof ipListSchema>
export type PolicyRule = z.infer<typeof policyRuleSchema>
export type PolicySet = z.infer<typeof policySetSchema>
export type IpOverride = z.infer<typeof ipOverrideSchema>
export type AgentPolicy = z.infer<typeof agentPolicySchema>
export type DashboardStats = z.infer<typeof dashboardStatsSchema>