Files
lijiaoqiao/gateway/internal/compliance/rules/loader.go
Your Name 89104bd0db feat(P1/P2): 完成TDD开发及P1/P2设计文档
## 设计文档
- multi_role_permission_design: 多角色权限设计 (CONDITIONAL GO)
- audit_log_enhancement_design: 审计日志增强 (CONDITIONAL GO)
- routing_strategy_template_design: 路由策略模板 (CONDITIONAL GO)
- sso_saml_technical_research: SSO/SAML调研 (CONDITIONAL GO)
- compliance_capability_package_design: 合规能力包设计 (CONDITIONAL GO)

## TDD开发成果
- IAM模块: supply-api/internal/iam/ (111个测试)
- 审计日志模块: supply-api/internal/audit/ (40+测试)
- 路由策略模块: gateway/internal/router/ (33+测试)
- 合规能力包: gateway/internal/compliance/ + scripts/ci/compliance/

## 规范文档
- parallel_agent_output_quality_standards: 并行Agent产出质量规范
- project_experience_summary: 项目经验总结 (v2)
- 2026-04-02-p1-p2-tdd-execution-plan: TDD执行计划

## 评审报告
- 5个CONDITIONAL GO设计文档评审报告
- fix_verification_report: 修复验证报告
- full_verification_report: 全面质量验证报告
- tdd_module_quality_verification: TDD模块质量验证
- tdd_execution_summary: TDD执行总结

依据: Superpowers执行框架 + TDD规范
2026-04-02 23:35:53 +08:00

140 lines
3.6 KiB
Go

package rules
import (
"fmt"
"os"
"regexp"
"gopkg.in/yaml.v3"
)
// Rule 定义合规规则结构
type Rule struct {
ID string `yaml:"id"`
Name string `yaml:"name"`
Description string `yaml:"description"`
Severity string `yaml:"severity"`
Matchers []Matcher `yaml:"matchers"`
Action Action `yaml:"action"`
Audit Audit `yaml:"audit"`
}
// Matcher 定义规则匹配器
type Matcher struct {
Type string `yaml:"type"`
Pattern string `yaml:"pattern"`
Target string `yaml:"target"`
Scope string `yaml:"scope"`
}
// Action 定义规则动作
type Action struct {
Primary string `yaml:"primary"`
Secondary string `yaml:"secondary"`
}
// Audit 定义审计配置
type Audit struct {
EventName string `yaml:"event_name"`
EventCategory string `yaml:"event_category"`
EventSubCategory string `yaml:"event_sub_category"`
}
// RulesConfig YAML规则配置结构
type RulesConfig struct {
Rules []Rule `yaml:"rules"`
}
// RuleLoader 规则加载器
type RuleLoader struct {
ruleIDPattern *regexp.Regexp
}
// NewRuleLoader 创建新的规则加载器
func NewRuleLoader() *RuleLoader {
// 规则ID格式: {Category}-{SubCategory}[-{Detail}]
// Category: 大写字母, 2-4字符
// SubCategory: 大写字母, 2-10字符
// Detail: 可选, 大写字母+数字+连字符, 1-20字符
pattern := regexp.MustCompile(`^[A-Z]{2,4}-[A-Z]{2,10}(-[A-Z0-9-]{1,20})?$`)
return &RuleLoader{
ruleIDPattern: pattern,
}
}
// LoadFromFile 从YAML文件加载规则
func (l *RuleLoader) LoadFromFile(filePath string) ([]Rule, error) {
// 检查文件是否存在
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return nil, fmt.Errorf("file not found: %s", filePath)
}
// 读取文件内容
data, err := os.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("failed to read file: %w", err)
}
// 解析YAML
var config RulesConfig
if err := yaml.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("failed to parse YAML: %w", err)
}
// 验证规则
for _, rule := range config.Rules {
if err := l.validateRule(rule); err != nil {
return nil, err
}
}
return config.Rules, nil
}
// validateRule 验证规则完整性
func (l *RuleLoader) validateRule(rule Rule) error {
// 检查必需字段
if rule.ID == "" {
return fmt.Errorf("missing required field: id")
}
if rule.Name == "" {
return fmt.Errorf("missing required field: name for rule %s", rule.ID)
}
if rule.Severity == "" {
return fmt.Errorf("missing required field: severity for rule %s", rule.ID)
}
if len(rule.Matchers) == 0 {
return fmt.Errorf("missing required field: matchers for rule %s", rule.ID)
}
if rule.Action.Primary == "" {
return fmt.Errorf("missing required field: action.primary for rule %s", rule.ID)
}
// 验证规则ID格式
if !l.ValidateRuleID(rule.ID) {
return fmt.Errorf("invalid rule ID format: %s (expected format: {Category}-{SubCategory}[-{Detail}])", rule.ID)
}
// 验证每个匹配器
for i, matcher := range rule.Matchers {
if matcher.Type == "" {
return fmt.Errorf("missing required field: matchers[%d].type for rule %s", i, rule.ID)
}
if matcher.Pattern == "" {
return fmt.Errorf("missing required field: matchers[%d].pattern for rule %s", i, rule.ID)
}
// 验证正则表达式是否有效
if _, err := regexp.Compile(matcher.Pattern); err != nil {
return fmt.Errorf("invalid regex pattern in matchers[%d] for rule %s: %w", i, rule.ID, err)
}
}
return nil
}
// ValidateRuleID 验证规则ID格式
func (l *RuleLoader) ValidateRuleID(ruleID string) bool {
return l.ruleIDPattern.MatchString(ruleID)
}