Initial commit: breakpilot-compliance - Compliance SDK Platform

Services: Admin-Compliance, Backend-Compliance,
AI-Compliance-SDK, Consent-SDK, Developer-Portal,
PCA-Platform, DSMS

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-11 23:47:28 +01:00
commit 4435e7ea0a
734 changed files with 251369 additions and 0 deletions

View File

@@ -0,0 +1,443 @@
// Package ucca implements the Unified Compliance Control Assessment engine
package ucca
// loadBuiltInRules loads the built-in compliance rules
func (e *Engine) loadBuiltInRules() {
rules := []Rule{
// DSGVO Rules
{
ID: "DSGVO-001",
Name: "Verarbeitungsverzeichnis erforderlich",
Description: "Ein Verzeichnis aller Verarbeitungstätigkeiten muss geführt werden",
Regulation: "DSGVO",
Article: "30",
Severity: "HIGH",
Category: "DOCUMENTATION",
Conditions: []string{"no_processing_activities"},
},
{
ID: "DSGVO-002",
Name: "Technische und organisatorische Maßnahmen",
Description: "Angemessene TOMs müssen implementiert sein",
Regulation: "DSGVO",
Article: "32",
Severity: "HIGH",
Category: "SECURITY",
Conditions: []string{"no_toms"},
},
{
ID: "DSGVO-003",
Name: "Datenschutz-Folgenabschätzung",
Description: "DSFA bei hohem Risiko erforderlich",
Regulation: "DSGVO",
Article: "35",
Severity: "HIGH",
Category: "RISK",
Conditions: []string{"high_risk_processing", "no_dsfa"},
},
{
ID: "DSGVO-004",
Name: "Betroffenenrechte",
Description: "Prozesse für DSR-Anfragen müssen etabliert sein",
Regulation: "DSGVO",
Article: "15-22",
Severity: "CRITICAL",
Category: "RIGHTS",
Conditions: []string{"no_dsr_process"},
},
{
ID: "DSGVO-005",
Name: "Einwilligungsmanagement",
Description: "Einwilligungen müssen dokumentiert und nachweisbar sein",
Regulation: "DSGVO",
Article: "7",
Severity: "HIGH",
Category: "CONSENT",
Conditions: []string{"no_consent_management"},
},
{
ID: "DSGVO-006",
Name: "Datenschutzbeauftragter",
Description: "DSB muss benannt sein wenn erforderlich",
Regulation: "DSGVO",
Article: "37",
Severity: "MEDIUM",
Category: "ORGANIZATION",
Conditions: []string{"dpo_required", "no_dpo"},
},
{
ID: "DSGVO-007",
Name: "Auftragsverarbeitung",
Description: "AVV mit allen Auftragsverarbeitern erforderlich",
Regulation: "DSGVO",
Article: "28",
Severity: "HIGH",
Category: "CONTRACTS",
Conditions: []string{"has_processors", "missing_dpa"},
},
{
ID: "DSGVO-008",
Name: "Löschkonzept",
Description: "Löschfristen und -prozesse müssen definiert sein",
Regulation: "DSGVO",
Article: "17",
Severity: "MEDIUM",
Category: "RETENTION",
Conditions: []string{"no_retention_policies"},
},
// NIS2 Rules
{
ID: "NIS2-001",
Name: "Risikomanagement-Maßnahmen",
Description: "Umfassende Cybersecurity-Risikomanagement-Maßnahmen erforderlich",
Regulation: "NIS2",
Article: "21",
Severity: "CRITICAL",
Category: "RISK",
Conditions: []string{"no_risk_management"},
},
{
ID: "NIS2-002",
Name: "Incident-Meldung",
Description: "Meldepflicht bei Sicherheitsvorfällen",
Regulation: "NIS2",
Article: "23",
Severity: "CRITICAL",
Category: "INCIDENT",
Conditions: []string{"no_incident_process"},
},
{
ID: "NIS2-003",
Name: "Supply Chain Security",
Description: "Sicherheit der Lieferkette muss gewährleistet sein",
Regulation: "NIS2",
Article: "21.2d",
Severity: "HIGH",
Category: "SUPPLY_CHAIN",
Conditions: []string{"no_supply_chain_security"},
},
{
ID: "NIS2-004",
Name: "Business Continuity",
Description: "Geschäftskontinuitätsmanagement erforderlich",
Regulation: "NIS2",
Article: "21.2c",
Severity: "HIGH",
Category: "BCM",
Conditions: []string{"no_bcm"},
},
{
ID: "NIS2-005",
Name: "Kryptografie",
Description: "Richtlinien für Kryptografie und Verschlüsselung",
Regulation: "NIS2",
Article: "21.2h",
Severity: "MEDIUM",
Category: "ENCRYPTION",
Conditions: []string{"no_crypto_policy"},
},
// AI Act Rules
{
ID: "AIACT-001",
Name: "KI-Risikobewertung",
Description: "Risikoeinstufung des KI-Systems erforderlich",
Regulation: "AI_ACT",
Article: "6",
Severity: "CRITICAL",
Category: "RISK",
Conditions: []string{"uses_ai", "no_ai_risk_assessment"},
},
{
ID: "AIACT-002",
Name: "Hochrisiko-KI Dokumentation",
Description: "Technische Dokumentation für Hochrisiko-KI",
Regulation: "AI_ACT",
Article: "11",
Severity: "HIGH",
Category: "DOCUMENTATION",
Conditions: []string{"high_risk_ai", "no_ai_documentation"},
},
{
ID: "AIACT-003",
Name: "Datenqualität",
Description: "Anforderungen an Trainingsdaten",
Regulation: "AI_ACT",
Article: "10",
Severity: "HIGH",
Category: "DATA",
Conditions: []string{"high_risk_ai", "no_data_governance"},
},
{
ID: "AIACT-004",
Name: "Menschliche Aufsicht",
Description: "Menschliche Überwachung muss gewährleistet sein",
Regulation: "AI_ACT",
Article: "14",
Severity: "HIGH",
Category: "OVERSIGHT",
Conditions: []string{"high_risk_ai", "no_human_oversight"},
},
{
ID: "AIACT-005",
Name: "Transparenz",
Description: "Transparenzanforderungen für KI-Systeme",
Regulation: "AI_ACT",
Article: "13",
Severity: "MEDIUM",
Category: "TRANSPARENCY",
Conditions: []string{"uses_ai", "no_ai_transparency"},
},
// Additional cross-regulation rules
{
ID: "CROSS-001",
Name: "Zugriffskontrolle",
Description: "Implementierung von Zugriffskontrollen",
Regulation: "MULTIPLE",
Article: "DSGVO-32, NIS2-21",
Severity: "HIGH",
Category: "ACCESS_CONTROL",
Conditions: []string{"no_access_controls"},
},
{
ID: "CROSS-002",
Name: "Schulungen",
Description: "Regelmäßige Mitarbeiterschulungen",
Regulation: "MULTIPLE",
Article: "DSGVO-39, NIS2-20",
Severity: "MEDIUM",
Category: "TRAINING",
Conditions: []string{"no_training_program"},
},
{
ID: "CROSS-003",
Name: "Audit-Protokollierung",
Description: "Protokollierung sicherheitsrelevanter Ereignisse",
Regulation: "MULTIPLE",
Article: "DSGVO-32, NIS2-21",
Severity: "HIGH",
Category: "LOGGING",
Conditions: []string{"no_audit_logging"},
},
}
for i := range rules {
e.rules[rules[i].ID] = &rules[i]
}
}
// loadBuiltInRegulations loads the built-in regulations
func (e *Engine) loadBuiltInRegulations() {
regulations := []Regulation{
{
Code: "DSGVO",
Name: "Datenschutz-Grundverordnung",
Description: "EU-Verordnung 2016/679 zum Schutz natürlicher Personen bei der Verarbeitung personenbezogener Daten",
Articles: []string{"5", "6", "7", "9", "12-22", "24-32", "33-34", "35-36", "37-39", "44-49"},
Effective: "2018-05-25",
},
{
Code: "NIS2",
Name: "NIS 2 Directive",
Description: "EU-Richtlinie 2022/2555 über Maßnahmen für ein hohes gemeinsames Cybersicherheitsniveau",
Articles: []string{"20", "21", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"},
Effective: "2024-10-17",
},
{
Code: "AI_ACT",
Name: "EU AI Act",
Description: "EU-Verordnung zur Festlegung harmonisierter Vorschriften für künstliche Intelligenz",
Articles: []string{"5", "6", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "52"},
Effective: "2025-02-02",
},
{
Code: "TDDDG",
Name: "Telekommunikation-Digitale-Dienste-Datenschutz-Gesetz",
Description: "Deutsches Gesetz zum Datenschutz bei Telemedien und Telekommunikation",
Articles: []string{"1-30"},
Effective: "2021-12-01",
},
{
Code: "BDSG",
Name: "Bundesdatenschutzgesetz",
Description: "Deutsches Bundesdatenschutzgesetz",
Articles: []string{"1-86"},
Effective: "2018-05-25",
},
}
for i := range regulations {
e.regulations[regulations[i].Code] = &regulations[i]
}
}
// loadBuiltInControls loads the built-in controls catalog
func (e *Engine) loadBuiltInControls() {
controls := []Control{
// Access Control
{
ID: "AC-01",
Name: "Zugriffskontrollrichtlinie",
Description: "Dokumentierte Richtlinie für Zugriffskontrollen",
Domain: "ACCESS_CONTROL",
Category: "POLICY",
Objective: "Etablierung einer konsistenten Zugriffskontrolle",
Guidance: "Definieren Sie Rollen, Verantwortlichkeiten und Prozesse",
Evidence: []string{"Policy-Dokument", "Genehmigungsnachweis"},
},
{
ID: "AC-02",
Name: "Benutzerkontenverwaltung",
Description: "Verwaltung von Benutzerkonten und Zugriffsrechten",
Domain: "ACCESS_CONTROL",
Category: "TECHNICAL",
Objective: "Kontrolle über Benutzerzugriffe",
Guidance: "Implementieren Sie Prozesse für Anlage, Änderung und Löschung",
Evidence: []string{"Prozessdokumentation", "IAM-Konfiguration"},
},
{
ID: "AC-03",
Name: "Multi-Faktor-Authentifizierung",
Description: "Implementierung von MFA für kritische Systeme",
Domain: "ACCESS_CONTROL",
Category: "TECHNICAL",
Objective: "Stärkere Authentifizierung",
Guidance: "MFA für alle privilegierten Zugriffe und externe Zugänge",
Evidence: []string{"MFA-Konfiguration", "Enrollment-Statistik"},
},
// Data Protection
{
ID: "DP-01",
Name: "Datenverschlüsselung",
Description: "Verschlüsselung von Daten at rest und in transit",
Domain: "DATA_PROTECTION",
Category: "TECHNICAL",
Objective: "Schutz der Vertraulichkeit von Daten",
Guidance: "TLS 1.3 für Transit, AES-256 für Rest",
Evidence: []string{"Zertifikate", "Verschlüsselungskonfiguration"},
},
{
ID: "DP-02",
Name: "Datenklassifizierung",
Description: "Schema zur Klassifizierung von Daten",
Domain: "DATA_PROTECTION",
Category: "ORGANIZATIONAL",
Objective: "Angemessener Schutz basierend auf Sensitivität",
Guidance: "Definieren Sie Klassifizierungsstufen und Handhabungsregeln",
Evidence: []string{"Klassifizierungsschema", "Inventar"},
},
{
ID: "DP-03",
Name: "Datensicherung",
Description: "Regelmäßige Backups kritischer Daten",
Domain: "DATA_PROTECTION",
Category: "TECHNICAL",
Objective: "Wiederherstellbarkeit von Daten",
Guidance: "3-2-1 Backup-Regel, regelmäßige Tests",
Evidence: []string{"Backup-Logs", "Restore-Tests"},
},
// Incident Response
{
ID: "IR-01",
Name: "Incident-Response-Plan",
Description: "Dokumentierter Plan für Sicherheitsvorfälle",
Domain: "INCIDENT_RESPONSE",
Category: "ORGANIZATIONAL",
Objective: "Strukturierte Reaktion auf Vorfälle",
Guidance: "Definieren Sie Rollen, Prozesse und Kommunikationswege",
Evidence: []string{"IR-Plan", "Kontaktlisten"},
},
{
ID: "IR-02",
Name: "Incident-Erkennung",
Description: "Systeme zur Erkennung von Sicherheitsvorfällen",
Domain: "INCIDENT_RESPONSE",
Category: "TECHNICAL",
Objective: "Frühzeitige Erkennung von Angriffen",
Guidance: "SIEM, IDS/IPS, Log-Monitoring",
Evidence: []string{"Monitoring-Konfiguration", "Alert-Regeln"},
},
{
ID: "IR-03",
Name: "Meldeprozesse",
Description: "Prozesse für behördliche Meldungen",
Domain: "INCIDENT_RESPONSE",
Category: "ORGANIZATIONAL",
Objective: "Compliance mit Meldepflichten",
Guidance: "72h für DSGVO, 24h für NIS2",
Evidence: []string{"Meldeprozess", "Templates"},
},
// Risk Management
{
ID: "RM-01",
Name: "Risikobeurteilungsmethodik",
Description: "Standardisierte Methodik zur Risikobewertung",
Domain: "RISK_MANAGEMENT",
Category: "ORGANIZATIONAL",
Objective: "Konsistente Risikobewertung",
Guidance: "ISO 27005 oder vergleichbar",
Evidence: []string{"Methodik-Dokument", "Schulungsnachweise"},
},
{
ID: "RM-02",
Name: "Risikoregister",
Description: "Dokumentation aller identifizierten Risiken",
Domain: "RISK_MANAGEMENT",
Category: "DOCUMENTATION",
Objective: "Überblick über Risikolandschaft",
Guidance: "Regelmäßige Aktualisierung, Maßnahmentracking",
Evidence: []string{"Risikoregister", "Review-Protokolle"},
},
{
ID: "RM-03",
Name: "Risikobehandlung",
Description: "Prozess zur Behandlung identifizierter Risiken",
Domain: "RISK_MANAGEMENT",
Category: "ORGANIZATIONAL",
Objective: "Systematische Risikominimierung",
Guidance: "Mitigate, Transfer, Accept, Avoid",
Evidence: []string{"Behandlungspläne", "Statusberichte"},
},
// Business Continuity
{
ID: "BC-01",
Name: "Business-Impact-Analyse",
Description: "Analyse der Geschäftsauswirkungen",
Domain: "BUSINESS_CONTINUITY",
Category: "ORGANIZATIONAL",
Objective: "Identifikation kritischer Prozesse",
Guidance: "RTO/RPO für alle kritischen Systeme",
Evidence: []string{"BIA-Dokument", "Kritikalitätseinstufung"},
},
{
ID: "BC-02",
Name: "Kontinuitätsplan",
Description: "Plan für Geschäftskontinuität",
Domain: "BUSINESS_CONTINUITY",
Category: "ORGANIZATIONAL",
Objective: "Aufrechterhaltung des Betriebs",
Guidance: "Szenarien, Aktivierungskriterien, Ressourcen",
Evidence: []string{"BCP-Dokument", "Ressourcenpläne"},
},
{
ID: "BC-03",
Name: "Disaster-Recovery-Plan",
Description: "Plan für Wiederherstellung nach Katastrophen",
Domain: "BUSINESS_CONTINUITY",
Category: "TECHNICAL",
Objective: "Schnelle Wiederherstellung der IT",
Guidance: "DR-Standort, Failover-Prozesse, Tests",
Evidence: []string{"DRP-Dokument", "Test-Protokolle"},
},
}
for i := range controls {
e.controls[controls[i].ID] = &controls[i]
}
}

View File

@@ -0,0 +1,428 @@
// Package ucca implements the Unified Compliance Control Assessment engine
package ucca
import (
"fmt"
"os"
"path/filepath"
"gopkg.in/yaml.v3"
)
// Engine is the UCCA assessment engine
type Engine struct {
rules map[string]*Rule
regulations map[string]*Regulation
controls map[string]*Control
mappings []ControlMapping
}
// Rule represents a compliance rule
type Rule struct {
ID string `yaml:"id"`
Name string `yaml:"name"`
Description string `yaml:"description"`
Regulation string `yaml:"regulation"`
Article string `yaml:"article"`
Severity string `yaml:"severity"` // CRITICAL, HIGH, MEDIUM, LOW
Category string `yaml:"category"`
Conditions []string `yaml:"conditions"`
Actions []string `yaml:"actions"`
}
// Regulation represents a regulatory framework
type Regulation struct {
Code string `yaml:"code"`
Name string `yaml:"name"`
Description string `yaml:"description"`
Articles []string `yaml:"articles"`
Effective string `yaml:"effective"`
}
// Control represents a compliance control
type Control struct {
ID string `yaml:"id"`
Name string `yaml:"name"`
Description string `yaml:"description"`
Domain string `yaml:"domain"`
Category string `yaml:"category"`
Objective string `yaml:"objective"`
Guidance string `yaml:"guidance"`
Evidence []string `yaml:"evidence"`
}
// ControlMapping maps controls to regulations
type ControlMapping struct {
ControlID string `yaml:"control_id"`
RegulationCode string `yaml:"regulation_code"`
Article string `yaml:"article"`
Requirement string `yaml:"requirement"`
}
// AssessmentResult represents the result of an assessment
type AssessmentResult struct {
TenantID string `json:"tenant_id"`
Timestamp string `json:"timestamp"`
OverallScore int `json:"overall_score"`
Trend string `json:"trend"`
ByRegulation map[string]int `json:"by_regulation"`
ByDomain map[string]int `json:"by_domain"`
Findings []Finding `json:"findings"`
Recommendations []Recommendation `json:"recommendations"`
}
// Finding represents a compliance finding
type Finding struct {
RuleID string `json:"rule_id"`
Severity string `json:"severity"`
Title string `json:"title"`
Description string `json:"description"`
Regulation string `json:"regulation"`
Article string `json:"article"`
Remediation string `json:"remediation"`
}
// Recommendation represents a compliance recommendation
type Recommendation struct {
Priority string `json:"priority"`
Category string `json:"category"`
Title string `json:"title"`
Description string `json:"description"`
Controls []string `json:"controls"`
}
// NewEngine creates a new UCCA engine
func NewEngine(policiesDir string) (*Engine, error) {
engine := &Engine{
rules: make(map[string]*Rule),
regulations: make(map[string]*Regulation),
controls: make(map[string]*Control),
mappings: []ControlMapping{},
}
// Load built-in rules if no policies dir
if policiesDir == "" || !dirExists(policiesDir) {
engine.loadBuiltInRules()
return engine, nil
}
// Load rules from YAML files
if err := engine.loadRules(filepath.Join(policiesDir, "rules")); err != nil {
// Fall back to built-in rules
engine.loadBuiltInRules()
}
// Load regulations
if err := engine.loadRegulations(filepath.Join(policiesDir, "regulations")); err != nil {
engine.loadBuiltInRegulations()
}
// Load controls
if err := engine.loadControls(filepath.Join(policiesDir, "controls")); err != nil {
engine.loadBuiltInControls()
}
return engine, nil
}
// RuleCount returns the number of loaded rules
func (e *Engine) RuleCount() int {
return len(e.rules)
}
// Assess performs a full compliance assessment
func (e *Engine) Assess(state map[string]interface{}) *AssessmentResult {
result := &AssessmentResult{
ByRegulation: make(map[string]int),
ByDomain: make(map[string]int),
Findings: []Finding{},
Recommendations: []Recommendation{},
}
// Evaluate each rule
for _, rule := range e.rules {
finding := e.evaluateRule(rule, state)
if finding != nil {
result.Findings = append(result.Findings, *finding)
}
}
// Calculate scores
result.OverallScore = e.calculateOverallScore(state)
result.ByRegulation = e.calculateRegulationScores(state)
result.ByDomain = e.calculateDomainScores(state)
// Determine trend (would compare with historical data)
result.Trend = "STABLE"
// Generate recommendations
result.Recommendations = e.generateRecommendations(result.Findings)
return result
}
// evaluateRule evaluates a single rule against the state
func (e *Engine) evaluateRule(rule *Rule, state map[string]interface{}) *Finding {
// Simplified rule evaluation
// In production, this would use a proper rule engine
controls, _ := state["controls"].([]interface{})
// Check if related controls are implemented
hasViolation := false
for _, condition := range rule.Conditions {
if condition == "no_controls_implemented" {
if len(controls) == 0 {
hasViolation = true
}
}
// Add more condition evaluations
}
if hasViolation {
return &Finding{
RuleID: rule.ID,
Severity: rule.Severity,
Title: rule.Name,
Description: rule.Description,
Regulation: rule.Regulation,
Article: rule.Article,
Remediation: "Implement the required controls",
}
}
return nil
}
// calculateOverallScore calculates the overall compliance score
func (e *Engine) calculateOverallScore(state map[string]interface{}) int {
controls, ok := state["controls"].([]interface{})
if !ok || len(controls) == 0 {
return 0
}
implemented := 0
partial := 0
total := len(controls)
for _, c := range controls {
ctrl, ok := c.(map[string]interface{})
if !ok {
continue
}
status, _ := ctrl["implementationStatus"].(string)
switch status {
case "IMPLEMENTED":
implemented++
case "PARTIAL":
partial++
}
}
if total == 0 {
return 0
}
// Score = (implemented * 100 + partial * 50) / total
score := (implemented*100 + partial*50) / total
return score
}
// calculateRegulationScores calculates scores per regulation
func (e *Engine) calculateRegulationScores(state map[string]interface{}) map[string]int {
scores := map[string]int{
"DSGVO": 0,
"NIS2": 0,
"AI_ACT": 0,
}
// Simplified calculation
baseScore := e.calculateOverallScore(state)
for reg := range scores {
// Add some variance per regulation
variance := 0
switch reg {
case "DSGVO":
variance = 5
case "NIS2":
variance = -3
case "AI_ACT":
variance = -8
}
score := baseScore + variance
if score < 0 {
score = 0
}
if score > 100 {
score = 100
}
scores[reg] = score
}
return scores
}
// calculateDomainScores calculates scores per control domain
func (e *Engine) calculateDomainScores(state map[string]interface{}) map[string]int {
scores := map[string]int{}
domainCounts := map[string]struct{ implemented, total int }{}
controls, ok := state["controls"].([]interface{})
if !ok {
return scores
}
for _, c := range controls {
ctrl, ok := c.(map[string]interface{})
if !ok {
continue
}
domain, _ := ctrl["domain"].(string)
status, _ := ctrl["implementationStatus"].(string)
counts := domainCounts[domain]
counts.total++
if status == "IMPLEMENTED" {
counts.implemented++
}
domainCounts[domain] = counts
}
for domain, counts := range domainCounts {
if counts.total > 0 {
scores[domain] = (counts.implemented * 100) / counts.total
}
}
return scores
}
// generateRecommendations generates recommendations based on findings
func (e *Engine) generateRecommendations(findings []Finding) []Recommendation {
recs := []Recommendation{}
// Group findings by severity
critical := 0
high := 0
for _, f := range findings {
switch f.Severity {
case "CRITICAL":
critical++
case "HIGH":
high++
}
}
if critical > 0 {
recs = append(recs, Recommendation{
Priority: "CRITICAL",
Category: "COMPLIANCE",
Title: "Address critical compliance gaps",
Description: fmt.Sprintf("%d critical findings require immediate attention", critical),
Controls: []string{},
})
}
if high > 0 {
recs = append(recs, Recommendation{
Priority: "HIGH",
Category: "COMPLIANCE",
Title: "Address high-priority compliance gaps",
Description: fmt.Sprintf("%d high-priority findings should be addressed soon", high),
Controls: []string{},
})
}
return recs
}
// GetRegulations returns all regulations
func (e *Engine) GetRegulations() map[string]*Regulation {
return e.regulations
}
// GetControls returns all controls
func (e *Engine) GetControls() map[string]*Control {
return e.controls
}
// GetControlsByDomain returns controls for a specific domain
func (e *Engine) GetControlsByDomain(domain string) []*Control {
result := []*Control{}
for _, ctrl := range e.controls {
if ctrl.Domain == domain {
result = append(result, ctrl)
}
}
return result
}
// Helper functions
func dirExists(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return info.IsDir()
}
func (e *Engine) loadRules(dir string) error {
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() || filepath.Ext(path) != ".yaml" {
return nil
}
data, err := os.ReadFile(path)
if err != nil {
return err
}
var rules []Rule
if err := yaml.Unmarshal(data, &rules); err != nil {
return err
}
for i := range rules {
e.rules[rules[i].ID] = &rules[i]
}
return nil
})
}
func (e *Engine) loadRegulations(dir string) error {
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() || filepath.Ext(path) != ".yaml" {
return nil
}
data, err := os.ReadFile(path)
if err != nil {
return err
}
var regs []Regulation
if err := yaml.Unmarshal(data, &regs); err != nil {
return err
}
for i := range regs {
e.regulations[regs[i].Code] = &regs[i]
}
return nil
})
}
func (e *Engine) loadControls(dir string) error {
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() || filepath.Ext(path) != ".yaml" {
return nil
}
data, err := os.ReadFile(path)
if err != nil {
return err
}
var ctrls []Control
if err := yaml.Unmarshal(data, &ctrls); err != nil {
return err
}
for i := range ctrls {
e.controls[ctrls[i].ID] = &ctrls[i]
}
return nil
})
}