feat(multi-layer): complete Multi-Layer Control Architecture (Phases 1-8 + Pass 0)
Some checks failed
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Failing after 47s
CI/CD / test-python-backend-compliance (push) Successful in 33s
CI/CD / test-python-document-crawler (push) Successful in 24s
CI/CD / test-python-dsms-gateway (push) Successful in 18s
CI/CD / validate-canonical-controls (push) Successful in 11s
CI/CD / Deploy (push) Has been skipped
Some checks failed
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Failing after 47s
CI/CD / test-python-backend-compliance (push) Successful in 33s
CI/CD / test-python-document-crawler (push) Successful in 24s
CI/CD / test-python-dsms-gateway (push) Successful in 18s
CI/CD / validate-canonical-controls (push) Successful in 11s
CI/CD / Deploy (push) Has been skipped
Implements the full Multi-Layer Control Architecture for migrating ~25,000 Rich Controls into atomic, deduplicated Master Controls with full traceability. Architecture: Legal Source → Obligation → Control Pattern → Master Control → Customer Instance New services: - ObligationExtractor: 3-tier extraction (exact → embedding → LLM) - PatternMatcher: 2-tier matching (keyword + embedding + domain-bonus) - ControlComposer: Pattern + Obligation → Master Control - PipelineAdapter: Pipeline integration + Migration Passes 1-5 - DecompositionPass: Pass 0a/0b — Rich Control → atomic Controls - CrosswalkRoutes: 15 API endpoints under /v1/canonical/ New DB schema: - Migration 060: obligation_extractions, control_patterns, crosswalk_matrix - Migration 061: obligation_candidates, parent_control_uuid tracking Pattern Library: 50 YAML patterns (30 core + 20 IT-security) Go SDK: Pattern loader with YAML validation and indexing Documentation: MkDocs updated with full architecture overview 500 Python tests passing across all components. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
260
ai-compliance-sdk/internal/ucca/pattern_loader.go
Normal file
260
ai-compliance-sdk/internal/ucca/pattern_loader.go
Normal file
@@ -0,0 +1,260 @@
|
||||
package ucca
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// ControlPattern represents a reusable control pattern template.
|
||||
// Pattern ID format: CP-{DOMAIN}-{NNN} (e.g. CP-AUTH-001).
|
||||
type ControlPattern struct {
|
||||
ID string `yaml:"id" json:"id"`
|
||||
Name string `yaml:"name" json:"name"`
|
||||
NameDE string `yaml:"name_de" json:"name_de"`
|
||||
Domain string `yaml:"domain" json:"domain"`
|
||||
Category string `yaml:"category" json:"category"`
|
||||
Description string `yaml:"description" json:"description"`
|
||||
ObjectiveTemplate string `yaml:"objective_template" json:"objective_template"`
|
||||
RationaleTemplate string `yaml:"rationale_template" json:"rationale_template"`
|
||||
RequirementsTemplate []string `yaml:"requirements_template" json:"requirements_template"`
|
||||
TestProcedureTemplate []string `yaml:"test_procedure_template" json:"test_procedure_template"`
|
||||
EvidenceTemplate []string `yaml:"evidence_template" json:"evidence_template"`
|
||||
SeverityDefault string `yaml:"severity_default" json:"severity_default"`
|
||||
ImplementationEffortDefault string `yaml:"implementation_effort_default,omitempty" json:"implementation_effort_default,omitempty"`
|
||||
OpenAnchorRefs []AnchorRef `yaml:"open_anchor_refs,omitempty" json:"open_anchor_refs,omitempty"`
|
||||
ObligationMatchKeywords []string `yaml:"obligation_match_keywords" json:"obligation_match_keywords"`
|
||||
Tags []string `yaml:"tags" json:"tags"`
|
||||
ComposableWith []string `yaml:"composable_with,omitempty" json:"composable_with,omitempty"`
|
||||
}
|
||||
|
||||
// AnchorRef links a pattern to an open-source framework reference.
|
||||
type AnchorRef struct {
|
||||
Framework string `yaml:"framework" json:"framework"`
|
||||
Ref string `yaml:"ref" json:"ref"`
|
||||
}
|
||||
|
||||
// patternFile is the top-level YAML structure.
|
||||
type patternFile struct {
|
||||
Version string `yaml:"version"`
|
||||
Description string `yaml:"description"`
|
||||
Patterns []ControlPattern `yaml:"patterns"`
|
||||
}
|
||||
|
||||
// ControlPatternIndex provides fast lookup of control patterns.
|
||||
type ControlPatternIndex struct {
|
||||
ByID map[string]*ControlPattern
|
||||
ByDomain map[string][]*ControlPattern
|
||||
ByCategory map[string][]*ControlPattern
|
||||
ByTag map[string][]*ControlPattern
|
||||
ByKeyword map[string][]*ControlPattern // keyword -> patterns (for obligation matching)
|
||||
All []*ControlPattern
|
||||
}
|
||||
|
||||
// LoadControlPatterns loads all YAML pattern files from the control_patterns directory.
|
||||
func LoadControlPatterns() (*ControlPatternIndex, error) {
|
||||
dir, err := findPatternsDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read patterns directory: %w", err)
|
||||
}
|
||||
|
||||
var allPatterns []ControlPattern
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
name := entry.Name()
|
||||
if strings.HasPrefix(name, "_") {
|
||||
continue // skip schema and metadata files
|
||||
}
|
||||
if !strings.HasSuffix(name, ".yaml") && !strings.HasSuffix(name, ".yml") {
|
||||
continue
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(filepath.Join(dir, name))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read %s: %w", name, err)
|
||||
}
|
||||
|
||||
var pf patternFile
|
||||
if err := yaml.Unmarshal(data, &pf); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse %s: %w", name, err)
|
||||
}
|
||||
|
||||
allPatterns = append(allPatterns, pf.Patterns...)
|
||||
}
|
||||
|
||||
if len(allPatterns) == 0 {
|
||||
return nil, fmt.Errorf("no control patterns found in %s", dir)
|
||||
}
|
||||
|
||||
idx, err := buildPatternIndex(allPatterns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
func findPatternsDir() (string, error) {
|
||||
candidates := []string{
|
||||
"policies/control_patterns",
|
||||
"../policies/control_patterns",
|
||||
"../../policies/control_patterns",
|
||||
}
|
||||
|
||||
_, filename, _, ok := runtime.Caller(0)
|
||||
if ok {
|
||||
srcDir := filepath.Dir(filename)
|
||||
candidates = append(candidates,
|
||||
filepath.Join(srcDir, "../../policies/control_patterns"),
|
||||
)
|
||||
}
|
||||
|
||||
for _, p := range candidates {
|
||||
abs, err := filepath.Abs(p)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
info, err := os.Stat(abs)
|
||||
if err == nil && info.IsDir() {
|
||||
return abs, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("control_patterns directory not found in any candidate path")
|
||||
}
|
||||
|
||||
func buildPatternIndex(patterns []ControlPattern) (*ControlPatternIndex, error) {
|
||||
idx := &ControlPatternIndex{
|
||||
ByID: make(map[string]*ControlPattern),
|
||||
ByDomain: make(map[string][]*ControlPattern),
|
||||
ByCategory: make(map[string][]*ControlPattern),
|
||||
ByTag: make(map[string][]*ControlPattern),
|
||||
ByKeyword: make(map[string][]*ControlPattern),
|
||||
}
|
||||
|
||||
for i := range patterns {
|
||||
p := &patterns[i]
|
||||
|
||||
// Validate ID uniqueness
|
||||
if _, exists := idx.ByID[p.ID]; exists {
|
||||
return nil, fmt.Errorf("duplicate pattern ID: %s", p.ID)
|
||||
}
|
||||
|
||||
idx.ByID[p.ID] = p
|
||||
idx.ByDomain[p.Domain] = append(idx.ByDomain[p.Domain], p)
|
||||
idx.ByCategory[p.Category] = append(idx.ByCategory[p.Category], p)
|
||||
idx.All = append(idx.All, p)
|
||||
|
||||
for _, tag := range p.Tags {
|
||||
idx.ByTag[tag] = append(idx.ByTag[tag], p)
|
||||
}
|
||||
|
||||
for _, kw := range p.ObligationMatchKeywords {
|
||||
lower := strings.ToLower(kw)
|
||||
idx.ByKeyword[lower] = append(idx.ByKeyword[lower], p)
|
||||
}
|
||||
}
|
||||
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
// GetPattern returns a pattern by its ID (e.g. "CP-AUTH-001").
|
||||
func (idx *ControlPatternIndex) GetPattern(id string) (*ControlPattern, bool) {
|
||||
p, ok := idx.ByID[strings.ToUpper(id)]
|
||||
return p, ok
|
||||
}
|
||||
|
||||
// GetPatternsByDomain returns all patterns for a domain (e.g. "AUTH").
|
||||
func (idx *ControlPatternIndex) GetPatternsByDomain(domain string) []*ControlPattern {
|
||||
return idx.ByDomain[strings.ToUpper(domain)]
|
||||
}
|
||||
|
||||
// GetPatternsByCategory returns all patterns for a category (e.g. "authentication").
|
||||
func (idx *ControlPatternIndex) GetPatternsByCategory(category string) []*ControlPattern {
|
||||
return idx.ByCategory[strings.ToLower(category)]
|
||||
}
|
||||
|
||||
// GetPatternsByTag returns all patterns with a given tag.
|
||||
func (idx *ControlPatternIndex) GetPatternsByTag(tag string) []*ControlPattern {
|
||||
return idx.ByTag[strings.ToLower(tag)]
|
||||
}
|
||||
|
||||
// MatchByKeywords returns patterns whose obligation_match_keywords overlap with
|
||||
// the given text. Returns matches sorted by score (number of keyword hits) descending.
|
||||
func (idx *ControlPatternIndex) MatchByKeywords(text string) []PatternMatch {
|
||||
textLower := strings.ToLower(text)
|
||||
scores := make(map[string]int)
|
||||
|
||||
for kw, patterns := range idx.ByKeyword {
|
||||
if strings.Contains(textLower, kw) {
|
||||
for _, p := range patterns {
|
||||
scores[p.ID]++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(scores) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Collect and sort by score descending
|
||||
matches := make([]PatternMatch, 0, len(scores))
|
||||
for id, score := range scores {
|
||||
p := idx.ByID[id]
|
||||
matches = append(matches, PatternMatch{
|
||||
Pattern: p,
|
||||
KeywordHits: score,
|
||||
TotalKeywords: len(p.ObligationMatchKeywords),
|
||||
})
|
||||
}
|
||||
|
||||
// Simple insertion sort (small N)
|
||||
for i := 1; i < len(matches); i++ {
|
||||
for j := i; j > 0 && matches[j].KeywordHits > matches[j-1].KeywordHits; j-- {
|
||||
matches[j], matches[j-1] = matches[j-1], matches[j]
|
||||
}
|
||||
}
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
// PatternMatch represents a keyword-based match result.
|
||||
type PatternMatch struct {
|
||||
Pattern *ControlPattern
|
||||
KeywordHits int
|
||||
TotalKeywords int
|
||||
}
|
||||
|
||||
// Score returns the match score as a ratio of hits to total keywords.
|
||||
func (m PatternMatch) Score() float64 {
|
||||
if m.TotalKeywords == 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(m.KeywordHits) / float64(m.TotalKeywords)
|
||||
}
|
||||
|
||||
// ValidatePatternID checks if a pattern ID exists in the index.
|
||||
func (idx *ControlPatternIndex) ValidatePatternID(id string) bool {
|
||||
_, ok := idx.ByID[strings.ToUpper(id)]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Domains returns the list of unique domains that have patterns.
|
||||
func (idx *ControlPatternIndex) Domains() []string {
|
||||
domains := make([]string, 0, len(idx.ByDomain))
|
||||
for d := range idx.ByDomain {
|
||||
domains = append(domains, d)
|
||||
}
|
||||
return domains
|
||||
}
|
||||
384
ai-compliance-sdk/internal/ucca/pattern_loader_test.go
Normal file
384
ai-compliance-sdk/internal/ucca/pattern_loader_test.go
Normal file
@@ -0,0 +1,384 @@
|
||||
package ucca
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadControlPatterns_ValidFiles(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %v", err)
|
||||
}
|
||||
if idx == nil {
|
||||
t.Fatal("Expected non-nil index")
|
||||
}
|
||||
if len(idx.All) != 50 {
|
||||
t.Errorf("Expected 50 patterns, got %d", len(idx.All))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadControlPatterns_NoDuplicateIDs(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
seen := make(map[string]bool)
|
||||
for _, p := range idx.All {
|
||||
if seen[p.ID] {
|
||||
t.Errorf("Duplicate pattern ID: %s", p.ID)
|
||||
}
|
||||
seen[p.ID] = true
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPatternIndex_GetPattern(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
id string
|
||||
expected bool
|
||||
}{
|
||||
{"existing pattern CP-AUTH-001", "CP-AUTH-001", true},
|
||||
{"existing pattern CP-CRYP-001", "CP-CRYP-001", true},
|
||||
{"lowercase lookup", "cp-auth-001", true},
|
||||
{"non-existing pattern", "CP-FAKE-999", false},
|
||||
{"empty id", "", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p, ok := idx.GetPattern(tt.id)
|
||||
if ok != tt.expected {
|
||||
t.Errorf("GetPattern(%q): expected found=%v, got found=%v", tt.id, tt.expected, ok)
|
||||
}
|
||||
if ok && p.ID == "" {
|
||||
t.Error("Pattern found but has empty ID")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPatternIndex_GetPatternsByDomain(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
domain string
|
||||
minCount int
|
||||
}{
|
||||
{"AUTH", 3},
|
||||
{"CRYP", 3},
|
||||
{"DATA", 5},
|
||||
{"SEC", 3},
|
||||
{"COMP", 5},
|
||||
{"LOG", 2},
|
||||
{"INC", 3},
|
||||
{"AI", 2},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.domain, func(t *testing.T) {
|
||||
patterns := idx.GetPatternsByDomain(tt.domain)
|
||||
if len(patterns) < tt.minCount {
|
||||
t.Errorf("Domain %s: expected at least %d patterns, got %d",
|
||||
tt.domain, tt.minCount, len(patterns))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
emptyPatterns := idx.GetPatternsByDomain("NOPE")
|
||||
if len(emptyPatterns) != 0 {
|
||||
t.Errorf("Expected 0 patterns for unknown domain, got %d", len(emptyPatterns))
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPatternIndex_GetPatternsByCategory(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
authPatterns := idx.GetPatternsByCategory("authentication")
|
||||
if len(authPatterns) < 3 {
|
||||
t.Errorf("Expected at least 3 authentication patterns, got %d", len(authPatterns))
|
||||
}
|
||||
|
||||
encPatterns := idx.GetPatternsByCategory("encryption")
|
||||
if len(encPatterns) < 3 {
|
||||
t.Errorf("Expected at least 3 encryption patterns, got %d", len(encPatterns))
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPatternIndex_GetPatternsByTag(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
dpPatterns := idx.GetPatternsByTag("data_protection")
|
||||
if len(dpPatterns) < 3 {
|
||||
t.Errorf("Expected at least 3 data_protection tagged patterns, got %d", len(dpPatterns))
|
||||
}
|
||||
|
||||
secPatterns := idx.GetPatternsByTag("security")
|
||||
if len(secPatterns) >= 1 {
|
||||
// At least 1 pattern tagged with "security" — good
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPatternIndex_MatchByKeywords(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
text string
|
||||
expectPatternID string
|
||||
}{
|
||||
{
|
||||
"password related text",
|
||||
"Die Passwortrichtlinie muss sicherstellen, dass Anmeldedaten geschuetzt sind",
|
||||
"CP-AUTH-001",
|
||||
},
|
||||
{
|
||||
"encryption text",
|
||||
"Verschluesselung ruhender Daten muss mit AES-256 erfolgen",
|
||||
"CP-CRYP-001",
|
||||
},
|
||||
{
|
||||
"incident response text",
|
||||
"Ein Vorfall-Reaktionsplan muss fuer Sicherheitsvorfaelle bereitstehen",
|
||||
"CP-INC-001",
|
||||
},
|
||||
{
|
||||
"DSGVO consent text",
|
||||
"Die Einwilligung der betroffenen Person muss freiwillig erfolgen",
|
||||
"CP-DATA-004",
|
||||
},
|
||||
{
|
||||
"AI risk text",
|
||||
"KI-Systeme mit hohem Risiko muessen einer Konformitaetsbewertung unterzogen werden",
|
||||
"CP-AI-001",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
matches := idx.MatchByKeywords(tt.text)
|
||||
if len(matches) == 0 {
|
||||
t.Fatalf("Expected at least 1 match for text: %s", tt.text[:50])
|
||||
}
|
||||
|
||||
// Check if the expected pattern is in top 3 matches
|
||||
found := false
|
||||
for i, m := range matches {
|
||||
if i >= 3 {
|
||||
break
|
||||
}
|
||||
if m.Pattern.ID == tt.expectPatternID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
topIDs := make([]string, 0, 3)
|
||||
for i, m := range matches {
|
||||
if i >= 3 {
|
||||
break
|
||||
}
|
||||
topIDs = append(topIDs, m.Pattern.ID)
|
||||
}
|
||||
t.Errorf("Expected %s in top 3, got %v", tt.expectPatternID, topIDs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPatternIndex_MatchByKeywords_NoMatch(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
matches := idx.MatchByKeywords("xyzzy foobar baz completely unrelated text")
|
||||
if len(matches) != 0 {
|
||||
t.Errorf("Expected 0 matches for unrelated text, got %d", len(matches))
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatternMatch_Score(t *testing.T) {
|
||||
match := PatternMatch{
|
||||
KeywordHits: 3,
|
||||
TotalKeywords: 7,
|
||||
}
|
||||
|
||||
score := match.Score()
|
||||
expected := 3.0 / 7.0
|
||||
if score < expected-0.01 || score > expected+0.01 {
|
||||
t.Errorf("Expected score ~%.3f, got %.3f", expected, score)
|
||||
}
|
||||
|
||||
zeroMatch := PatternMatch{
|
||||
KeywordHits: 0,
|
||||
TotalKeywords: 0,
|
||||
}
|
||||
if zeroMatch.Score() != 0 {
|
||||
t.Errorf("Expected 0 score for zero keywords, got %f", zeroMatch.Score())
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPatternIndex_ValidatePatternID(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
if !idx.ValidatePatternID("CP-AUTH-001") {
|
||||
t.Error("Expected CP-AUTH-001 to be valid")
|
||||
}
|
||||
if idx.ValidatePatternID("CP-FAKE-999") {
|
||||
t.Error("Expected CP-FAKE-999 to be invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPatternIndex_Domains(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
domains := idx.Domains()
|
||||
if len(domains) < 5 {
|
||||
t.Errorf("Expected at least 5 domains, got %d: %v", len(domains), domains)
|
||||
}
|
||||
|
||||
// Check critical domains are present
|
||||
domainSet := make(map[string]bool)
|
||||
for _, d := range domains {
|
||||
domainSet[d] = true
|
||||
}
|
||||
|
||||
for _, required := range []string{"AUTH", "CRYP", "DATA", "SEC", "COMP"} {
|
||||
if !domainSet[required] {
|
||||
t.Errorf("Expected domain %s to be present", required)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPattern_FieldsNotEmpty(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
for _, p := range idx.All {
|
||||
t.Run(p.ID, func(t *testing.T) {
|
||||
if p.ID == "" {
|
||||
t.Error("Empty ID")
|
||||
}
|
||||
if p.Name == "" {
|
||||
t.Error("Empty Name")
|
||||
}
|
||||
if p.NameDE == "" {
|
||||
t.Error("Empty NameDE")
|
||||
}
|
||||
if p.Domain == "" {
|
||||
t.Error("Empty Domain")
|
||||
}
|
||||
if p.Category == "" {
|
||||
t.Error("Empty Category")
|
||||
}
|
||||
if len(p.Description) < 20 {
|
||||
t.Errorf("Description too short: %d chars", len(p.Description))
|
||||
}
|
||||
if len(p.ObjectiveTemplate) < 20 {
|
||||
t.Errorf("ObjectiveTemplate too short: %d chars", len(p.ObjectiveTemplate))
|
||||
}
|
||||
if len(p.RationaleTemplate) < 20 {
|
||||
t.Errorf("RationaleTemplate too short: %d chars", len(p.RationaleTemplate))
|
||||
}
|
||||
if len(p.RequirementsTemplate) < 2 {
|
||||
t.Errorf("Not enough requirements: %d", len(p.RequirementsTemplate))
|
||||
}
|
||||
if len(p.TestProcedureTemplate) < 1 {
|
||||
t.Errorf("Not enough test procedures: %d", len(p.TestProcedureTemplate))
|
||||
}
|
||||
if len(p.EvidenceTemplate) < 1 {
|
||||
t.Errorf("Not enough evidence items: %d", len(p.EvidenceTemplate))
|
||||
}
|
||||
if len(p.ObligationMatchKeywords) < 3 {
|
||||
t.Errorf("Not enough keywords: %d", len(p.ObligationMatchKeywords))
|
||||
}
|
||||
if len(p.Tags) < 1 {
|
||||
t.Errorf("Not enough tags: %d", len(p.Tags))
|
||||
}
|
||||
|
||||
validSeverities := map[string]bool{"low": true, "medium": true, "high": true, "critical": true}
|
||||
if !validSeverities[p.SeverityDefault] {
|
||||
t.Errorf("Invalid severity: %s", p.SeverityDefault)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPattern_IDDomainConsistency(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
for _, p := range idx.All {
|
||||
parts := strings.Split(p.ID, "-")
|
||||
if len(parts) != 3 {
|
||||
t.Errorf("Pattern %s: expected 3 parts in ID, got %d", p.ID, len(parts))
|
||||
continue
|
||||
}
|
||||
idDomain := parts[1]
|
||||
if idDomain != p.Domain {
|
||||
t.Errorf("Pattern %s: ID domain '%s' != field domain '%s'", p.ID, idDomain, p.Domain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPattern_ComposableWithValid(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
for _, p := range idx.All {
|
||||
for _, ref := range p.ComposableWith {
|
||||
if _, ok := idx.ByID[ref]; !ok {
|
||||
t.Errorf("Pattern %s: composable_with ref '%s' does not exist", p.ID, ref)
|
||||
}
|
||||
if ref == p.ID {
|
||||
t.Errorf("Pattern %s: composable_with contains self-reference", p.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPattern_KeywordsLowercase(t *testing.T) {
|
||||
idx, err := LoadControlPatterns()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load patterns: %v", err)
|
||||
}
|
||||
|
||||
for _, p := range idx.All {
|
||||
for _, kw := range p.ObligationMatchKeywords {
|
||||
if kw != strings.ToLower(kw) {
|
||||
t.Errorf("Pattern %s: keyword should be lowercase: '%s'", p.ID, kw)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
128
ai-compliance-sdk/policies/control_patterns/_pattern_schema.json
Normal file
128
ai-compliance-sdk/policies/control_patterns/_pattern_schema.json
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://breakpilot.ai/schemas/control-pattern-v1",
|
||||
"title": "Control Pattern Schema",
|
||||
"description": "Schema for YAML control pattern definitions. Pattern ID format: CP-{DOMAIN}-{NNN}",
|
||||
"type": "object",
|
||||
"required": ["version", "patterns"],
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+\\.[0-9]+$"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"patterns": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/ControlPattern" },
|
||||
"minItems": 1
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"ControlPattern": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id", "name", "name_de", "domain", "category", "description",
|
||||
"objective_template", "rationale_template", "requirements_template",
|
||||
"test_procedure_template", "evidence_template", "severity_default",
|
||||
"obligation_match_keywords", "tags"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"pattern": "^CP-[A-Z]+-[0-9]{3}$",
|
||||
"description": "Unique pattern ID. Format: CP-{DOMAIN}-{NNN}"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z][a-z0-9_]*$",
|
||||
"description": "Machine-readable name (snake_case)"
|
||||
},
|
||||
"name_de": {
|
||||
"type": "string",
|
||||
"description": "Human-readable German name"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"enum": ["AUTH", "CRYP", "NET", "DATA", "LOG", "ACC", "SEC", "INC", "AI", "COMP", "GOV", "LAB", "FIN", "TRD", "ENV", "HLT"],
|
||||
"description": "Domain code matching DOMAIN_KEYWORDS in control_generator.py"
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"description": "Functional category (e.g. authentication, encryption, incident)"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"minLength": 20,
|
||||
"description": "Brief description of what this pattern covers"
|
||||
},
|
||||
"objective_template": {
|
||||
"type": "string",
|
||||
"minLength": 20,
|
||||
"description": "Template for the control objective. May contain {placeholders}."
|
||||
},
|
||||
"rationale_template": {
|
||||
"type": "string",
|
||||
"minLength": 20,
|
||||
"description": "Template explaining why this control matters."
|
||||
},
|
||||
"requirements_template": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 2,
|
||||
"description": "Template requirements. May contain {placeholder:default} syntax."
|
||||
},
|
||||
"test_procedure_template": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 1
|
||||
},
|
||||
"evidence_template": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 1
|
||||
},
|
||||
"severity_default": {
|
||||
"type": "string",
|
||||
"enum": ["low", "medium", "high", "critical"]
|
||||
},
|
||||
"implementation_effort_default": {
|
||||
"type": "string",
|
||||
"enum": ["s", "m", "l", "xl"]
|
||||
},
|
||||
"open_anchor_refs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["framework", "ref"],
|
||||
"properties": {
|
||||
"framework": { "type": "string" },
|
||||
"ref": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"obligation_match_keywords": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 3,
|
||||
"description": "Keywords for matching obligations to this pattern (de + en)"
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 1
|
||||
},
|
||||
"composable_with": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^CP-[A-Z]+-[0-9]{3}$"
|
||||
},
|
||||
"description": "Pattern IDs that combine well with this one"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
1361
ai-compliance-sdk/policies/control_patterns/core_patterns.yaml
Normal file
1361
ai-compliance-sdk/policies/control_patterns/core_patterns.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,917 @@
|
||||
version: "1.0"
|
||||
description: >
|
||||
20 IT-Security Domain Patterns — spezialisierte Patterns fuer sichere
|
||||
Softwareentwicklung, API-Sicherheit, Container, Cloud und DevSecOps.
|
||||
|
||||
patterns:
|
||||
|
||||
# =========================================================================
|
||||
# SDLC — Secure Software Development (5 Patterns)
|
||||
# =========================================================================
|
||||
|
||||
- id: CP-SEC-006
|
||||
name: secure_sdlc
|
||||
name_de: Sicherer Software-Entwicklungslebenszyklus
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Integration von Sicherheitsanforderungen in alle Phasen des
|
||||
Software-Entwicklungslebenszyklus (Design, Implementierung, Test, Deployment).
|
||||
objective_template: >
|
||||
Sicherheitsanforderungen systematisch in alle Phasen der
|
||||
Softwareentwicklung integrieren (Security by Design).
|
||||
rationale_template: >
|
||||
Sicherheitsmaengel, die erst nach dem Deployment entdeckt werden,
|
||||
kosten bis zu 30x mehr als fruehe Erkennung. Ein sicherer SDLC
|
||||
reduziert Schwachstellen und beschleunigt die Time-to-Market.
|
||||
requirements_template:
|
||||
- "Sicherheitsanforderungen in User Stories / Tickets erfasst"
|
||||
- "Threat Modeling fuer neue Features und Architekturentscheidungen"
|
||||
- "Security Champions in jedem Entwicklungsteam"
|
||||
- "Sicherheits-Abnahme vor Produktiv-Deployment"
|
||||
- "Security-Retrospektiven bei Schwachstellenfunden"
|
||||
test_procedure_template:
|
||||
- "Review: 5 aktuelle User Stories auf Sicherheitsanforderungen pruefen"
|
||||
- "Nachweis eines Threat Models fuer eine neue Komponente"
|
||||
- "Pruefung ob Security Champion je Team benannt ist"
|
||||
evidence_template:
|
||||
- "Secure SDLC Policy"
|
||||
- "Threat-Model-Dokumentation"
|
||||
- "Security-Champion-Liste"
|
||||
severity_default: high
|
||||
implementation_effort_default: l
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP SAMM", ref: "v2.0" }
|
||||
- { framework: "NIST SP 800-218", ref: "SSDF" }
|
||||
obligation_match_keywords:
|
||||
- entwicklung
|
||||
- sdlc
|
||||
- software
|
||||
- design
|
||||
- security by design
|
||||
- threat model
|
||||
- development
|
||||
tags: [sdlc, development, security_by_design]
|
||||
composable_with: [CP-SEC-007, CP-SEC-008]
|
||||
|
||||
- id: CP-SEC-007
|
||||
name: code_review
|
||||
name_de: Code-Review und statische Analyse
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Systematische Pruefung von Quellcode durch Peer Reviews und
|
||||
automatisierte statische Analyse (SAST) vor Zusammenfuehrung.
|
||||
objective_template: >
|
||||
Sicherheitsschwachstellen im Quellcode durch manuelle Reviews
|
||||
und automatisierte statische Analyse vor dem Merge erkennen.
|
||||
rationale_template: >
|
||||
Automatisierte SAST-Tools erkennen bekannte Schwachstellenmuster
|
||||
zuverlaessig, waehrend manuelle Reviews Logikfehler und Design-
|
||||
Schwaechen aufdecken, die Tools uebersehen.
|
||||
requirements_template:
|
||||
- "SAST-Tool in CI/CD-Pipeline integriert (Build bricht bei kritischen Findings)"
|
||||
- "Peer Review fuer alle Aenderungen vor Merge in Hauptbranch"
|
||||
- "Mindestens ein Reviewer mit Security-Expertise fuer sicherheitsrelevante Aenderungen"
|
||||
- "SAST-Regelwerk regelmaessig aktualisiert"
|
||||
- "False-Positive-Management mit dokumentierter Begruendung"
|
||||
test_procedure_template:
|
||||
- "Pruefung der SAST-Integration in CI/CD"
|
||||
- "Review: 5 aktuelle Merge Requests auf Peer-Review-Nachweis pruefen"
|
||||
- "Stichprobe: SAST-Findings auf Behandlung pruefen"
|
||||
evidence_template:
|
||||
- "Code-Review-Richtlinie"
|
||||
- "SAST-Konfiguration und -Berichte"
|
||||
- "Merge-Request-Statistik mit Review-Nachweis"
|
||||
severity_default: high
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V14.1" }
|
||||
- { framework: "NIST SP 800-218", ref: "PW.7" }
|
||||
obligation_match_keywords:
|
||||
- code review
|
||||
- quellcode
|
||||
- statische analyse
|
||||
- sast
|
||||
- review
|
||||
- pruefung
|
||||
- source code
|
||||
tags: [code_review, sast, development]
|
||||
composable_with: [CP-SEC-006, CP-SEC-008]
|
||||
|
||||
- id: CP-SEC-008
|
||||
name: dependency_management
|
||||
name_de: Abhaengigkeitsmanagement
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Verwaltung und Ueberwachung von Softwareabhaengigkeiten (Libraries,
|
||||
Frameworks) auf bekannte Schwachstellen und Lizenzkonformitaet.
|
||||
objective_template: >
|
||||
Alle Softwareabhaengigkeiten inventarisieren, auf bekannte
|
||||
Schwachstellen ueberwachen und zeitnah aktualisieren.
|
||||
rationale_template: >
|
||||
Supply-Chain-Angriffe ueber kompromittierte Abhaengigkeiten nehmen
|
||||
stark zu. SBOM-Pflichten (CRA, NIS2) erfordern vollstaendige
|
||||
Transparenz ueber eingesetzte Komponenten.
|
||||
requirements_template:
|
||||
- "Software Bill of Materials (SBOM) fuer alle Anwendungen"
|
||||
- "Automatisierte Schwachstellenpruefung aller Abhaengigkeiten (SCA) in CI/CD"
|
||||
- "Kritische Schwachstellen in Abhaengigkeiten innerhalb von {critical_sla:72} Stunden behoben"
|
||||
- "Lizenzpruefung aller Abhaengigkeiten gegen Whitelist"
|
||||
- "Lock-Files versioniert und integritaetsgeschuetzt"
|
||||
test_procedure_template:
|
||||
- "SBOM auf Vollstaendigkeit pruefen"
|
||||
- "SCA-Bericht: Offene Schwachstellen in Abhaengigkeiten"
|
||||
- "Lizenz-Compliance-Bericht pruefen"
|
||||
evidence_template:
|
||||
- "SBOM (CycloneDX oder SPDX Format)"
|
||||
- "SCA-Bericht"
|
||||
- "Lizenz-Compliance-Bericht"
|
||||
severity_default: high
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V14.2" }
|
||||
- { framework: "NIST SP 800-218", ref: "PS.3" }
|
||||
obligation_match_keywords:
|
||||
- abhaengigkeit
|
||||
- dependency
|
||||
- sbom
|
||||
- library
|
||||
- framework
|
||||
- supply chain
|
||||
- komponente
|
||||
- sca
|
||||
tags: [dependency, sbom, supply_chain]
|
||||
composable_with: [CP-SEC-006, CP-COMP-005]
|
||||
|
||||
- id: CP-SEC-009
|
||||
name: input_validation
|
||||
name_de: Eingabevalidierung
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Validierung und Bereinigung aller Eingabedaten an Systemgrenzen
|
||||
zum Schutz vor Injection-Angriffen und Datenkorrumpierung.
|
||||
objective_template: >
|
||||
Alle Eingabedaten an Systemgrenzen validieren und bereinigen,
|
||||
um Injection-Angriffe und Datenkorrumpierung zu verhindern.
|
||||
rationale_template: >
|
||||
Injection-Schwachstellen (SQL, XSS, Command Injection) bleiben
|
||||
seit ueber einem Jahrzehnt in den OWASP Top 10. Konsequente
|
||||
Eingabevalidierung ist die effektivste Gegenmassnahme.
|
||||
requirements_template:
|
||||
- "Whitelist-Validierung fuer alle Benutzereingaben"
|
||||
- "Parametrisierte Queries fuer alle Datenbankzugriffe (kein String-Concat)"
|
||||
- "Output-Encoding kontextabhaengig (HTML, JS, URL, SQL)"
|
||||
- "Maximale Laengen und Typbeschraenkungen fuer alle Eingabefelder"
|
||||
- "Server-seitige Validierung (Client-seitige Validierung allein genuegt nicht)"
|
||||
test_procedure_template:
|
||||
- "DAST-Scan auf Injection-Schwachstellen"
|
||||
- "Code-Review: Stichprobe auf parametrisierte Queries"
|
||||
- "Test: XSS-Payload in Eingabefelder eingeben"
|
||||
evidence_template:
|
||||
- "DAST-Scan-Bericht"
|
||||
- "Code-Review-Ergebnis (Injection-Bereich)"
|
||||
severity_default: critical
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V5.1, V5.2, V5.3" }
|
||||
- { framework: "OWASP Top 10", ref: "A03:2021 Injection" }
|
||||
obligation_match_keywords:
|
||||
- eingabe
|
||||
- validierung
|
||||
- input
|
||||
- injection
|
||||
- xss
|
||||
- sanitization
|
||||
- bereinigung
|
||||
tags: [input_validation, injection, application_security]
|
||||
composable_with: [CP-SEC-010, CP-SEC-007]
|
||||
|
||||
- id: CP-SEC-010
|
||||
name: error_handling
|
||||
name_de: Fehlerbehandlung und Informationspreisgabe
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Sichere Fehlerbehandlung, die keine sensitiven Informationen
|
||||
in Fehlermeldungen, Stack Traces oder Logs preisgibt.
|
||||
objective_template: >
|
||||
Fehler sicher behandeln, sodass Nutzern hilfreiche aber keine
|
||||
sicherheitsrelevanten Informationen angezeigt werden.
|
||||
rationale_template: >
|
||||
Detaillierte Fehlermeldungen in Produktion offenbaren Technologie-Stack,
|
||||
Datenbankstruktur und interne Pfade — wertvolle Informationen fuer
|
||||
Angreifer zur Angriffsvorbereitung.
|
||||
requirements_template:
|
||||
- "Generische Fehlermeldungen fuer Endnutzer in Produktion"
|
||||
- "Detaillierte Fehler nur in internen Logs (nicht in API-Responses)"
|
||||
- "Keine Stack Traces, SQL-Queries oder interne Pfade in Responses"
|
||||
- "Custom Error Pages fuer HTTP 4xx/5xx"
|
||||
- "Zentrales Exception-Handling in allen Anwendungen"
|
||||
test_procedure_template:
|
||||
- "Provozierung von Fehlern und Pruefung der Response auf sensitive Daten"
|
||||
- "Pruefung der Error Pages auf Informationspreisgabe"
|
||||
- "Review: Exception-Handling-Muster im Code"
|
||||
evidence_template:
|
||||
- "Error-Handling-Richtlinie"
|
||||
- "Penetrationstest-Bericht (Information Disclosure)"
|
||||
severity_default: medium
|
||||
implementation_effort_default: s
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V7.4" }
|
||||
- { framework: "OWASP Top 10", ref: "A05:2021 Security Misconfiguration" }
|
||||
obligation_match_keywords:
|
||||
- fehler
|
||||
- error
|
||||
- fehlermeldung
|
||||
- informationspreisgabe
|
||||
- information disclosure
|
||||
- stack trace
|
||||
- exception
|
||||
tags: [error_handling, information_disclosure, application_security]
|
||||
composable_with: [CP-SEC-009, CP-LOG-001]
|
||||
|
||||
# =========================================================================
|
||||
# API & Web Security (3 Patterns)
|
||||
# =========================================================================
|
||||
|
||||
- id: CP-SEC-011
|
||||
name: api_security
|
||||
name_de: API-Sicherheit
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Absicherung von APIs durch Authentifizierung, Rate Limiting,
|
||||
Eingabevalidierung und Zugriffskontrolle.
|
||||
objective_template: >
|
||||
Alle APIs durch angemessene Authentifizierung, Autorisierung,
|
||||
Rate Limiting und Eingabevalidierung schuetzen.
|
||||
rationale_template: >
|
||||
APIs sind die primaere Angriffsflaeche moderner Anwendungen.
|
||||
Ungeschuetzte APIs ermoeglichen Massendatenabfluss, Missbrauch
|
||||
und Denial-of-Service.
|
||||
requirements_template:
|
||||
- "Authentifizierung fuer alle nicht-oeffentlichen API-Endpunkte"
|
||||
- "Autorisierung auf Objektebene (BOLA/IDOR-Schutz)"
|
||||
- "Rate Limiting und Throttling implementiert"
|
||||
- "API-Schema-Validierung (OpenAPI/JSON Schema)"
|
||||
- "API-Versionierung und Deprecation-Policy"
|
||||
- "CORS-Policy restriktiv konfiguriert"
|
||||
test_procedure_template:
|
||||
- "API-Sicherheits-Scan (z.B. OWASP ZAP)"
|
||||
- "Test: Zugriff auf fremde Ressourcen via IDOR"
|
||||
- "Test: Rate Limit ueberschreiten"
|
||||
evidence_template:
|
||||
- "API-Sicherheitsrichtlinie"
|
||||
- "API-Security-Scan-Bericht"
|
||||
- "OpenAPI-Spezifikation"
|
||||
severity_default: high
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP API Security Top 10", ref: "2023 Edition" }
|
||||
- { framework: "OWASP ASVS", ref: "V13.1" }
|
||||
obligation_match_keywords:
|
||||
- api
|
||||
- schnittstelle
|
||||
- endpunkt
|
||||
- rest
|
||||
- graphql
|
||||
- interface
|
||||
- webservice
|
||||
tags: [api, security, web]
|
||||
composable_with: [CP-AUTH-003, CP-SEC-009]
|
||||
|
||||
- id: CP-SEC-012
|
||||
name: csrf_protection
|
||||
name_de: CSRF-Schutz
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Schutz vor Cross-Site Request Forgery durch Token-basierte
|
||||
Validierung und SameSite-Cookie-Attribute.
|
||||
objective_template: >
|
||||
Webanwendungen gegen Cross-Site Request Forgery schuetzen, sodass
|
||||
unautorisierte Aktionen im Namen authentifizierter Nutzer verhindert werden.
|
||||
rationale_template: >
|
||||
CSRF ermoeglicht es Angreifern, authentifizierte Nutzer zu
|
||||
unbeabsichtigten Aktionen zu verleiten — z.B. Passwortaenderung
|
||||
oder Datenloeschung.
|
||||
requirements_template:
|
||||
- "CSRF-Token fuer alle zustandsaendernden Requests (POST, PUT, DELETE)"
|
||||
- "SameSite=Strict oder Lax fuer Session-Cookies"
|
||||
- "Double-Submit-Cookie-Pattern als Alternative wo CSRF-Tokens nicht moeglich"
|
||||
- "Pruefung des Origin- oder Referer-Headers fuer kritische Aktionen"
|
||||
test_procedure_template:
|
||||
- "Test: Zustandsaendernden Request ohne CSRF-Token senden"
|
||||
- "Pruefung der SameSite-Cookie-Attribute"
|
||||
- "DAST-Scan: CSRF-Findings auswerten"
|
||||
evidence_template:
|
||||
- "DAST-Scan-Bericht (CSRF-Bereich)"
|
||||
- "Cookie-Konfiguration"
|
||||
severity_default: medium
|
||||
implementation_effort_default: s
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V4.2.2" }
|
||||
- { framework: "OWASP Top 10", ref: "A01:2021 Broken Access Control" }
|
||||
obligation_match_keywords:
|
||||
- csrf
|
||||
- cross-site
|
||||
- request forgery
|
||||
- samesite
|
||||
- token
|
||||
- formular
|
||||
tags: [csrf, web_security, application_security]
|
||||
composable_with: [CP-SEC-009, CP-SEC-011]
|
||||
|
||||
- id: CP-SEC-013
|
||||
name: content_security_policy
|
||||
name_de: Content Security Policy
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Implementierung einer Content Security Policy (CSP) zum Schutz
|
||||
vor XSS, Clickjacking und anderen Browser-basierten Angriffen.
|
||||
objective_template: >
|
||||
Browser-basierte Angriffe durch eine restriktive Content Security
|
||||
Policy (CSP) und Security-Header begrenzen.
|
||||
rationale_template: >
|
||||
CSP ist die effektivste clientseitige Verteidigung gegen XSS-Angriffe
|
||||
und reduziert die Auswirkungen von Injection-Schwachstellen erheblich.
|
||||
requirements_template:
|
||||
- "CSP-Header mit restriktiven Direktiven (kein unsafe-inline ohne Nonce)"
|
||||
- "X-Frame-Options oder frame-ancestors gegen Clickjacking"
|
||||
- "X-Content-Type-Options: nosniff"
|
||||
- "Referrer-Policy konfiguriert"
|
||||
- "CSP-Report-URI fuer Monitoring konfiguriert"
|
||||
test_procedure_template:
|
||||
- "Security-Header-Scan (z.B. securityheaders.com)"
|
||||
- "Test: Inline-Script-Ausfuehrung ohne Nonce (muss blockiert werden)"
|
||||
- "Review: CSP-Violation-Reports der letzten 30 Tage"
|
||||
evidence_template:
|
||||
- "Security-Header-Scan-Ergebnis"
|
||||
- "CSP-Konfiguration"
|
||||
- "CSP-Violation-Report-Statistik"
|
||||
severity_default: medium
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V14.4" }
|
||||
obligation_match_keywords:
|
||||
- csp
|
||||
- content security
|
||||
- header
|
||||
- xss
|
||||
- clickjacking
|
||||
- browser
|
||||
- security header
|
||||
tags: [csp, web_security, headers]
|
||||
composable_with: [CP-SEC-009, CP-SEC-012]
|
||||
|
||||
# =========================================================================
|
||||
# Container & Cloud Security (3 Patterns)
|
||||
# =========================================================================
|
||||
|
||||
- id: CP-SEC-014
|
||||
name: container_security
|
||||
name_de: Container-Sicherheit
|
||||
domain: SEC
|
||||
category: system
|
||||
description: >
|
||||
Absicherung von Container-Umgebungen (Docker, Kubernetes) durch
|
||||
Image-Scanning, Laufzeitschutz und sichere Konfiguration.
|
||||
objective_template: >
|
||||
Container-Umgebungen durch Image-Haertung, Laufzeitschutz und
|
||||
Netzwerk-Policies sicher konfigurieren und betreiben.
|
||||
rationale_template: >
|
||||
Container mit bekannten Schwachstellen oder ueberprivilegierter
|
||||
Konfiguration sind ein haeufiger Angriffsvektor. Die geteilte
|
||||
Kernel-Architektur erfordert besondere Sicherheitsmassnahmen.
|
||||
requirements_template:
|
||||
- "Base-Image-Scanning in CI/CD-Pipeline"
|
||||
- "Keine Container mit Root-Privileges in Produktion"
|
||||
- "Read-Only-Filesystem wo moeglich"
|
||||
- "Netzwerk-Policies zwischen Container-Namespaces"
|
||||
- "Image-Registry nur aus vertrauenswuerdigen Quellen"
|
||||
- "Automatische Rebuilds bei bekannten CVEs in Base Images"
|
||||
test_procedure_template:
|
||||
- "Container-Image-Scan aller Produktiv-Images"
|
||||
- "Pruefung: Kein Container laeuft als Root"
|
||||
- "Pruefung der Netzwerk-Policies"
|
||||
evidence_template:
|
||||
- "Container-Sicherheitsrichtlinie"
|
||||
- "Image-Scan-Bericht"
|
||||
- "Kubernetes-/Docker-Konfiguration"
|
||||
severity_default: high
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "NIST SP 800-190", ref: "Container Security Guide" }
|
||||
obligation_match_keywords:
|
||||
- container
|
||||
- docker
|
||||
- kubernetes
|
||||
- k8s
|
||||
- image
|
||||
- pod
|
||||
- deployment
|
||||
tags: [container, docker, kubernetes]
|
||||
composable_with: [CP-SEC-003, CP-SEC-015]
|
||||
|
||||
- id: CP-SEC-015
|
||||
name: cloud_security_posture
|
||||
name_de: Cloud-Sicherheitslage
|
||||
domain: SEC
|
||||
category: system
|
||||
description: >
|
||||
Kontinuierliche Ueberwachung und Durchsetzung von Sicherheitsrichtlinien
|
||||
in Cloud-Umgebungen (IaaS, PaaS, SaaS).
|
||||
objective_template: >
|
||||
Cloud-Ressourcen durch automatisierte Richtlinienpruefung und
|
||||
Konfigurationsmanagement sicher konfigurieren und ueberwachen.
|
||||
rationale_template: >
|
||||
Cloud-Fehlkonfigurationen (offene S3-Buckets, oeffentlich erreichbare
|
||||
Datenbanken) sind fuer einen Grossteil der Cloud-Datenpannen verantwortlich.
|
||||
requirements_template:
|
||||
- "Cloud Security Posture Management (CSPM) Tool im Einsatz"
|
||||
- "Automatisierte Pruefung auf oeffentlich erreichbare Ressourcen"
|
||||
- "Verschluesselung aller Cloud-Storage-Dienste erzwungen"
|
||||
- "IAM-Policies nach Least-Privilege konfiguriert"
|
||||
- "Cloud-Trail / Audit-Logging aktiviert"
|
||||
- "Multi-Region-Backup fuer kritische Daten"
|
||||
test_procedure_template:
|
||||
- "CSPM-Scan der Cloud-Umgebung"
|
||||
- "Pruefung auf oeffentlich erreichbare Ressourcen"
|
||||
- "Review der IAM-Policies auf ueberprivilegierte Accounts"
|
||||
evidence_template:
|
||||
- "CSPM-Bericht"
|
||||
- "Cloud-IAM-Policy-Review"
|
||||
- "Cloud-Audit-Log-Konfiguration"
|
||||
severity_default: high
|
||||
implementation_effort_default: l
|
||||
open_anchor_refs:
|
||||
- { framework: "NIST SP 800-144", ref: "Cloud Computing Guide" }
|
||||
obligation_match_keywords:
|
||||
- cloud
|
||||
- iaas
|
||||
- paas
|
||||
- saas
|
||||
- aws
|
||||
- azure
|
||||
- gcp
|
||||
- cloud security
|
||||
tags: [cloud, cspm, infrastructure]
|
||||
composable_with: [CP-SEC-014, CP-CRYP-001]
|
||||
|
||||
- id: CP-SEC-016
|
||||
name: infrastructure_as_code
|
||||
name_de: Infrastruktur als Code
|
||||
domain: SEC
|
||||
category: system
|
||||
description: >
|
||||
Verwaltung der gesamten Infrastruktur als versionierter Code mit
|
||||
Sicherheitspruefung vor dem Deployment.
|
||||
objective_template: >
|
||||
Infrastruktur-Konfigurationen als versionierten Code verwalten
|
||||
und vor dem Deployment automatisiert auf Sicherheit pruefen.
|
||||
rationale_template: >
|
||||
IaC ermoeglicht reproduzierbare, audierbare und sicherheitsgeprufte
|
||||
Infrastruktur. Manuelle Konfiguration fuehrt zu Configuration Drift
|
||||
und nicht-nachvollziehbaren Aenderungen.
|
||||
requirements_template:
|
||||
- "Alle Infrastruktur-Konfigurationen in Git versioniert"
|
||||
- "IaC-Security-Scanner in CI/CD (z.B. tfsec, checkov)"
|
||||
- "Keine manuellen Aenderungen an Produktiv-Infrastruktur"
|
||||
- "Review-Prozess fuer Infrastruktur-Aenderungen"
|
||||
- "State-Dateien verschluesselt und zugriffsbeschraenkt"
|
||||
test_procedure_template:
|
||||
- "IaC-Security-Scan-Ergebnis pruefen"
|
||||
- "Vergleich: Ist-Zustand vs. Code-Zustand (Drift-Detection)"
|
||||
- "Review: Letzte 5 Infrastruktur-Aenderungen auf Audit-Trail pruefen"
|
||||
evidence_template:
|
||||
- "IaC-Repository (Zugangsnachweis)"
|
||||
- "IaC-Security-Scan-Bericht"
|
||||
- "Drift-Detection-Ergebnis"
|
||||
severity_default: medium
|
||||
implementation_effort_default: l
|
||||
open_anchor_refs:
|
||||
- { framework: "NIST SP 800-128", ref: "Configuration Management" }
|
||||
obligation_match_keywords:
|
||||
- infrastruktur
|
||||
- terraform
|
||||
- ansible
|
||||
- konfiguration
|
||||
- infrastructure
|
||||
- iac
|
||||
- deployment
|
||||
- provisioning
|
||||
tags: [iac, infrastructure, devops]
|
||||
composable_with: [CP-SEC-003, CP-COMP-002]
|
||||
|
||||
# =========================================================================
|
||||
# Identity & Secrets (3 Patterns)
|
||||
# =========================================================================
|
||||
|
||||
- id: CP-AUTH-005
|
||||
name: secrets_management
|
||||
name_de: Secrets-Management
|
||||
domain: AUTH
|
||||
category: authentication
|
||||
description: >
|
||||
Sichere Verwaltung von Secrets (API-Keys, Datenbank-Passwoerter,
|
||||
Zertifikate) ueber ihren gesamten Lebenszyklus.
|
||||
objective_template: >
|
||||
Secrets sicher speichern, verteilen und rotieren — keine Secrets
|
||||
im Quellcode, in Umgebungsvariablen auf Disk oder in Logs.
|
||||
rationale_template: >
|
||||
Geleakte Secrets in Git-Repositories sind eine der haeufigsten
|
||||
Ursachen fuer Datenpannen. Automatisiertes Secrets-Management
|
||||
eliminiert menschliche Fehler bei der Secret-Verwaltung.
|
||||
requirements_template:
|
||||
- "Secrets in einem dedizierten Secrets Manager (Vault, AWS SM, etc.)"
|
||||
- "Keine Secrets in Quellcode, Docker-Images oder CI/CD-Logs"
|
||||
- "Pre-Commit-Hook: Automatische Secret-Erkennung (z.B. gitleaks)"
|
||||
- "Automatische Rotation fuer alle maschinellen Secrets"
|
||||
- "Audit-Log fuer jeden Secret-Zugriff"
|
||||
test_procedure_template:
|
||||
- "Repository-Scan auf eingebettete Secrets (gitleaks, trufflehog)"
|
||||
- "Pruefung der Secrets-Manager-Konfiguration"
|
||||
- "Stichprobe: 5 Secrets auf Rotationshistorie pruefen"
|
||||
evidence_template:
|
||||
- "Secrets-Management-Richtlinie"
|
||||
- "Secret-Scan-Bericht (Repository)"
|
||||
- "Secrets-Manager-Audit-Log"
|
||||
severity_default: critical
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V6.4" }
|
||||
- { framework: "NIST SP 800-57", ref: "Part 1" }
|
||||
obligation_match_keywords:
|
||||
- secret
|
||||
- api key
|
||||
- passwort
|
||||
- credential
|
||||
- token
|
||||
- zertifikat
|
||||
- schluessel
|
||||
- vault
|
||||
tags: [secrets, vault, credential]
|
||||
composable_with: [CP-CRYP-003, CP-SEC-006]
|
||||
|
||||
- id: CP-AUTH-006
|
||||
name: service_authentication
|
||||
name_de: Service-zu-Service-Authentifizierung
|
||||
domain: AUTH
|
||||
category: authentication
|
||||
description: >
|
||||
Authentifizierung und Autorisierung zwischen internen Diensten
|
||||
(Microservices) durch mTLS, JWT oder Service Mesh.
|
||||
objective_template: >
|
||||
Interne Service-Kommunikation authentifizieren und autorisieren,
|
||||
um Lateral Movement bei kompromittierten Diensten zu verhindern.
|
||||
rationale_template: >
|
||||
Ohne Service-Authentifizierung kann ein kompromittierter Dienst
|
||||
ungehindert auf alle anderen internen Dienste zugreifen.
|
||||
requirements_template:
|
||||
- "Mutual TLS (mTLS) oder JWT-basierte Authentifizierung zwischen Services"
|
||||
- "Service-Identitaeten zentral verwaltet und automatisch rotiert"
|
||||
- "Autorisierung auf API-Ebene (nicht nur Netzwerk-Ebene)"
|
||||
- "Service Mesh oder API Gateway fuer zentrales Policy-Enforcement"
|
||||
test_procedure_template:
|
||||
- "Test: Nicht-authentifizierter Service-Zugriff (muss abgelehnt werden)"
|
||||
- "Pruefung der mTLS-Konfiguration"
|
||||
- "Review: Service-Autorisierungs-Policies"
|
||||
evidence_template:
|
||||
- "Service-Authentifizierungskonzept"
|
||||
- "mTLS/JWT-Konfiguration"
|
||||
- "Service-Mesh-Policies"
|
||||
severity_default: high
|
||||
implementation_effort_default: l
|
||||
open_anchor_refs:
|
||||
- { framework: "NIST SP 800-204", ref: "Microservices Security" }
|
||||
obligation_match_keywords:
|
||||
- service
|
||||
- microservice
|
||||
- mtls
|
||||
- service mesh
|
||||
- internal
|
||||
- api gateway
|
||||
- dienst
|
||||
tags: [service_auth, microservices, mtls]
|
||||
composable_with: [CP-CRYP-002, CP-SEC-011]
|
||||
|
||||
- id: CP-AUTH-007
|
||||
name: identity_lifecycle
|
||||
name_de: Identitaets-Lebenszyklus
|
||||
domain: AUTH
|
||||
category: identity
|
||||
description: >
|
||||
Verwaltung des vollstaendigen Lebenszyklus digitaler Identitaeten
|
||||
vom Onboarding ueber Rollenaenderungen bis zum Offboarding.
|
||||
objective_template: >
|
||||
Digitale Identitaeten vom Onboarding bis zum Offboarding
|
||||
lueckenlos und zeitnah verwalten.
|
||||
rationale_template: >
|
||||
Verwaiste Konten nach Mitarbeiter-Austritt sind ein haeufiger
|
||||
Angriffsvektor. Unvollstaendiges Offboarding fuehrt zu
|
||||
unautorisiertem Zugriff und Compliance-Verstoessen.
|
||||
requirements_template:
|
||||
- "Automatisiertes Onboarding mit Standardrechten je Rolle"
|
||||
- "Offboarding-Checkliste mit Entzug aller Zugaenge innerhalb {offboard_hours:24} Stunden"
|
||||
- "Automatische Deaktivierung bei Vertragsende"
|
||||
- "Regelmaessige Kontenbereinigung auf verwaiste Accounts"
|
||||
- "Gastkonten mit automatischem Ablaufdatum"
|
||||
test_procedure_template:
|
||||
- "Stichprobe: 3 kuerzlich ausgeschiedene Mitarbeiter — alle Zugaenge deaktiviert?"
|
||||
- "Scan auf verwaiste Konten (keine Anmeldung > 90 Tage)"
|
||||
- "Pruefung der Offboarding-Checkliste"
|
||||
evidence_template:
|
||||
- "Onboarding-/Offboarding-Prozessbeschreibung"
|
||||
- "Bericht verwaiste Konten"
|
||||
- "Offboarding-Checklisten (Stichprobe)"
|
||||
severity_default: high
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "NIST SP 800-53", ref: "AC-2, PS-4" }
|
||||
obligation_match_keywords:
|
||||
- identitaet
|
||||
- onboarding
|
||||
- offboarding
|
||||
- lebenszyklus
|
||||
- lifecycle
|
||||
- konto
|
||||
- account
|
||||
- benutzer
|
||||
tags: [identity, lifecycle, onboarding]
|
||||
composable_with: [CP-ACC-001, CP-AUTH-001]
|
||||
|
||||
# =========================================================================
|
||||
# DevSecOps & CI/CD (3 Patterns)
|
||||
# =========================================================================
|
||||
|
||||
- id: CP-SEC-017
|
||||
name: cicd_security
|
||||
name_de: CI/CD-Pipeline-Sicherheit
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Absicherung der CI/CD-Pipeline gegen Manipulation, Credential-Leaks
|
||||
und Supply-Chain-Angriffe.
|
||||
objective_template: >
|
||||
CI/CD-Pipelines gegen Manipulation absichern und als vertrauenswuerdige
|
||||
Deployment-Kette etablieren.
|
||||
rationale_template: >
|
||||
Eine kompromittierte CI/CD-Pipeline ermoeglicht das Einschleusen von
|
||||
Schadcode in Produktionssysteme ueber den vertrauenswuerdigen Build-Prozess.
|
||||
requirements_template:
|
||||
- "Pipeline-Konfiguration versioniert und nur ueber Review aenderbar"
|
||||
- "Secrets in CI/CD ueber Secrets Manager (nicht als Umgebungsvariablen)"
|
||||
- "Build-Artefakte signiert und integritaetsgeprueft"
|
||||
- "Minimale Berechtigungen fuer CI/CD-Runner"
|
||||
- "Audit-Log aller Pipeline-Ausfuehrungen"
|
||||
test_procedure_template:
|
||||
- "Review: Pipeline-Konfiguration auf Secrets-Exposition pruefen"
|
||||
- "Pruefung der Runner-Berechtigungen"
|
||||
- "Pruefung der Artefakt-Signierung"
|
||||
evidence_template:
|
||||
- "CI/CD-Sicherheitsrichtlinie"
|
||||
- "Pipeline-Konfiguration (Git-Review)"
|
||||
- "Artefakt-Signierungs-Nachweis"
|
||||
severity_default: high
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "NIST SP 800-218", ref: "PO.3, PS.1" }
|
||||
obligation_match_keywords:
|
||||
- pipeline
|
||||
- ci/cd
|
||||
- build
|
||||
- deployment
|
||||
- continuous
|
||||
- integration
|
||||
- delivery
|
||||
tags: [cicd, pipeline, devsecops]
|
||||
composable_with: [CP-SEC-006, CP-AUTH-005]
|
||||
|
||||
- id: CP-SEC-018
|
||||
name: dast_scanning
|
||||
name_de: Dynamische Anwendungssicherheitstests
|
||||
domain: SEC
|
||||
category: application
|
||||
description: >
|
||||
Automatisierte dynamische Sicherheitstests (DAST) gegen laufende
|
||||
Anwendungen zur Erkennung von Laufzeit-Schwachstellen.
|
||||
objective_template: >
|
||||
Laufende Anwendungen automatisiert auf Sicherheitsschwachstellen
|
||||
testen, die nur zur Laufzeit erkennbar sind.
|
||||
rationale_template: >
|
||||
DAST erkennt Schwachstellen, die statische Analyse nicht findet:
|
||||
Fehlkonfigurationen, fehlende Security-Header, CORS-Probleme und
|
||||
Authentifizierungsfehler im Deployment-Kontext.
|
||||
requirements_template:
|
||||
- "Automatisierter DAST-Scan (min. {scan_interval:woechentlich}) gegen Staging"
|
||||
- "Vollstaendiger DAST-Scan vor jedem Major Release"
|
||||
- "Kritische DAST-Findings blockieren Produktiv-Deployment"
|
||||
- "Authentifizierte Scans fuer geschuetzte Bereiche"
|
||||
- "DAST-Tool-Konfiguration regelmaessig aktualisiert"
|
||||
test_procedure_template:
|
||||
- "Review des letzten DAST-Berichts"
|
||||
- "Pruefung: Werden kritische Findings tatsaechlich behoben?"
|
||||
- "Verifizierung der Scan-Abdeckung (alle Endpunkte)"
|
||||
evidence_template:
|
||||
- "DAST-Scan-Bericht"
|
||||
- "Behebungsprotokoll fuer DAST-Findings"
|
||||
severity_default: medium
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V14.2" }
|
||||
- { framework: "NIST SP 800-53", ref: "SA-11" }
|
||||
obligation_match_keywords:
|
||||
- dast
|
||||
- dynamisch
|
||||
- sicherheitstest
|
||||
- penetrationstest
|
||||
- runtime
|
||||
- scanning
|
||||
- web scanner
|
||||
tags: [dast, scanning, testing]
|
||||
composable_with: [CP-SEC-007, CP-SEC-002]
|
||||
|
||||
- id: CP-LOG-003
|
||||
name: secure_logging_no_pii
|
||||
name_de: Datenschutzkonformes Logging
|
||||
domain: LOG
|
||||
category: logging
|
||||
description: >
|
||||
Sicherstellung, dass Log-Daten keine personenbezogenen Daten
|
||||
enthalten und dennoch fuer forensische Analyse nutzbar sind.
|
||||
objective_template: >
|
||||
Log-Daten so gestalten, dass sie fuer Sicherheitsanalyse und
|
||||
Debugging nutzbar sind, ohne personenbezogene Daten preiszugeben.
|
||||
rationale_template: >
|
||||
Logs mit personenbezogenen Daten schaffen neue DSGVO-Verarbeitungen,
|
||||
erhoehen die Angriffsflaeche und erschweren die Weitergabe an
|
||||
Dritte (z.B. SOC-Provider).
|
||||
requirements_template:
|
||||
- "Pseudonymisierung aller Nutzer-IDs in Logs"
|
||||
- "Kein Logging von Passwoertern, Tokens, Kreditkartendaten"
|
||||
- "IP-Adressen maximal gekuerzt geloggt (Privacy-Modus)"
|
||||
- "Log-Retention gemaess Loeschkonzept"
|
||||
- "Automatisierte PII-Erkennung in Log-Streams"
|
||||
test_procedure_template:
|
||||
- "Stichprobe: 100 Log-Eintraege auf PII-Freiheit pruefen"
|
||||
- "Test: Login mit Passwort — Passwort darf nicht in Logs erscheinen"
|
||||
- "Pruefung der Log-Retention-Konfiguration"
|
||||
evidence_template:
|
||||
- "Logging-Richtlinie (DSGVO-konform)"
|
||||
- "Log-Stichproben-Analyse"
|
||||
- "PII-Scanner-Konfiguration"
|
||||
severity_default: medium
|
||||
implementation_effort_default: m
|
||||
open_anchor_refs:
|
||||
- { framework: "OWASP ASVS", ref: "V7.1.3" }
|
||||
- { framework: "ENISA Guidelines", ref: "Privacy-preserving Logging" }
|
||||
obligation_match_keywords:
|
||||
- logging
|
||||
- personenbezogen
|
||||
- protokollierung
|
||||
- pii
|
||||
- pseudonymisierung
|
||||
- datenschutz
|
||||
- log
|
||||
tags: [logging, privacy, gdpr]
|
||||
composable_with: [CP-LOG-001, CP-DATA-002]
|
||||
|
||||
# =========================================================================
|
||||
# Data & Privacy (3 Patterns)
|
||||
# =========================================================================
|
||||
|
||||
- id: CP-DATA-006
|
||||
name: data_subject_rights
|
||||
name_de: Betroffenenrechte
|
||||
domain: DATA
|
||||
category: data_protection
|
||||
description: >
|
||||
Prozesse zur Erfuellung der Betroffenenrechte (Auskunft, Berichtigung,
|
||||
Loeschung, Datenportabilitaet) gemaess Art. 15-22 DSGVO.
|
||||
objective_template: >
|
||||
Betroffenenrechte fristgerecht (max. 30 Tage) erfuellen und den
|
||||
gesamten Prozess nachweisbar dokumentieren.
|
||||
rationale_template: >
|
||||
Die Nichterfuellung von Betroffenenrechten ist einer der haeufigsten
|
||||
DSGVO-Beschwerdgruende bei Aufsichtsbehoerden und kann zu
|
||||
empfindlichen Bussgeldern fuehren.
|
||||
requirements_template:
|
||||
- "Anfrage-Kanal fuer Betroffenenrechte eingerichtet und dokumentiert"
|
||||
- "Identitaetspruefung vor Auskunftserteilung"
|
||||
- "Fristenueberwachung: Antwort innerhalb von {response_days:30} Tagen"
|
||||
- "Automatisierte Datenextraktion fuer Auskunfts- und Portabilitaetsanfragen"
|
||||
- "Loeschprozess fuer alle Systeme (inkl. Backups) definiert"
|
||||
- "Dokumentation aller bearbeiteten Anfragen"
|
||||
test_procedure_template:
|
||||
- "Test: Auskunftsanfrage stellen und Antwort auf Vollstaendigkeit pruefen"
|
||||
- "Test: Loeschanfrage stellen und Umsetzung in allen Systemen verifizieren"
|
||||
- "Pruefung der Fristeneinhaltung der letzten 10 Anfragen"
|
||||
evidence_template:
|
||||
- "Betroffenenrechte-Prozessbeschreibung"
|
||||
- "Bearbeitungsprotokoll (anonymisiert)"
|
||||
- "Anfrageformular / Kontaktkanal-Dokumentation"
|
||||
severity_default: high
|
||||
implementation_effort_default: l
|
||||
open_anchor_refs:
|
||||
- { framework: "ENISA Guidelines", ref: "Data Subject Rights" }
|
||||
obligation_match_keywords:
|
||||
- betroffenenrechte
|
||||
- auskunft
|
||||
- loeschung
|
||||
- berichtigung
|
||||
- datenportabilitaet
|
||||
- widerspruch
|
||||
- data subject
|
||||
tags: [data_protection, dsr, gdpr]
|
||||
composable_with: [CP-DATA-003, CP-DATA-004]
|
||||
|
||||
- id: CP-DATA-007
|
||||
name: data_transfer_safeguards
|
||||
name_de: Datentransfer-Schutzmassnahmen
|
||||
domain: DATA
|
||||
category: data_protection
|
||||
description: >
|
||||
Schutzmassnahmen fuer die Uebermittlung personenbezogener Daten
|
||||
in Drittlaender (SCC, Angemessenheitsbeschluss, BCR).
|
||||
objective_template: >
|
||||
Personenbezogene Daten nur unter Einhaltung der gesetzlichen
|
||||
Uebermittlungsgarantien in Drittlaender transferieren.
|
||||
rationale_template: >
|
||||
Seit Schrems II erfordern Datentransfers in die USA und andere
|
||||
Drittlaender zusaetzliche Schutzmassnahmen. Verstoesse fuehren
|
||||
zu hohen Bussgeldern (z.B. Meta: 1,2 Mrd. EUR).
|
||||
requirements_template:
|
||||
- "Register aller Drittland-Datentransfers"
|
||||
- "Transfer Impact Assessment (TIA) fuer jeden Drittland-Transfer"
|
||||
- "Standardvertragsklauseln (SCC) oder Angemessenheitsbeschluss"
|
||||
- "Supplementary Measures wo erforderlich"
|
||||
- "Regelmaessige Neubewertung (bei Rechtsaenderung oder Schrems-Entscheid)"
|
||||
test_procedure_template:
|
||||
- "Pruefung des Drittland-Transfer-Registers auf Vollstaendigkeit"
|
||||
- "Review: TIA fuer einen Drittland-Transfer"
|
||||
- "Stichprobe: SCC fuer 3 Auftragsverarbeiter pruefen"
|
||||
evidence_template:
|
||||
- "Drittland-Transfer-Register"
|
||||
- "Transfer Impact Assessments"
|
||||
- "Standardvertragsklauseln (unterzeichnet)"
|
||||
severity_default: critical
|
||||
implementation_effort_default: l
|
||||
open_anchor_refs:
|
||||
- { framework: "ENISA Guidelines", ref: "International Data Transfers" }
|
||||
obligation_match_keywords:
|
||||
- drittland
|
||||
- transfer
|
||||
- uebermittlung
|
||||
- scc
|
||||
- angemessenheit
|
||||
- third country
|
||||
- schrems
|
||||
- binding corporate rules
|
||||
tags: [data_transfer, international, gdpr]
|
||||
composable_with: [CP-COMP-005, CP-DATA-004]
|
||||
|
||||
- id: CP-DATA-008
|
||||
name: disposal_procedure
|
||||
name_de: Sichere Datentraegerentsorgung
|
||||
domain: DATA
|
||||
category: data_protection
|
||||
description: >
|
||||
Sichere Vernichtung oder Bereinigung von Datentraegern bei
|
||||
Ausserbetriebnahme, Rueckgabe oder Entsorgung.
|
||||
objective_template: >
|
||||
Daten auf ausgemusterten Datentraegern unwiederbringlich vernichten,
|
||||
bevor diese das Unternehmen verlassen.
|
||||
rationale_template: >
|
||||
Unsachgemaess entsorgte Datentraeger sind eine haeufige Quelle
|
||||
fuer Datenpannen. Selbst formatierte Festplatten koennen
|
||||
wiederhergestellt werden.
|
||||
requirements_template:
|
||||
- "Zertifizierte Datenvernichtung fuer alle ausgemusterten Datentraeger"
|
||||
- "NIST SP 800-88 konforme Bereinigung (Clear, Purge oder Destroy)"
|
||||
- "Vernichtungsprotokoll mit Seriennummer und Methode"
|
||||
- "Verschluesselte Datentraeger: Cryptographic Erasure als Minimum"
|
||||
- "Regelmaessige Audit der Entsorgungsprozesse"
|
||||
test_procedure_template:
|
||||
- "Pruefung der Vernichtungsprotokolle der letzten 6 Monate"
|
||||
- "Stichprobe: Versuch, Daten von bereinigtem Datentraeger wiederherzustellen"
|
||||
evidence_template:
|
||||
- "Datentraegerentsorgungsrichtlinie"
|
||||
- "Vernichtungsprotokolle / -zertifikate"
|
||||
severity_default: medium
|
||||
implementation_effort_default: s
|
||||
open_anchor_refs:
|
||||
- { framework: "NIST SP 800-88", ref: "Rev. 1" }
|
||||
obligation_match_keywords:
|
||||
- entsorgung
|
||||
- vernichtung
|
||||
- datentraeger
|
||||
- disposal
|
||||
- loeschung
|
||||
- bereinigung
|
||||
- sanitization
|
||||
tags: [disposal, data_destruction, physical]
|
||||
composable_with: [CP-SEC-005, CP-DATA-003]
|
||||
Reference in New Issue
Block a user