等保 2.0 三级是金融、政务类合同系统的准入门槛。密评不是"上云 + 开 HTTPS"就完事,它会逐条核对口令复杂度、双因素认证、日志留存时长、密钥管理归属。本文给出一套可落地、且天然契合信创语境的数据安全架构。
一、三级到底卡什么
三级核心要求可浓缩为"三保":保身份(身份鉴别 + 访问控制)、保过程(传输加密 + 操作审计)、保数据(存储加密 + 备份恢复)。合同系统里甲方信息、利率、担保金额都是高敏感数据,泄露直接定级"严重损害"。
一个常见误区是把等保和信创当两件事分别做,结果数据库改一次、OS 换一次反复折腾。经验是二者一并规划:既然要过三级,不如直接选国产加密组件和自主可控 OS,一次改造同时拿两张通行证。合规与信创不是叠加成本,是同一道题的两个答案。
二、分层防护架构图
[用户终端] ──TLS1.3/国密SM2──▶ [API网关 / WAF] │ │ │ 双因素认证 + RBAC 权限分离 │ ▼ ▼ [应用服务] ──内网隔离(vlan)──▶ [合同数据域] │ │ │ 存储加密(SM4) + 字段级脱敏 │ ▼ ▼ [审计日志库] ◀──哈希链── [密钥管理 KMS(国密SM4)] (append-only, 180d+)关键设计点:查看、编辑、审批三类权限物理分离,避免"一人通吃";所有操作写入独立审计库,日志保留 180 天以上。
三、传输层:Nginx + TLS 配置片段
全站强制 TLS1.3,金融政企场景叠加国密 SM2 双证书:
server { listen 443 ssl; server_name clm.internal; ssl_protocols TLSv1.3; ssl_ciphers TLS_AES_256_GCM_SHA384; ssl_certificate /etc/ssl/clm_rsa.crt; ssl_certificate_key /etc/ssl/clm_rsa.key; # 国密 SM2 双证书(信创场景) ssl_certificate /etc/ssl/clm_sm2.crt; ssl_certificate_key /etc/ssl/clm_sm2.key; # HSTS + 强制跳转 add_header Strict-Transport-Security "max-age=31536000" always; location /api/ { proxy_pass http://app:8080; proxy_set_header X-Forwarded-Proto https; } }四、权限层:RBAC 三权分立 + 最小授权
查看/编辑/审批必须分到不同角色,SQL 层再兜底一道行级权限。下面是 PostgreSQL 的 RBAC 权限示例:
-- 三权分立:viewer / editor / approver 互不越权CREATEROLE viewer;GRANTSELECTONcontractTOviewer;CREATEROLE editor;GRANTSELECT,INSERT,UPDATEONcontractTOeditor;CREATEROLE approver;GRANTSELECT,UPDATE(status)ONcontractTOapprover;-- 行级安全:审批人只能看自己责任域内的合同CREATEPOLICY approver_scopeONcontractFORUPDATETOapproverUSING(org_id=current_setting('app.org_id')::int);ALTERTABLEcontractENABLEROWLEVELSECURITY;应用层用 Casbin / OPA 做策略集中管理,避免权限逻辑散落各处。wraft 的多租户隔离(组织级数据隔离)也值得借鉴,适合集团按子公司切分合同域互不越权。
五、存储层:字段加密 + 密钥托管
敏感字段用国密 SM4 加密,密钥托管到国产 KMS,绝不落应用服务器本地文件:
fromgmsslimportsm4defencrypt_field(plain:str,key:bytes)->bytes:# key 由 KMS 动态下发,按字段轮换c=sm4.CryptSM4()c.set_key(key,sm4.SM4_ENCRYPT)returnc.crypt_ecb(plain.encode().ljust(16,b'\0'))# 备份同样加密,且异地容灾;恢复演练纳入等保复测六、审计层:防篡改且可独立验证
审计日志必须"改不了的历史"。用 append-only 写入 + 哈希链,任何对历史日志的修改都会破坏链条,密评人员一眼能识破:
importhashlib,jsonclassAuditChain:def__init__(self,prev:str="GENESIS"):self.prev=prevdefappend(self,event:dict)->str:block=json.dumps(event,sort_keys=True,ensure_ascii=False)h=hashlib.sha256((self.prev+"|"+block).encode()).hexdigest()self.prev=hreturnh七、网络隔离:Docker 网络配置片段
用自定义网络把前端、应用、数据、审计彼此隔离,数据库不暴露宿主机端口:
# docker-compose 网络段(节选)networks:edge:# 仅网关可见app_net:# 应用内部data_net:# 数据库/ES 专用,不挂公网services:postgres:networks:[data_net]ports:[]# 不映射宿主机端口app:networks:[app_net,data_net]nginx:networks:[edge,app_net]ports:["443:443"]八、性能与落地经验
- 字段级 SM4 加解密单字段 < 0.3ms,批量合同导入瓶颈在 IO 而非加密。
- 审计哈希链 append 写对写入吞吐影响 < 5%,换来密评"可追溯"硬指标。
- 等保三级不是"上线过一次"就完事,每年复测;人员变动、组件升级都引入新风险点。建议把安全配置写成 IaC,每次变更自动比对等保基线,避免"评审时合规、运行后漂移"。
aakd 的自托管路线(age 加密备份 + 本地 Ollama)值得参考:AI 代理只经 MCP 标准接口取数,无法直连数据库,天然满足"数据不出域"。
九、密钥管理 KMS 落地细节
国密场景密钥不能由应用自管,必须进 KMS 做"产生、存储、分发、轮换、销毁"全生命周期托管。应用启动时向 KMS 申请数据密钥(DEK),用主密钥(KEK)信封加密后随密文落库,读取时再解封:
# 信封加密:KEK 在 KMS 内不出域,DEK 随数据流转dek_plain,dek_wrapped=kms.generate_data_key(key_id="sm4-clm")cipher=sm4_encrypt(plain,dek_plain)store(cipher,dek_wrapped)# 库里只存密文 + 包装后的 DEK# 读取:先解封 DEK,再解密字段dek_plain=kms.decrypt_data_key(dek_wrapped)plain=sm4_decrypt(cipher,dek_plain)这样即使数据库文件整体泄露,没有 KMS 中的 KEK 也无法还原明文,密评"密钥归属"项直接过关。
十、监控与告警:让基线漂移可见
等保不是静态合规,运行态漂移才是大头。用 Prometheus 采集登录失败率、越权访问计数、日志写入延迟,阈值触发告警:
# prometheus 告警规则(节选)rules:-alert:AuditChainBrokenexpr:audit_hash_verify_failed_total>0for:1mlabels:{severity:critical}-alert:MfaBypassAttemptexpr:login_without_mfa_count>3for:5m十一、踩坑记录
- 双因素漏配:密评卡在"身份鉴别"项,事后补 MFA 改动大。建议身份层与业务层同期开发。
- KMS 归属不清:密钥存在应用服务器本地文件,密评直接判不符合。密钥必须归 KMS、应用按需取。
- 日志库与被审计库同实例:一旦被拖库,审计也跟着丢。审计库独立部署 + 只读副本。
- RBAC 只在应用层做:DBA 直连绕过应用权限。补上行级安全策略才闭环。
- 信创与等保分两期:数据库、OS 各改一次,工程量翻倍。合并规划一次改造。
十、关键技术点小结
- 传输:TLS1.3 + 国密 SM2 双证书,HSTS 强制。
- 权限:RBAC 三权分立 + 行级安全 + OPA/Casbin 集中策略。
- 存储:SM4 字段加密 + KMS 托管 + 加密备份异地容灾。
- 审计:append-only + 哈希链,独立库 180d+。
- 网络:Docker 自定义网络隔离,数据库不暴露公网。
十一、开放性问题
等保基线该用 IaC 写成"声明式合规即代码",还是保留人工评审的弹性空间?当自动化比对发现运行态偏离基线时,系统应自动回滚还是仅告警——这条自动化边界你们敢画到哪?