跳到主内容

安全守卫

核心能力

安全守卫

EnerOS 安全守卫是 Agent 决策落地前的最后一道防线,位于内核态的命令执行通道上。所有来自 Agent、API、外部系统的控制命令都必须通过安全网关的拦截与校验,确保即便上层逻辑出现缺陷也不会引发电力系统事故。

电力系统是 cyber-physical 系统,一次错误命令可能造成大面积停电、设备损毁甚至人身事故。EnerOS 的安全守卫基于「纵深防御」原则构建多层防线,单点失效不会导致事故穿透到物理电网。这是 EnerOS 区别于通用 AgentOS 的安全护城河。

架构总览

┌─────────────────────────────────────────────────────┐
│  Agent / API / 外部系统                            │
└──────────────────┬──────────────────────────────────┘
                   │ submit(cmd)
┌──────────────────┴──────────────────────────────────┐
│  SafetyGateway (责任链)                             │
│  ┌──────────────────────────────────────────────┐   │
│  │ 1. AuthStage      mTLS / OAuth2 / mTLS+Token │   │
│  │ 2. PermissionStage RBAC / ABAC                │   │
│  │ 3. ConstraintStage 严格约束校验               │   │
│  │ 4. RuleStage      电力安全规则                │   │
│  │ 5. RateLimitStage 速率与配额                  │   │
│  │ 6. AuditStage     WORM 审计                   │   │
│  └──────────────────────────────────────────────┘   │
│                ↓ Verdict                            │
│         Allow / Deny / Project                      │
└──────────────────┬──────────────────────────────────┘
                   │ execute
┌──────────────────┴──────────────────────────────────┐
│  设备执行层(实时域)                                │
└─────────────────────────────────────────────────────┘

安全网关架构

网关采用责任链模式,每条命令依次通过:身份认证 → 权限校验 → 约束校验 → 安全规则 → 速率限制 → 审计记录。

use eneros_safety::{SafetyGateway, Pipeline};
use std::time::Duration;

let gateway = SafetyGateway::builder()
    .stage(AuthStage::mtls())
    .stage(PermissionStage::rbac())
    .stage(ConstraintStage::strict())
    .stage(RuleStage::default())
    .stage(RateLimitStage::new(100, Duration::from_secs(1)))
    .stage(AuditStage::worm())
    .build();

责任链阶段说明

阶段职责失败动作典型耗时
AuthStage身份认证(mTLS / Token)Deny< 50μs
PermissionStage权限校验(RBAC / ABAC)Deny< 20μs
ConstraintStage物理约束校验Deny / Project< 200μs
RuleStage电力安全规则(五防等)Deny / Project< 30μs
RateLimitStage速率与配额Deny< 5μs
AuditStageWORM 审计写入不阻断< 50μs
总计--< 100μs

命令拦截

每条命令通过 submit 进入网关,返回 Allow / Deny / Project

use eneros_safety::{Command, Verdict, BreakerId};

let cmd = Command::OpenBreaker { id: breaker_id };

match gateway.submit(cmd).await? {
    Verdict::Allow => {
        ctx.execute(cmd).await?;
    }
    Verdict::Deny(reason) => {
        log::warn!("命令被拦截: {}", reason);
        ctx.notify_agent("命令被安全网关拒绝").await?;
    }
    Verdict::Project(alternative) => {
        log::info!("命令被投影为可行解: {:?}", alternative);
        ctx.execute(alternative).await?;
    }
}

Command 变体

变体含义风险等级
OpenBreaker { id }断开断路器
CloseBreaker { id }合上断路器
OpenDisconnector { id }拉开刀闸
CloseDisconnector { id }合上刀闸
SetGenerator { id, mw }调整机组出力
AdjustTap { id, tap }调节分接头
SetLoad { id, mw }调整负荷
GroundDevice { id }装设接地线
EmergencyStop紧急停机极高

Verdict 变体

变体含义处理
Allow全部通过执行
Deny(reason)被拒绝通知 Agent
Project(alt)投影为可行解执行 alt
Delay(duration)延迟执行等待后重试
ManualReview需人工审核转人工

安全规则

规则系统支持组合式策略,覆盖典型电力安全场景:

use eneros_safety::{Rule, RuleSet};

let rules = RuleSet::new()
    // 禁止带负荷拉刀闸
    .add(Rule::no_load_break_disconnector())
    // 同期检定
    .add(Rule::sync_check_before_close())
    // 五防闭锁
    .add(Rule::five_interlocks())
    // 检修区域隔离
    .add(Rule::maintenance_zone_isolation())
    // 频率异常闭锁
    .add(Rule::frequency_block(49.0, 51.0))
    // 电压越限闭锁
    .add(Rule::voltage_block(0.85, 1.15))
    // 自定义规则
    .add(Rule::custom("no_dispatch_during_maintenance", |cmd, ctx| {
        if ctx.maintenance_in_progress() && cmd.is_dispatch() {
            Verdict::Deny("检修期间禁止调度操作".into())
        } else {
            Verdict::Allow
        }
    }));

内置规则一览

规则检查内容适用设备
no_load_break_disconnector禁止带负荷拉刀闸刀闸
sync_check_before_close合闸前同期检定断路器
five_interlocks五防闭锁全检所有设备
maintenance_zone_isolation检修区域隔离所有设备
frequency_block频率越限闭锁系统级
voltage_block电压越限闭锁母线级
overload_block设备过载闭锁线路、变压器
cold_load_pickup冷负荷投入限制负荷开关
reclosing_block重合闸闭锁断路器
parallel_protection并列保护发电机

操作票

对于复杂操作序列,强制走操作票流程,确保顺序与隔离:

use eneros_safety::{OperationTicket, Step};

let ticket = OperationTicket::new()
    .step(Step::open(bus_id_1))
    .step(Step::verify_open(bus_id_1))
    .step(Step::ground(bus_id_1))
    .step(Step::maintain(bus_id_1))
    .step(Step::unground(bus_id_1))
    .step(Step::close(bus_id_1))
    .step(Step::verify_closed(bus_id_1));

let ticket_id = gateway.submit_ticket(ticket).await?;
// 必须按序执行,跳步会被拒绝
// 每步执行后自动记录到 WORM 审计

// 查询操作票状态
let status = gateway.ticket_status(ticket_id).await?;
println!("当前步骤: {}/{}", status.current_step, status.total_steps);

OperationTicket 字段

字段类型说明
idTicketId操作票唯一 ID
stepsVec操作步骤序列
created_byAgentId创建者
approved_byOption审批人(关键操作)
statusTicketStatusDraft / Pending / Active / Done / Cancelled
timeoutDuration超时自动取消

速率与配额

防止 Agent 失控导致的「命令风暴」:

// 单 Agent 速率限制
gateway.set_rate_limit("dispatch_agent", 100, Duration::from_secs(1));

// 关键设备配额
gateway.set_quota("circuit_breaker_5", 5, Duration::from_hours(1));

// 突发流量桶
gateway.set_burst_limit("protection_agent", 10, 100, Duration::from_secs(1));

// 全局速率
gateway.set_global_rate_limit(10000, Duration::from_secs(1));

速率策略

策略含义适用场景
TokenBucket令牌桶一般 Agent
LeakyBucket漏桶平滑流量
SlidingWindow滑动窗口精确限流
Quota总量配额关键设备

审计与 WORM

所有命令决策(含被拦截的)写入 WORM(Write Once Read Many)存储,满足 NERC CIP 与 IEC 62443 取证要求:

use eneros_safety::{AuditQuery, Range, VerdictFilter};

let audit_log = gateway.audit_log();

// 查询审计
let entries = audit_log.query(
    AuditQuery::new()
        .agent("dispatch_agent")
        .range(Range::last(Duration::from_hours(24)))
        .verdict(VerdictFilter::All)
).await?;

for entry in &entries {
    println!("{} | {:?} | {} | {:?}",
        entry.timestamp, entry.verdict, entry.command, entry.agent);
}

// 导出审计报告(合规)
let report = audit_log.export_report(
    Range::between(month_start, month_end),
    Format::Csv,
).await?;
std::fs::write("audit_202607.csv", report)?;

AuditEntry 字段

字段类型说明
timestampTimestamp命令提交时间
agentAgentId提交者
commandCommand命令内容
verdictVerdict处置结果
reasonOption拒绝原因
duration_usu64校验耗时(μs)
tenantTenantId租户
signature[u8; 32]防篡改签名

紧急停机

支持硬件级紧急停机按钮,绕过所有 Agent 直接断开:

use eneros_safety::EmergencyScope;

gateway.emergency_stop(EmergencyScope::All).await?;
// 内核自动完成:
//   1. 所有 Agent 暂停
//   2. 所有控制输出置零
//   3. 进入安全状态
//   4. 通知运维人员
//   5. 启动应急流程

// 局部紧急停机
gateway.emergency_stop(EmergencyScope::Region("substation_a")).await?;

// 恢复运行(需人工确认)
gateway.resume_from_emergency().await?;

EmergencyScope 变体

变体范围恢复方式
All全系统人工
Region(name)指定区域人工
Agent(id)单个 Agent自动
Device(id)单个设备自动

安全等级矩阵

等级描述阶段适用场景
L0全开放仅审计实验室测试
L1约束校验Auth + Constraint数字孪生
L2约束+规则+ Rule + RateLimit生产环境
L3全链路+操作票+ Permission + Ticket关键基础设施
L4L3+独立硬件校验+ Hardware Safety Module国家级电网
use eneros_safety::SafetyLevel;

// 配置安全等级
gateway.set_level(SafetyLevel::L3)?;

// 运行时动态切换(仅可降级到更严格)
gateway.escalate_to(SafetyLevel::L4).await?;

性能指标

操作延迟吞吐
单命令校验(全链路)< 100μs10k cmd/s
AuthStage< 50μs-
PermissionStage< 20μs-
ConstraintStage(1000 节点)< 200μs-
RuleStage< 30μs-
操作票执行(5 步)< 1ms-
WORM 审计写入< 50μs100k entries/s
紧急停机响应< 1ms-
审计查询(24h)< 50ms-

测试环境:4 核 / 8GB / Ubuntu 22.04。

配置参数

eneros.toml 中安全相关配置:

[safety]
# 安全等级:L0 / L1 / L2 / L3 / L4
level = "L3"
# 是否强制操作票
require_ticket = true
# 默认速率限制(cmd/s)
default_rate_limit = 100
# 关键设备配额(cmd/h)
critical_device_quota = 5
# WORM 审计存储路径
audit_dir = "/var/eneros/audit"
# 审计保留期(天)
audit_retention_days = 3650
# 是否启用紧急停机硬件接口
hardware_emergency_stop = true
# 紧急停机心跳超时(ms)
emergency_heartbeat_ms = 100
参数类型默认值说明
levelenumL3安全等级
require_ticketbooltrue强制操作票
default_rate_limitu32100默认速率限制
critical_device_quotau325关键设备配额
audit_dirString/var/eneros/auditWORM 审计路径
audit_retention_daysu323650审计保留期
hardware_emergency_stopbooltrue硬件紧急停机
emergency_heartbeat_msu32100心跳超时

与其他能力的关系

关联能力互动方式
物理约束决策约束引擎是网关核心
零信任与安全增强身份认证与审计
多智能体协作Agent 命令的来源
实时双执行域实时域命令也经过网关
多租户与隔离命令按租户命名空间审计
时序原生操作审计日志入库
电网拓扑一等公民操作票依赖拓扑校验

相关文档