4. Policy Check 核心原则:策略即代码(Policy as Code)

在传统合规审计中,策略通常以 PDF 文档、Word 表格或邮件形式存在,依赖人工解读与执行。Policy Check 将这一过程彻底重构为 策略即代码(Policy as Code, PaC) 模式,使合规规则成为可版本管理、可自动验证、可集成到 CI/CD 管线的代码资产。

4.1 策略即代码的核心价值

  • 可版本化:策略文件纳入 Git 等版本控制系统,每次变更都有审计轨迹。
  • 可自动化:无需人工逐条核对,由引擎自动评估基础设施或应用配置。
  • 可测试:为策略编写单元测试,确保规则逻辑正确。
  • 可复用:同一套策略可在开发、预发、生产环境一致执行。
  • 可追溯:策略变更与合规报告一一对应,满足监管取证要求。
关键认知:策略即代码不是简单的“把规则写成 YAML”,而是将合规知识转化为可执行、可断言、可组合的代码逻辑,使审计从“事后检查”变为“事前预防”和“事中控制”。

4.2 声明式 vs 命令式策略:两种范式对比

Policy Check 支持两种策略定义范式,理解其差异是正确编写策略的前提。

维度 声明式(Declarative) 命令式(Imperative)
核心思想 描述“目标状态是什么” 描述“如何检查或修复”
表达方式 数据驱动,规则 = 条件 + 预期值 逻辑驱动,规则 = 步骤 + 断言
可读性 高,接近自然语言或配置规范 中,需要理解控制流
幂等性 天然幂等,只描述结果 需自行保证幂等
适用场景 资源合规、配置基线、安全策略 复杂逻辑校验、多步骤编排、自定义修复
Policy Check 示例 Rego / CUE / HCL Python / JavaScript / Shell
实践建议:优先使用声明式策略定义基线规则,仅在需要复杂条件分支或动态修复时引入命令式策略。Policy Check 引擎支持两种范式混合编排。

4.3 声明式策略示例:Rego 语言

以下是一个典型的声明式策略,检查所有 Kubernetes 容器是否设置了 CPU 和内存限制:

package kubernetes.admission

# 默认允许
default allow = true

# 拒绝未设置资源限制的容器
allow {
    input.request.operation == "CREATE"
    container := input.request.object.spec.containers[_]
    container.resources.limits.cpu != null
    container.resources.limits.memory != null
}

# 违反策略时返回详细消息
deny[msg] {
    input.request.operation == "CREATE"
    container := input.request.object.spec.containers[_]
    not container.resources.limits
    msg := sprintf("容器 %v 未设置资源限制", [container.name])
}

4.4 命令式策略示例:Python 脚本

当需要执行外部 API 调用或复杂数据聚合时,命令式策略更为灵活:

import requests

def check_cert_expiry(endpoint, warning_days=30):
    """检查 TLS 证书是否即将过期"""
    response = requests.get(f"https://{endpoint}", verify=True)
    cert = response.connection.sock.getpeercert()
    expiry = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
    remaining = (expiry - datetime.utcnow()).days
    
    if remaining <= 0:
        return {"status": "FAIL", "message": f"证书已过期"}
    elif remaining <= warning_days:
        return {"status": "WARN", "message": f"证书将在 {remaining} 天后过期"}
    else:
        return {"status": "PASS", "message": f"证书有效期剩余 {remaining} 天"}

4.5 策略范式选择决策流程

策略范式选择决策流程 定义合规目标 规则逻辑 是否简单? 是 声明式策略 Rego / CUE / HCL 否 需要外部 API/复杂计算? 是 命令式策略 Python / JS / Shell 否 混合策略 声明式 + 命令式 输出:可执行的策略代码包 版本管理 → 自动化测试 → 集成到 CI/CD

4.6 策略即代码的工程化实践

常见陷阱:不要将所有策略都写成命令式脚本。命令式策略虽然灵活,但可读性差、测试成本高、难以审计。建议 80% 的基线策略使用声明式,仅 20% 的复杂场景使用命令式。

在 Policy Check 中实施策略即代码时,应遵循以下工程化步骤:

  1. 策略建模:将合规需求转化为可量化的规则条件。
  2. 代码编写:选择声明式或命令式范式实现规则。
  3. 单元测试:为每条策略编写正向和反向测试用例。
  4. 版本管理:将策略代码与基础设施代码一同纳入 Git 仓库。
  5. CI/CD 集成:在流水线中自动执行策略检查,阻断不合规变更。
  6. 审计报告:每次策略执行生成结构化报告,包含通过/失败详情。

4.7 声明式与命令式策略对比总结

对比项 声明式策略 命令式策略
学习曲线 低,领域特定语言(DSL) 中高,通用编程语言
执行效率 高,可并行评估 中,依赖运行时
调试难度 中,需理解 DSL 语义 低,标准 IDE 支持
策略组合 内置 AND/OR/NOT 逻辑 需手动编排
修复能力 仅检测,不自动修复 可包含修复逻辑
审计友好度 高,规则即文档 中,需额外注释
最佳实践:在 Policy Check 项目中,建议将声明式策略作为默认选择,仅在需要调用外部系统、执行复杂数学计算或实现动态修复时,才使用命令式策略。两种范式可以通过统一的策略引擎编排层无缝协作。