Files
breakpilot-compliance/backend-compliance/compliance/services/regulation_scraper.py
Benjamin Admin 95fcba34cd
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Failing after 30s
CI / test-python-backend-compliance (push) Successful in 30s
CI / test-python-document-crawler (push) Successful in 21s
CI / test-python-dsms-gateway (push) Successful in 17s
fix(quality): Ruff/CVE/TS-Fixes, 104 neue Tests, Complexity-Refactoring
- Ruff: 144 auto-fixes (unused imports, == None → is None), F821/F811/F841 manuell
- CVEs: python-multipart>=0.0.22, weasyprint>=68.0, pillow>=12.1.1, npm audit fix (0 vulns)
- TS: 5 tote Drafting-Engine-Dateien entfernt, allowed-facts/sanitizer/StepHeader/context fixes
- Tests: +104 (ISMS 58, Evidence 18, VVT 14, Generation 14) → 1449 passed
- Refactoring: collect_ci_evidence (F→A), row_to_response (E→A), extract_requirements (E→A)
- Dead Code: pca-platform, 7 Go-Handler, dsr_api.py, duplicate Schemas entfernt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:00:33 +01:00

875 lines
67 KiB
Python

"""
Compliance Regulation Scraper Service.
Extracts requirements and audit aspects from:
- EU-Lex regulations (GDPR, AI Act, CRA, NIS2, etc.)
- BSI Technical Guidelines (TR-03161)
- German laws (TDDDG, etc.)
Similar pattern to edu-search and zeugnisse-crawler.
"""
import logging
import re
from datetime import datetime
from typing import Dict, List, Any, Optional
from enum import Enum
import httpx
from bs4 import BeautifulSoup
from sqlalchemy.orm import Session
from ..db.models import (
RegulationDB,
RequirementDB,
RegulationTypeEnum,
)
from ..db.repository import (
RegulationRepository,
RequirementRepository,
)
logger = logging.getLogger(__name__)
class SourceType(str, Enum):
EUR_LEX = "eur_lex"
BSI_PDF = "bsi_pdf"
GESETZE_IM_INTERNET = "gesetze_im_internet"
MANUAL = "manual"
class ScraperStatus(str, Enum):
IDLE = "idle"
RUNNING = "running"
COMPLETED = "completed"
ERROR = "error"
class RegulationScraperService:
"""
Scrapes and extracts requirements from regulatory sources.
Supported sources:
- EUR-Lex: https://eur-lex.europa.eu/eli/reg/{year}/{number}/oj/eng
- BSI: Local PDF parsing
- Gesetze-im-Internet: German law portal
"""
# EUR-Lex patterns for article extraction
ARTICLE_PATTERN = re.compile(
r'Article\s+(\d+[a-z]?)\s*\n\s*(.+?)(?=\nArticle\s+\d|$)',
re.DOTALL | re.IGNORECASE
)
# BSI TR pattern for test aspects
BSI_ASPECT_PATTERN = re.compile(
r'(O\.[A-Za-z_]+[\d]*)\s+(.+?)(?=\nO\.|$)',
re.DOTALL
)
# Known regulation URLs - All 19 regulations from seed data
KNOWN_SOURCES = {
# A. Datenschutz & Datenuebermittlung
"GDPR": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32016R0679",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
"EPRIVACY": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32002L0058",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_DIRECTIVE,
},
"SCC": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32021D0914",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
"DPF": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32023D1795",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
# B. KI-Regulierung
"AIACT": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=OJ:L_202401689",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
# C. Cybersecurity & Produktsicherheit
"CRA": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=OJ:L_202402847",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
"NIS2": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32022L2555",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_DIRECTIVE,
},
"EUCSA": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32019R0881",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
# D. Datenoekonomie & Interoperabilitaet
"DATAACT": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32023R2854",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
"DGA": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32022R0868",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
# E. Plattform-Pflichten
"DSA": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32022R2065",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
# F. Barrierefreiheit
"EAA": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32019L0882",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_DIRECTIVE,
},
# G. IP & Urheberrecht
"DSM": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32019L0790",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_DIRECTIVE,
},
# H. Produkthaftung
"PLD": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32024L2853",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_DIRECTIVE,
},
"GPSR": {
"url": "https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32023R0988",
"type": SourceType.EUR_LEX,
"regulation_type": RegulationTypeEnum.EU_REGULATION,
},
# I. BSI-Standards (Deutschland)
"BSI-TR-03161-1": {
"url": "/docs/BSI-TR-03161-1.pdf",
"type": SourceType.BSI_PDF,
"regulation_type": RegulationTypeEnum.BSI_STANDARD,
},
"BSI-TR-03161-2": {
"url": "/docs/BSI-TR-03161-2.pdf",
"type": SourceType.BSI_PDF,
"regulation_type": RegulationTypeEnum.BSI_STANDARD,
},
"BSI-TR-03161-3": {
"url": "/docs/BSI-TR-03161-3.pdf",
"type": SourceType.BSI_PDF,
"regulation_type": RegulationTypeEnum.BSI_STANDARD,
},
}
def __init__(self, db: Session):
self.db = db
self.reg_repo = RegulationRepository(db)
self.req_repo = RequirementRepository(db)
self.status = ScraperStatus.IDLE
self.current_source: Optional[str] = None
self.last_error: Optional[str] = None
self.stats = {
"sources_processed": 0,
"requirements_extracted": 0,
"errors": 0,
"last_run": None,
}
async def get_status(self) -> Dict[str, Any]:
"""Get current scraper status."""
return {
"status": self.status.value,
"current_source": self.current_source,
"last_error": self.last_error,
"stats": self.stats,
"known_sources": list(self.KNOWN_SOURCES.keys()),
}
async def scrape_all(self) -> Dict[str, Any]:
"""Scrape all known regulation sources."""
self.status = ScraperStatus.RUNNING
self.stats["last_run"] = datetime.utcnow().isoformat()
results = {
"success": [],
"failed": [],
"skipped": [],
}
for code, source_info in self.KNOWN_SOURCES.items():
try:
self.current_source = code
# Check if already scraped recently
existing = self.reg_repo.get_by_code(code)
if existing and existing.requirements:
results["skipped"].append({
"code": code,
"reason": "already_has_requirements",
"requirement_count": len(existing.requirements),
})
continue
# Scrape based on source type
if source_info["type"] == SourceType.EUR_LEX:
count = await self._scrape_eurlex(code, source_info)
elif source_info["type"] == SourceType.BSI_PDF:
count = await self._scrape_bsi_pdf(code, source_info)
else:
results["skipped"].append({
"code": code,
"reason": "unknown_source_type",
})
continue
results["success"].append({
"code": code,
"requirements_extracted": count,
})
self.stats["sources_processed"] += 1
self.stats["requirements_extracted"] += count
except Exception as e:
logger.error(f"Error scraping {code}: {e}")
results["failed"].append({
"code": code,
"error": str(e),
})
self.stats["errors"] += 1
self.last_error = str(e)
self.status = ScraperStatus.COMPLETED
self.current_source = None
return results
async def scrape_single(self, code: str, force: bool = False) -> Dict[str, Any]:
"""Scrape a single regulation source."""
if code not in self.KNOWN_SOURCES:
raise ValueError(f"Unknown regulation code: {code}")
source_info = self.KNOWN_SOURCES[code]
self.status = ScraperStatus.RUNNING
self.current_source = code
try:
# Check existing
existing = self.reg_repo.get_by_code(code)
if existing and existing.requirements and not force:
self.status = ScraperStatus.COMPLETED
return {
"code": code,
"status": "skipped",
"reason": "already_has_requirements",
"requirement_count": len(existing.requirements),
}
# Delete existing requirements if force
if existing and force:
for req in existing.requirements:
self.db.delete(req)
self.db.commit()
# Scrape
if source_info["type"] == SourceType.EUR_LEX:
count = await self._scrape_eurlex(code, source_info)
elif source_info["type"] == SourceType.BSI_PDF:
count = await self._scrape_bsi_pdf(code, source_info)
else:
raise ValueError(f"Unknown source type: {source_info['type']}")
self.status = ScraperStatus.COMPLETED
return {
"code": code,
"status": "success",
"requirements_extracted": count,
}
except Exception as e:
self.status = ScraperStatus.ERROR
self.last_error = str(e)
raise
finally:
self.current_source = None
async def _scrape_eurlex(self, code: str, source_info: Dict) -> int:
"""Scrape EUR-Lex regulation page."""
url = source_info["url"]
logger.info(f"Scraping EUR-Lex: {code} from {url}")
async with httpx.AsyncClient(timeout=60.0) as client:
response = await client.get(url, follow_redirects=True)
response.raise_for_status()
html = response.text
soup = BeautifulSoup(html, 'html.parser')
# Get or create regulation
regulation = self.reg_repo.get_by_code(code)
if not regulation:
regulation = RegulationDB(
code=code,
name=code,
regulation_type=source_info["regulation_type"],
source_url=url,
is_active=True,
)
self.db.add(regulation)
self.db.commit()
self.db.refresh(regulation)
# Extract articles
requirements_created = 0
# Find all article elements (EUR-Lex structure varies)
articles = soup.find_all('div', class_='eli-subdivision')
if not articles:
articles = soup.find_all('p', class_='oj-ti-art')
for article_elem in articles:
try:
# Extract article number and title
article_id = article_elem.get('id', '')
if not article_id:
title_elem = article_elem.find(['span', 'p'], class_=['oj-ti-art', 'eli-title'])
if title_elem:
text = title_elem.get_text(strip=True)
match = re.search(r'Article\s+(\d+[a-z]?)', text, re.IGNORECASE)
if match:
article_id = f"art_{match.group(1)}"
if not article_id:
continue
# Extract article text
article_text = article_elem.get_text(separator='\n', strip=True)
# Parse article number and title
lines = article_text.split('\n')
article_num = None
title = None
for line in lines[:3]:
art_match = re.search(r'Article\s+(\d+[a-z]?)', line, re.IGNORECASE)
if art_match:
article_num = f"Art. {art_match.group(1)}"
elif not article_num:
continue
elif not title and len(line) > 3 and not line.startswith('Article'):
title = line[:200]
break
if not article_num:
continue
# Check if requirement already exists
existing = self.db.query(RequirementDB).filter(
RequirementDB.regulation_id == regulation.id,
RequirementDB.article == article_num
).first()
if existing:
continue
# Create requirement
requirement = RequirementDB(
regulation_id=regulation.id,
article=article_num,
title=title or f"{code} {article_num}",
requirement_text=article_text[:5000], # Limit length
source_section=article_id,
is_applicable=True,
priority=2,
)
self.db.add(requirement)
requirements_created += 1
except Exception as e:
logger.warning(f"Error parsing article in {code}: {e}")
continue
# Alternative: extract from raw text with regex
if requirements_created == 0:
text = soup.get_text()
matches = self.ARTICLE_PATTERN.findall(text)
for art_num, art_text in matches[:50]: # Limit to 50 articles
article_num = f"Art. {art_num}"
existing = self.db.query(RequirementDB).filter(
RequirementDB.regulation_id == regulation.id,
RequirementDB.article == article_num
).first()
if existing:
continue
# Extract first line as title
lines = art_text.strip().split('\n')
title = lines[0][:200] if lines else f"{code} {article_num}"
requirement = RequirementDB(
regulation_id=regulation.id,
article=article_num,
title=title,
requirement_text=art_text[:5000],
is_applicable=True,
priority=2,
)
self.db.add(requirement)
requirements_created += 1
# Fallback: If scraping failed (e.g., WAF protection), use seed requirements
if requirements_created == 0:
logger.info(f"Scraping returned 0 results for {code}, using seed requirements")
seed_reqs = self._get_eurlex_seed_requirements(code)
for seed in seed_reqs:
existing = self.db.query(RequirementDB).filter(
RequirementDB.regulation_id == regulation.id,
RequirementDB.article == seed["article"]
).first()
if existing:
continue
requirement = RequirementDB(
regulation_id=regulation.id,
article=seed["article"],
title=seed["title"],
description=seed.get("description"),
requirement_text=seed.get("requirement_text"),
is_applicable=True,
priority=seed.get("priority", 2),
)
self.db.add(requirement)
requirements_created += 1
self.db.commit()
logger.info(f"Extracted {requirements_created} requirements from {code}")
return requirements_created
def _get_eurlex_seed_requirements(self, code: str) -> List[Dict[str, Any]]:
"""
Returns seed requirements for EUR-Lex regulations when scraping fails.
These are the key articles relevant for Breakpilot compliance.
"""
if code == "NIS2":
return [
{"article": "Art. 6", "title": "Risikobewertung", "description": "Risikobewertung fuer Cybersicherheit", "requirement_text": "Einrichtungen muessen eine Risikobewertung fuer Cybersicherheit durchfuehren.", "priority": 1},
{"article": "Art. 7", "title": "Nationale Cybersicherheitsstrategie", "description": "Umsetzung nationaler Vorgaben", "requirement_text": "Einhaltung der nationalen Cybersicherheitsstrategie.", "priority": 2},
{"article": "Art. 20", "title": "Governance", "description": "Leitungsorgane muessen Cybersicherheit beaufsichtigen", "requirement_text": "Leitungsorgane muessen Cybersicherheitsmassnahmen genehmigen und deren Umsetzung beaufsichtigen.", "priority": 1},
{"article": "Art. 21", "title": "Risikomanagementmassnahmen", "description": "Technische und organisatorische Massnahmen", "requirement_text": "Geeignete und verhaeltnismaessige technische, operative und organisatorische Massnahmen zur Beherrschung von Cybersicherheitsrisiken.", "priority": 1},
{"article": "Art. 21(2)(a)", "title": "Risikoanalyse und Sicherheitskonzepte", "description": "Konzepte fuer Risikoanalyse", "requirement_text": "Konzepte fuer die Risikoanalyse und Sicherheit von Informationssystemen.", "priority": 1},
{"article": "Art. 21(2)(b)", "title": "Bewertung von Sicherheitsvorfaellen", "description": "Incident Handling", "requirement_text": "Bewertung der Wirksamkeit von Risikomanagementmassnahmen.", "priority": 1},
{"article": "Art. 21(2)(c)", "title": "Business Continuity", "description": "Betriebskontinuitaet sicherstellen", "requirement_text": "Aufrechterhaltung des Betriebs, Backup-Management und Krisenmanagement.", "priority": 1},
{"article": "Art. 21(2)(d)", "title": "Lieferkettensicherheit", "description": "Sicherheit in der Lieferkette", "requirement_text": "Sicherheit der Lieferkette einschliesslich Beziehungen zu Lieferanten.", "priority": 1},
{"article": "Art. 21(2)(e)", "title": "Sicherheit bei Entwicklung", "description": "Sichere Entwicklung", "requirement_text": "Sicherheit bei Erwerb, Entwicklung und Wartung von Systemen.", "priority": 1},
{"article": "Art. 21(2)(f)", "title": "Schwachstellenmanagement", "description": "Umgang mit Schwachstellen", "requirement_text": "Konzepte zur Bewertung der Wirksamkeit von Massnahmen.", "priority": 1},
{"article": "Art. 21(2)(g)", "title": "Cyberhygiene und Schulungen", "description": "Grundlegende Cyberhygiene-Praktiken", "requirement_text": "Grundlegende Cyberhygiene-Praktiken und Schulungen.", "priority": 1},
{"article": "Art. 21(2)(h)", "title": "Kryptografie", "description": "Einsatz von Verschluesselung", "requirement_text": "Konzepte und Verfahren fuer Kryptografie und Verschluesselung.", "priority": 1},
{"article": "Art. 21(2)(i)", "title": "Personalsicherheit", "description": "HR-Security", "requirement_text": "Sicherheit des Personals, Zugangskontrollen und Asset-Management.", "priority": 1},
{"article": "Art. 21(2)(j)", "title": "MFA und sichere Authentifizierung", "description": "Multi-Faktor-Authentifizierung", "requirement_text": "Multi-Faktor-Authentifizierung und sichere Kommunikation.", "priority": 1},
{"article": "Art. 23", "title": "Meldepflichten", "description": "Meldung von Sicherheitsvorfaellen", "requirement_text": "Erhebliche Sicherheitsvorfaelle muessen den zustaendigen Behoerden gemeldet werden.", "priority": 1},
{"article": "Art. 24", "title": "Europaeische Schwachstellendatenbank", "description": "CVE-Datenbank nutzen", "requirement_text": "Nutzung der europaeischen Schwachstellendatenbank.", "priority": 2},
]
elif code == "DATAACT":
return [
{"article": "Art. 3", "title": "Datenzugang fuer Nutzer", "description": "Nutzer koennen auf ihre Daten zugreifen", "requirement_text": "Daten, die durch Nutzung vernetzter Produkte generiert werden, muessen dem Nutzer zugaenglich gemacht werden.", "priority": 1},
{"article": "Art. 4", "title": "Recht auf Datenzugang", "description": "Unentgeltlicher Zugang", "requirement_text": "Nutzer haben das Recht auf unentgeltlichen Zugang zu ihren Daten.", "priority": 1},
{"article": "Art. 5", "title": "Recht auf Datenweitergabe", "description": "Daten an Dritte weitergeben", "requirement_text": "Nutzer koennen verlangen, dass Daten an Dritte weitergegeben werden.", "priority": 1},
{"article": "Art. 6", "title": "Pflichten des Dateninhabers", "description": "Daten zeitnah bereitstellen", "requirement_text": "Dateninhaber muessen Daten unverzueglich und in geeignetem Format bereitstellen.", "priority": 1},
{"article": "Art. 8", "title": "Faire Vertragsbedingungen", "description": "Keine unfairen Klauseln", "requirement_text": "Vertragsbedingungen fuer Datenzugang muessen fair und nicht-diskriminierend sein.", "priority": 2},
{"article": "Art. 14", "title": "Cloud-Switching", "description": "Wechsel zwischen Cloud-Anbietern", "requirement_text": "Unterstuetzung beim Wechsel zwischen Cloud-Diensten und Datenportabilitaet.", "priority": 1},
{"article": "Art. 23", "title": "Technische Schutzmassnahmen", "description": "Schutz nicht-personenbezogener Daten", "requirement_text": "Angemessene technische Schutzmassnahmen fuer nicht-personenbezogene Daten.", "priority": 1},
{"article": "Art. 25", "title": "Geschaeftsgeheimnisse", "description": "Schutz von Geschaeftsgeheimnissen", "requirement_text": "Massnahmen zum Schutz von Geschaeftsgeheimnissen bei Datenzugang.", "priority": 2},
]
elif code == "DGA":
return [
{"article": "Art. 5", "title": "Bedingungen fuer Weiterverwendung", "description": "Weiterverwendung oeffentlicher Daten", "requirement_text": "Bedingungen fuer die Weiterverwendung geschuetzter Daten oeffentlicher Stellen.", "priority": 2},
{"article": "Art. 7", "title": "Technische Anforderungen", "description": "Sichere Verarbeitungsumgebungen", "requirement_text": "Sichere Verarbeitungsumgebungen fuer Zugang zu geschuetzten Daten.", "priority": 1},
{"article": "Art. 10", "title": "Datenvermittlungsdienste", "description": "Registrierung von Vermittlungsdiensten", "requirement_text": "Datenvermittlungsdienste muessen registriert und reguliert werden.", "priority": 2},
{"article": "Art. 12", "title": "Bedingungen fuer Datenvermittlung", "description": "Neutralitaet wahren", "requirement_text": "Datenvermittler muessen neutral handeln und duerfen Daten nicht fuer eigene Zwecke nutzen.", "priority": 1},
{"article": "Art. 16", "title": "Datenaltruismus", "description": "Freiwillige Datenspende", "requirement_text": "Registrierung als Organisation fuer Datenaltruismus moeglich.", "priority": 3},
{"article": "Art. 21", "title": "Einwilligungsformular", "description": "Europaeisches Einwilligungsformular", "requirement_text": "Verwendung des europaeischen Einwilligungsformulars fuer Datenaltruismus.", "priority": 3},
]
elif code == "DSA":
return [
{"article": "Art. 6", "title": "Haftungsausschluss Hosting", "description": "Bedingungen fuer Haftungsausschluss", "requirement_text": "Hosting-Dienste haften nicht, wenn sie keine Kenntnis von rechtswidrigen Inhalten haben.", "priority": 1},
{"article": "Art. 11", "title": "Kontaktstelle", "description": "Behoerdenkontakt", "requirement_text": "Anbieter muessen eine Kontaktstelle fuer Behoerden benennen.", "priority": 2},
{"article": "Art. 12", "title": "Rechtsvertreter", "description": "Vertreter in der EU", "requirement_text": "Nicht-EU-Anbieter muessen einen Rechtsvertreter in der EU benennen.", "priority": 2},
{"article": "Art. 13", "title": "AGB-Transparenz", "description": "Transparente Nutzungsbedingungen", "requirement_text": "AGB muessen klar, verstaendlich und leicht zugaenglich sein.", "priority": 1},
{"article": "Art. 14", "title": "Transparenzberichte", "description": "Jaehrliche Berichte", "requirement_text": "Jaehrliche Transparenzberichte ueber Content-Moderation veroeffentlichen.", "priority": 2},
{"article": "Art. 16", "title": "Melde- und Abhilfeverfahren", "description": "Notice and Action", "requirement_text": "Leicht zugaengliches System fuer Meldung rechtswidriger Inhalte.", "priority": 1},
{"article": "Art. 17", "title": "Begruendungspflicht", "description": "Entscheidungen begruenden", "requirement_text": "Nutzer muessen ueber Content-Moderation-Entscheidungen informiert werden.", "priority": 1},
{"article": "Art. 20", "title": "Internes Beschwerdemanagement", "description": "Beschwerden bearbeiten", "requirement_text": "Internes System zur Bearbeitung von Beschwerden ueber Content-Moderation.", "priority": 1},
{"article": "Art. 26", "title": "Werbetransparenz", "description": "Werbung kennzeichnen", "requirement_text": "Online-Werbung muss klar als solche erkennbar sein.", "priority": 1},
{"article": "Art. 27", "title": "Empfehlungssysteme", "description": "Algorithmen erklaeren", "requirement_text": "Transparenz ueber Parameter von Empfehlungsalgorithmen.", "priority": 2},
]
elif code == "EUCSA":
return [
{"article": "Art. 46", "title": "Cybersicherheitszertifizierung", "description": "EU-Zertifizierungsrahmen", "requirement_text": "Freiwillige europaeische Zertifizierung fuer IKT-Produkte und -Dienste.", "priority": 2},
{"article": "Art. 51", "title": "Sicherheitsziele", "description": "Ziele der Zertifizierung", "requirement_text": "Schutz von Daten vor unbefugtem Zugriff, Manipulation und Zerstoerung.", "priority": 1},
{"article": "Art. 52", "title": "Vertrauenswuerdigkeitsstufen", "description": "Basic, Substantial, High", "requirement_text": "Drei Stufen: Basic, Substantial, High - je nach Risiko.", "priority": 1},
{"article": "Art. 54", "title": "Konformitaetsbewertung", "description": "Selbstbewertung oder Drittbewertung", "requirement_text": "Je nach Stufe Selbstbewertung oder unabhaengige Bewertung.", "priority": 2},
{"article": "Art. 56", "title": "Zertifizierungsstellen", "description": "Akkreditierte Stellen", "requirement_text": "Zertifizierung durch akkreditierte Konformitaetsbewertungsstellen.", "priority": 2},
]
elif code == "EAA":
return [
{"article": "Art. 3", "title": "Barrierefreiheitsanforderungen", "description": "Produkte barrierefrei gestalten", "requirement_text": "Produkte und Dienstleistungen muessen die Barrierefreiheitsanforderungen erfuellen.", "priority": 1},
{"article": "Art. 4", "title": "Bestehende Rechtsvorschriften", "description": "Verhaeltnis zu anderen Vorschriften", "requirement_text": "Ergaenzung zu bestehenden Barrierefreiheitsvorschriften.", "priority": 3},
{"article": "Art. 13", "title": "Konformitaetsvermutung", "description": "Harmonisierte Normen", "requirement_text": "Konformitaet bei Einhaltung harmonisierter Normen vermutet.", "priority": 2},
{"article": "Art. 14", "title": "Gemeinsame technische Spezifikationen", "description": "Falls keine Normen existieren", "requirement_text": "EU-Kommission kann technische Spezifikationen festlegen.", "priority": 3},
{"article": "Anhang I", "title": "Barrierefreiheitsanforderungen fuer Produkte", "description": "WCAG-konforme Webseiten", "requirement_text": "Webseiten, Apps und E-Books muessen WCAG 2.1 Level AA erfuellen.", "priority": 1},
]
elif code == "DSM":
return [
{"article": "Art. 3", "title": "Text and Data Mining (Forschung)", "description": "TDM fuer Forschung erlaubt", "requirement_text": "Text- und Data-Mining fuer wissenschaftliche Forschung ist erlaubt.", "priority": 2},
{"article": "Art. 4", "title": "Text and Data Mining (Allgemein)", "description": "TDM-Ausnahme", "requirement_text": "TDM erlaubt, wenn Rechteinhaber nicht widersprochen haben.", "priority": 1},
{"article": "Art. 15", "title": "Leistungsschutzrecht Presse", "description": "Verguetung fuer Presseverleger", "requirement_text": "Online-Nutzung von Presseveroeffentlichungen erfordert Lizenz.", "priority": 2},
{"article": "Art. 17", "title": "Upload-Filter", "description": "Plattformhaftung fuer Uploads", "requirement_text": "Plattformen haften fuer urheberrechtsverletzende Uploads ihrer Nutzer.", "priority": 1},
{"article": "Art. 17(7)", "title": "Overblocking verhindern", "description": "Legitime Nutzung schuetzen", "requirement_text": "Massnahmen duerfen nicht zu ungerechtfertigter Sperrung fuehren.", "priority": 1},
]
elif code == "PLD":
return [
{"article": "Art. 4", "title": "Produktbegriff", "description": "Software als Produkt", "requirement_text": "Software gilt als Produkt im Sinne der Produkthaftung.", "priority": 1},
{"article": "Art. 6", "title": "Fehlerhaftes Produkt", "description": "Definition Produktfehler", "requirement_text": "Ein Produkt ist fehlerhaft, wenn es nicht die erwartete Sicherheit bietet.", "priority": 1},
{"article": "Art. 7", "title": "KI-Systeme", "description": "Haftung fuer KI", "requirement_text": "Haftung gilt auch fuer durch KI verursachte Schaeden.", "priority": 1},
{"article": "Art. 9", "title": "Haftung des Herstellers", "description": "Verschuldensunabhaengige Haftung", "requirement_text": "Hersteller haften verschuldensunabhaengig fuer Produktfehler.", "priority": 1},
{"article": "Art. 10", "title": "Softwareaktualisierungen", "description": "Pflicht zu Updates", "requirement_text": "Fehlende Sicherheitsupdates koennen Haftung begruenden.", "priority": 1},
]
elif code == "GPSR":
return [
{"article": "Art. 5", "title": "Allgemeine Sicherheitsanforderung", "description": "Produkte muessen sicher sein", "requirement_text": "Nur sichere Produkte duerfen in Verkehr gebracht werden.", "priority": 1},
{"article": "Art. 8", "title": "Pflichten der Hersteller", "description": "Sicherheitsbewertung durchfuehren", "requirement_text": "Hersteller muessen Risikoanalyse und Sicherheitsbewertung durchfuehren.", "priority": 1},
{"article": "Art. 9", "title": "Technische Dokumentation", "description": "Dokumentationspflicht", "requirement_text": "Technische Dokumentation zur Konformitaet erstellen und aufbewahren.", "priority": 1},
{"article": "Art. 10", "title": "EU-Konformitaetserklaerung", "description": "CE-Kennzeichnung", "requirement_text": "Konformitaetserklaerung und CE-Kennzeichnung erforderlich.", "priority": 1},
{"article": "Art. 14", "title": "Produktrueckrufe", "description": "Rueckrufverfahren", "requirement_text": "Bei Sicherheitsrisiken muessen Produkte zurueckgerufen werden.", "priority": 1},
]
elif code == "CRA":
return [
{"article": "Art. 5", "title": "Wesentliche Anforderungen", "description": "Cybersicherheit bei Entwurf", "requirement_text": "Produkte muessen so entworfen werden, dass sie ein angemessenes Cybersicherheitsniveau gewaehrleisten.", "priority": 1},
{"article": "Art. 6", "title": "Sicherheitsupdates", "description": "Updates bereitstellen", "requirement_text": "Hersteller muessen Sicherheitsupdates fuer die erwartete Produktlebensdauer bereitstellen.", "priority": 1},
{"article": "Art. 10", "title": "Schwachstellenbehandlung", "description": "Vulnerability Handling", "requirement_text": "Hersteller muessen ein koordiniertes Schwachstellenmanagement implementieren.", "priority": 1},
{"article": "Art. 11", "title": "Meldepflicht", "description": "Schwachstellen melden", "requirement_text": "Aktiv ausgenutzte Schwachstellen muessen innerhalb von 24 Stunden gemeldet werden.", "priority": 1},
{"article": "Art. 13", "title": "SBOM", "description": "Software Bill of Materials", "requirement_text": "Eine SBOM muss fuer das Produkt erstellt und gepflegt werden.", "priority": 1},
{"article": "Art. 15", "title": "Support-Zeitraum", "description": "Mindest-Support-Dauer", "requirement_text": "Mindestens 5 Jahre Support oder erwartete Produktlebensdauer.", "priority": 1},
{"article": "Anhang I.1", "title": "Sichere Standardkonfiguration", "description": "Secure by Default", "requirement_text": "Produkte muessen mit sicheren Standardeinstellungen ausgeliefert werden.", "priority": 1},
{"article": "Anhang I.2", "title": "Schutz vor unbefugtem Zugriff", "description": "Access Control", "requirement_text": "Mechanismen zum Schutz vor unbefugtem Zugriff implementieren.", "priority": 1},
{"article": "Anhang I.3", "title": "Datenintegritaet", "description": "Integritaetsschutz", "requirement_text": "Schutz der Integritaet von Daten und Konfiguration.", "priority": 1},
{"article": "Anhang I.4", "title": "Verfuegbarkeit", "description": "Resilienz", "requirement_text": "Schutz vor DoS-Angriffen und Sicherstellung der Verfuegbarkeit.", "priority": 1},
]
elif code == "EPRIVACY":
return [
{"article": "Art. 5", "title": "Vertraulichkeit der Kommunikation", "description": "Kommunikation schuetzen", "requirement_text": "Vertraulichkeit der Kommunikation und Verkehrsdaten gewaehrleisten.", "priority": 1},
{"article": "Art. 6", "title": "Verkehrsdaten", "description": "Umgang mit Verkehrsdaten", "requirement_text": "Verkehrsdaten muessen nach Abschluss geloescht oder anonymisiert werden.", "priority": 1},
{"article": "Art. 9", "title": "Standortdaten", "description": "Nur mit Einwilligung", "requirement_text": "Standortdaten nur mit ausdruecklicher Einwilligung verarbeiten.", "priority": 1},
{"article": "Art. 13", "title": "Unerbetene Nachrichten", "description": "Opt-in fuer Marketing", "requirement_text": "Direktwerbung per E-Mail nur mit vorheriger Einwilligung.", "priority": 1},
]
elif code == "SCC":
return [
{"article": "Klausel 8", "title": "Datenschutzgarantien", "description": "Garantien dokumentieren", "requirement_text": "Datenimporteur muss angemessene Datenschutzgarantien gewaehrleisten.", "priority": 1},
{"article": "Klausel 10", "title": "Betroffenenrechte", "description": "Rechte durchsetzen", "requirement_text": "Betroffene koennen ihre Rechte auch gegenueber Datenimporteur geltend machen.", "priority": 1},
{"article": "Klausel 14", "title": "Lokale Rechtsvorschriften", "description": "Rechtslage pruefen", "requirement_text": "Parteien muessen pruefen, ob lokale Gesetze die Einhaltung verhindern.", "priority": 1},
{"article": "Klausel 15", "title": "Behoerdenzugriff", "description": "Transparenz bei Anfragen", "requirement_text": "Datenimporteur muss ueber Behoerdenanfragen informieren.", "priority": 1},
]
elif code == "DPF":
return [
{"article": "Prinzip 1", "title": "Notice", "description": "Informationspflicht", "requirement_text": "Betroffene muessen ueber Datenverarbeitung informiert werden.", "priority": 1},
{"article": "Prinzip 2", "title": "Choice", "description": "Wahlmoeglichkeit", "requirement_text": "Betroffene muessen der Weitergabe widersprechen koennen.", "priority": 1},
{"article": "Prinzip 4", "title": "Security", "description": "Sicherheitsmassnahmen", "requirement_text": "Angemessene Sicherheitsmassnahmen zum Schutz der Daten.", "priority": 1},
{"article": "Prinzip 5", "title": "Data Integrity", "description": "Datenintegritaet", "requirement_text": "Daten muessen richtig, vollstaendig und aktuell sein.", "priority": 1},
{"article": "Prinzip 6", "title": "Access", "description": "Auskunftsrecht", "requirement_text": "Betroffene haben Recht auf Zugang zu ihren Daten.", "priority": 1},
]
return []
async def _scrape_bsi_pdf(self, code: str, source_info: Dict) -> int:
"""
Scrape BSI Technical Guideline PDF.
Note: Full PDF parsing requires PyMuPDF or pdfplumber.
This is a placeholder that creates seed requirements.
"""
logger.info(f"Processing BSI TR: {code}")
# Get or create regulation
regulation = self.reg_repo.get_by_code(code)
if not regulation:
regulation = RegulationDB(
code=code,
name=f"BSI {code}",
full_name=f"BSI Technical Guideline {code}",
regulation_type=source_info["regulation_type"],
local_pdf_path=source_info["url"],
is_active=True,
)
self.db.add(regulation)
self.db.commit()
self.db.refresh(regulation)
# Known BSI TR-03161 test aspects (Pruefaspekte)
# These are the key security requirements from the TR
bsi_aspects = self._get_bsi_aspects(code)
requirements_created = 0
for aspect in bsi_aspects:
existing = self.db.query(RequirementDB).filter(
RequirementDB.regulation_id == regulation.id,
RequirementDB.article == aspect["id"]
).first()
if existing:
continue
requirement = RequirementDB(
regulation_id=regulation.id,
article=aspect["id"],
title=aspect["title"],
description=aspect.get("description"),
requirement_text=aspect.get("requirement_text"),
breakpilot_interpretation=aspect.get("interpretation"),
is_applicable=aspect.get("is_applicable", True),
priority=aspect.get("priority", 2),
source_page=aspect.get("page"),
source_section=aspect.get("section"),
)
self.db.add(requirement)
requirements_created += 1
self.db.commit()
logger.info(f"Created {requirements_created} BSI requirements from {code}")
return requirements_created
def _get_bsi_aspects(self, code: str) -> List[Dict[str, Any]]:
"""
Returns comprehensive BSI TR-03161 test aspects (Pruefaspekte).
These are the actual test aspects from BSI TR-03161:
- Part 1: Allgemeine Anforderungen (~45 Aspekte)
- Part 2: Web-Anwendungen (~40 Aspekte)
- Part 3: Hintergrundsysteme (~35 Aspekte)
Total: ~120 Pruefaspekte
"""
if code == "BSI-TR-03161-1":
# Teil 1: Allgemeine Anforderungen
return [
# Zweckbindung & Datenminimierung
{"id": "O.Purp_1", "title": "Zweckbindung", "description": "Anwendungszweck klar definiert", "requirement_text": "Die Anwendung muss einen klar definierten und dokumentierten Zweck haben.", "priority": 1, "section": "4.1"},
{"id": "O.Purp_2", "title": "Zweckdokumentation", "description": "Zweck fuer Nutzer einsehbar", "requirement_text": "Der Zweck muss fuer Nutzer transparent und einsehbar dokumentiert sein.", "priority": 2, "section": "4.1"},
{"id": "O.Data_1", "title": "Datenminimierung", "description": "Nur notwendige Daten erheben", "requirement_text": "Es duerfen nur die fuer den definierten Zweck erforderlichen Daten erhoben werden.", "priority": 1, "section": "4.2"},
{"id": "O.Data_2", "title": "Datenerforderlichkeit", "description": "Erforderlichkeit pruefen", "requirement_text": "Vor jeder Datenerhebung muss die Erforderlichkeit geprueft und dokumentiert werden.", "priority": 1, "section": "4.2"},
{"id": "O.Data_3", "title": "Datenkategorien", "description": "Datenkategorien klassifizieren", "requirement_text": "Alle verarbeiteten Datenkategorien muessen klassifiziert und dokumentiert sein.", "priority": 2, "section": "4.2"},
{"id": "O.Data_4", "title": "Besondere Kategorien", "description": "Art. 9 DSGVO Daten identifizieren", "requirement_text": "Besondere Kategorien personenbezogener Daten (Art. 9 DSGVO) muessen identifiziert und besonders geschuetzt werden.", "priority": 1, "section": "4.2"},
# Authentifizierung
{"id": "O.Auth_1", "title": "Authentifizierungsmechanismus", "description": "Sichere Authentifizierung", "requirement_text": "Die Anwendung muss sichere Authentifizierungsmechanismen implementieren.", "priority": 1, "section": "4.3"},
{"id": "O.Auth_2", "title": "Passwortrichtlinie", "description": "Starke Passwoerter erzwingen", "requirement_text": "Passwortrichtlinien muessen Mindestlaenge (12 Zeichen), Komplexitaet und Historie durchsetzen.", "priority": 1, "section": "4.3"},
{"id": "O.Auth_3", "title": "Passwort-Hashing", "description": "Sichere Hash-Algorithmen", "requirement_text": "Passwoerter muessen mit aktuellen Algorithmen (bcrypt, Argon2) gehasht werden.", "priority": 1, "section": "4.3"},
{"id": "O.Auth_4", "title": "Multi-Faktor-Authentifizierung", "description": "MFA fuer sensitive Bereiche", "requirement_text": "Fuer administrative und sensitive Funktionen muss MFA verfuegbar sein.", "priority": 1, "section": "4.3"},
{"id": "O.Auth_5", "title": "Brute-Force-Schutz", "description": "Rate Limiting bei Login", "requirement_text": "Nach mehreren fehlgeschlagenen Anmeldeversuchen muss Account-Lockout oder Rate-Limiting greifen.", "priority": 1, "section": "4.3"},
{"id": "O.Auth_6", "title": "Sichere Passwort-Wiederherstellung", "description": "Reset-Prozess absichern", "requirement_text": "Der Passwort-Reset-Prozess muss gegen Enumeration und Manipulation geschuetzt sein.", "priority": 1, "section": "4.3"},
# Autorisierung
{"id": "O.Authz_1", "title": "Zugriffskontrolle", "description": "Rollenbasierte Zugriffskontrolle", "requirement_text": "Ein rollenbasiertes Zugriffskonzept (RBAC) muss implementiert sein.", "priority": 1, "section": "4.4"},
{"id": "O.Authz_2", "title": "Least Privilege", "description": "Minimale Rechte", "requirement_text": "Benutzer sollen nur die minimal notwendigen Berechtigungen erhalten.", "priority": 1, "section": "4.4"},
{"id": "O.Authz_3", "title": "Rechtetrennung", "description": "Funktionale Trennung", "requirement_text": "Administrative und operative Rollen muessen getrennt sein.", "priority": 1, "section": "4.4"},
{"id": "O.Authz_4", "title": "Autorisierungspruefung", "description": "Serverseitige Pruefung", "requirement_text": "Jede Ressource muss serverseitig auf Zugriffsberechtigung geprueft werden.", "priority": 1, "section": "4.4"},
# Kryptografie
{"id": "O.Cryp_1", "title": "TLS-Verschluesselung", "description": "TLS 1.2+ fuer Transport", "requirement_text": "Alle Daten muessen bei der Uebertragung mit TLS 1.2 oder hoeher verschluesselt werden.", "priority": 1, "section": "4.5"},
{"id": "O.Cryp_2", "title": "Verschluesselung at Rest", "description": "Sensible Daten verschluesseln", "requirement_text": "Sensible Daten muessen bei der Speicherung verschluesselt werden (AES-256 oder vergleichbar).", "priority": 1, "section": "4.5"},
{"id": "O.Cryp_3", "title": "HSTS", "description": "HTTP Strict Transport Security", "requirement_text": "HSTS-Header muessen gesetzt sein um HTTPS zu erzwingen.", "priority": 1, "section": "4.5"},
{"id": "O.Cryp_4", "title": "Zertifikatvalidierung", "description": "Zertifikate pruefen", "requirement_text": "TLS-Zertifikate muessen vollstaendig validiert werden (Chain, Revocation, Hostname).", "priority": 1, "section": "4.5"},
{"id": "O.Cryp_5", "title": "Key Management", "description": "Sichere Schluesselverwaltung", "requirement_text": "Kryptographische Schluessel muessen sicher generiert, gespeichert und rotiert werden.", "priority": 1, "section": "4.5"},
{"id": "O.Cryp_6", "title": "Aktuelle Algorithmen", "description": "Keine veralteten Algorithmen", "requirement_text": "Es duerfen nur aktuelle, als sicher geltende kryptographische Algorithmen verwendet werden.", "priority": 1, "section": "4.5"},
# Datenschutz
{"id": "O.Priv_1", "title": "Datenschutzerklaerung", "description": "Transparente Information", "requirement_text": "Eine vollstaendige Datenschutzerklaerung muss vor Nutzung einsehbar sein.", "priority": 1, "section": "4.6"},
{"id": "O.Priv_2", "title": "Einwilligung", "description": "Wirksame Einwilligung", "requirement_text": "Einwilligungen muessen freiwillig, informiert, spezifisch und dokumentiert sein.", "priority": 1, "section": "4.6"},
{"id": "O.Priv_3", "title": "Betroffenenrechte", "description": "Auskunft, Loeschung, etc.", "requirement_text": "Technische Prozesse fuer Betroffenenrechte (Art. 15-21 DSGVO) muessen implementiert sein.", "priority": 1, "section": "4.6"},
{"id": "O.Priv_4", "title": "Loeschkonzept", "description": "Aufbewahrungsfristen", "requirement_text": "Ein dokumentiertes Loeschkonzept mit definierten Aufbewahrungsfristen muss umgesetzt sein.", "priority": 1, "section": "4.6"},
{"id": "O.Priv_5", "title": "Datenschutz durch Technik", "description": "Privacy by Design", "requirement_text": "Datenschutz muss bereits bei der Entwicklung beruecksichtigt werden (Art. 25 DSGVO).", "priority": 1, "section": "4.6"},
# Logging & Audit
{"id": "O.Log_1", "title": "Security Logging", "description": "Sicherheitsereignisse protokollieren", "requirement_text": "Sicherheitsrelevante Ereignisse (Login, Fehler, Zugriffsverletzungen) muessen protokolliert werden.", "priority": 1, "section": "4.7"},
{"id": "O.Log_2", "title": "Audit Trail", "description": "Nachvollziehbarkeit", "requirement_text": "Aenderungen an personenbezogenen Daten muessen nachvollziehbar protokolliert werden.", "priority": 1, "section": "4.7"},
{"id": "O.Log_3", "title": "Log-Integritaet", "description": "Logs vor Manipulation schuetzen", "requirement_text": "Logs muessen vor unbefugter Aenderung oder Loeschung geschuetzt sein.", "priority": 2, "section": "4.7"},
{"id": "O.Log_4", "title": "Keine PII in Logs", "description": "Keine personenbezogenen Daten loggen", "requirement_text": "Logs duerfen keine personenbezogenen Daten im Klartext enthalten.", "priority": 1, "section": "4.7"},
# Software-Entwicklung
{"id": "O.Dev_1", "title": "Secure SDLC", "description": "Sicherer Entwicklungsprozess", "requirement_text": "Ein dokumentierter sicherer Entwicklungsprozess (Secure SDLC) muss etabliert sein.", "priority": 1, "section": "4.8"},
{"id": "O.Dev_2", "title": "Code Review", "description": "Sicherheits-Review von Code", "requirement_text": "Sicherheitsrelevanter Code muss vor Release einem Review unterzogen werden.", "priority": 2, "section": "4.8"},
{"id": "O.Dev_3", "title": "Dependency Management", "description": "Abhaengigkeiten pruefen", "requirement_text": "Externe Abhaengigkeiten muessen auf bekannte Schwachstellen geprueft werden.", "priority": 1, "section": "4.8"},
{"id": "O.Dev_4", "title": "Penetration Testing", "description": "Regelmaessige Sicherheitstests", "requirement_text": "Regelmaessige Penetrationstests oder Schwachstellenscans muessen durchgefuehrt werden.", "priority": 2, "section": "4.8"},
# Betrieb
{"id": "O.Ops_1", "title": "Patch Management", "description": "Zeitnahes Patchen", "requirement_text": "Sicherheitspatches muessen zeitnah (kritisch: 24-72h) eingespielt werden.", "priority": 1, "section": "4.9"},
{"id": "O.Ops_2", "title": "Backup", "description": "Regelmaessige Datensicherung", "requirement_text": "Regelmaessige, getestete Backups muessen vorhanden sein.", "priority": 1, "section": "4.9"},
{"id": "O.Ops_3", "title": "Incident Response", "description": "Vorfallsmanagement", "requirement_text": "Ein dokumentierter Incident-Response-Prozess muss etabliert sein.", "priority": 1, "section": "4.9"},
{"id": "O.Ops_4", "title": "Monitoring", "description": "Systemueberwachung", "requirement_text": "Kritische Systeme und Dienste muessen kontinuierlich ueberwacht werden.", "priority": 2, "section": "4.9"},
# Dokumentation
{"id": "O.Doc_1", "title": "Technische Dokumentation", "description": "Systemarchitektur dokumentiert", "requirement_text": "Die Systemarchitektur und Datenflüsse muessen dokumentiert sein.", "priority": 2, "section": "4.10"},
{"id": "O.Doc_2", "title": "Verarbeitungsverzeichnis", "description": "Art. 30 DSGVO", "requirement_text": "Ein vollstaendiges Verzeichnis von Verarbeitungstaetigkeiten muss gefuehrt werden.", "priority": 1, "section": "4.10"},
{"id": "O.Doc_3", "title": "TOMs", "description": "Technisch-organisatorische Massnahmen", "requirement_text": "Technisch-organisatorische Massnahmen (Art. 32 DSGVO) muessen dokumentiert sein.", "priority": 1, "section": "4.10"},
]
elif code == "BSI-TR-03161-2":
# Teil 2: Web-Anwendungen
return [
# Session Management
{"id": "O.Sess_1", "title": "Session-Timeout", "description": "Automatische Sitzungsbeendigung", "requirement_text": "Sessions muessen nach Inaktivitaet automatisch beendet werden (max. 30 Min).", "priority": 1, "section": "5.1"},
{"id": "O.Sess_2", "title": "Session-ID Sicherheit", "description": "Sichere Session-IDs", "requirement_text": "Session-IDs muessen kryptographisch sicher generiert werden (min. 128 Bit Entropie).", "priority": 1, "section": "5.1"},
{"id": "O.Sess_3", "title": "Session-Regeneration", "description": "ID nach Login erneuern", "requirement_text": "Nach erfolgreicher Authentifizierung muss eine neue Session-ID generiert werden.", "priority": 1, "section": "5.1"},
{"id": "O.Sess_4", "title": "Secure Cookie Flags", "description": "HttpOnly, Secure, SameSite", "requirement_text": "Session-Cookies muessen mit Secure, HttpOnly und SameSite-Flags gesetzt werden.", "priority": 1, "section": "5.1"},
{"id": "O.Sess_5", "title": "Session-Binding", "description": "Session an Client binden", "requirement_text": "Sessions sollten an Client-Eigenschaften (User-Agent, IP) gebunden werden.", "priority": 2, "section": "5.1"},
{"id": "O.Sess_6", "title": "Logout-Funktionalitaet", "description": "Vollstaendiges Logout", "requirement_text": "Beim Logout muss die Session vollstaendig invalidiert werden.", "priority": 1, "section": "5.1"},
# Eingabevalidierung
{"id": "O.Input_1", "title": "Serverseitige Validierung", "description": "Alle Eingaben serverseitig pruefen", "requirement_text": "Alle Benutzereingaben muessen serverseitig validiert werden.", "priority": 1, "section": "5.2"},
{"id": "O.Input_2", "title": "Whitelist-Validierung", "description": "Erlaubte Zeichen definieren", "requirement_text": "Eingabevalidierung sollte auf Whitelist-Basis erfolgen.", "priority": 1, "section": "5.2"},
{"id": "O.Input_3", "title": "Encoding", "description": "Korrekte Zeichenkodierung", "requirement_text": "Einheitliche Zeichenkodierung (UTF-8) muss durchgesetzt werden.", "priority": 2, "section": "5.2"},
{"id": "O.Input_4", "title": "Datei-Upload Validierung", "description": "Uploads pruefen", "requirement_text": "Datei-Uploads muessen auf Typ, Groesse und Inhalt validiert werden.", "priority": 1, "section": "5.2"},
# Injection-Schutz
{"id": "O.SQL_1", "title": "SQL-Injection Schutz", "description": "Prepared Statements", "requirement_text": "SQL-Anfragen muessen parametrisiert sein (Prepared Statements).", "priority": 1, "section": "5.3"},
{"id": "O.SQL_2", "title": "ORM Nutzung", "description": "Abstraktionsschicht nutzen", "requirement_text": "Es sollte ein ORM oder Query Builder verwendet werden.", "priority": 2, "section": "5.3"},
{"id": "O.Cmd_1", "title": "Command Injection Schutz", "description": "Keine Shell-Befehle mit Eingaben", "requirement_text": "Benutzereingaben duerfen nicht in Shell-Befehlen verwendet werden.", "priority": 1, "section": "5.3"},
{"id": "O.LDAP_1", "title": "LDAP Injection Schutz", "description": "LDAP-Queries absichern", "requirement_text": "LDAP-Queries muessen gegen Injection geschuetzt sein.", "priority": 1, "section": "5.3"},
{"id": "O.XML_1", "title": "XML Injection Schutz", "description": "XXE verhindern", "requirement_text": "XML-Parser muessen gegen XXE-Angriffe konfiguriert sein.", "priority": 1, "section": "5.3"},
# XSS-Schutz
{"id": "O.XSS_1", "title": "Output Encoding", "description": "Kontextabhaengiges Escaping", "requirement_text": "Ausgaben muessen kontextabhaengig (HTML, JS, CSS, URL) escaped werden.", "priority": 1, "section": "5.4"},
{"id": "O.XSS_2", "title": "Content Security Policy", "description": "CSP-Header setzen", "requirement_text": "Ein restriktiver Content-Security-Policy-Header muss gesetzt sein.", "priority": 1, "section": "5.4"},
{"id": "O.XSS_3", "title": "DOM-basiertes XSS", "description": "DOM-Manipulation absichern", "requirement_text": "JavaScript-DOM-Manipulationen muessen sicher implementiert sein.", "priority": 1, "section": "5.4"},
{"id": "O.XSS_4", "title": "Template-Engine Escaping", "description": "Auto-Escaping aktivieren", "requirement_text": "Template-Engines muessen mit aktiviertem Auto-Escaping verwendet werden.", "priority": 1, "section": "5.4"},
# CSRF-Schutz
{"id": "O.CSRF_1", "title": "Anti-CSRF Token", "description": "Token bei State-Changes", "requirement_text": "Zustandsaendernde Anfragen muessen mit Anti-CSRF-Token geschuetzt sein.", "priority": 1, "section": "5.5"},
{"id": "O.CSRF_2", "title": "SameSite Cookie", "description": "SameSite-Attribut setzen", "requirement_text": "Cookies sollten das SameSite-Attribut (Strict oder Lax) haben.", "priority": 1, "section": "5.5"},
{"id": "O.CSRF_3", "title": "Referer-Pruefung", "description": "Origin validieren", "requirement_text": "Bei kritischen Aktionen sollte der Origin/Referer-Header geprueft werden.", "priority": 2, "section": "5.5"},
# Security Headers
{"id": "O.Head_1", "title": "X-Content-Type-Options", "description": "nosniff setzen", "requirement_text": "Der X-Content-Type-Options: nosniff Header muss gesetzt sein.", "priority": 1, "section": "5.6"},
{"id": "O.Head_2", "title": "X-Frame-Options", "description": "Clickjacking-Schutz", "requirement_text": "X-Frame-Options oder CSP frame-ancestors muss Clickjacking verhindern.", "priority": 1, "section": "5.6"},
{"id": "O.Head_3", "title": "X-XSS-Protection", "description": "Browser XSS-Filter", "requirement_text": "X-XSS-Protection sollte aktiviert sein (oder CSP nutzen).", "priority": 2, "section": "5.6"},
{"id": "O.Head_4", "title": "Referrer-Policy", "description": "Referrer einschraenken", "requirement_text": "Eine restriktive Referrer-Policy sollte gesetzt sein.", "priority": 2, "section": "5.6"},
{"id": "O.Head_5", "title": "Permissions-Policy", "description": "Browser-Features einschraenken", "requirement_text": "Nicht benoetigte Browser-APIs sollten per Permissions-Policy deaktiviert werden.", "priority": 3, "section": "5.6"},
# Fehlerbehandlung
{"id": "O.Err_1", "title": "Generische Fehlermeldungen", "description": "Keine technischen Details", "requirement_text": "Fehlermeldungen an Benutzer duerfen keine technischen Details enthalten.", "priority": 1, "section": "5.7"},
{"id": "O.Err_2", "title": "Custom Error Pages", "description": "Eigene Fehlerseiten", "requirement_text": "Standard-Fehlerseiten des Servers muessen durch eigene ersetzt werden.", "priority": 2, "section": "5.7"},
{"id": "O.Err_3", "title": "Exception Handling", "description": "Alle Exceptions abfangen", "requirement_text": "Unbehandelte Exceptions muessen abgefangen und geloggt werden.", "priority": 1, "section": "5.7"},
# API-Sicherheit
{"id": "O.API_1", "title": "API-Authentifizierung", "description": "API-Keys oder OAuth", "requirement_text": "APIs muessen authentifiziert werden (API-Keys, OAuth, JWT).", "priority": 1, "section": "5.8"},
{"id": "O.API_2", "title": "Rate Limiting", "description": "Anfragen begrenzen", "requirement_text": "APIs muessen Rate-Limiting implementieren.", "priority": 1, "section": "5.8"},
{"id": "O.API_3", "title": "Input-Validierung API", "description": "Request-Body validieren", "requirement_text": "API-Request-Bodies muessen gegen ein Schema validiert werden.", "priority": 1, "section": "5.8"},
{"id": "O.API_4", "title": "Versionierung", "description": "API-Versionen", "requirement_text": "APIs sollten versioniert sein um Breaking Changes zu vermeiden.", "priority": 3, "section": "5.8"},
# Client-Sicherheit
{"id": "O.JS_1", "title": "JavaScript Sicherheit", "description": "Sichere JS-Praktiken", "requirement_text": "JavaScript muss sicher implementiert sein (kein eval, innerHTML mit Vorsicht).", "priority": 1, "section": "5.9"},
{"id": "O.JS_2", "title": "Third-Party Scripts", "description": "Externe Scripts absichern", "requirement_text": "Third-Party Scripts muessen mit SRI oder CSP abgesichert werden.", "priority": 1, "section": "5.9"},
{"id": "O.Store_1", "title": "Lokale Speicherung", "description": "LocalStorage sicher nutzen", "requirement_text": "Sensible Daten duerfen nicht im LocalStorage/SessionStorage gespeichert werden.", "priority": 1, "section": "5.9"},
]
elif code == "BSI-TR-03161-3":
# Teil 3: Hintergrundsysteme (Backend)
return [
# Systemarchitektur
{"id": "O.Arch_1", "title": "Defense in Depth", "description": "Mehrschichtige Sicherheit", "requirement_text": "Eine mehrschichtige Sicherheitsarchitektur (Defense in Depth) muss implementiert sein.", "priority": 1, "section": "6.1"},
{"id": "O.Arch_2", "title": "Segmentierung", "description": "Netzwerksegmentierung", "requirement_text": "Das Netzwerk muss segmentiert sein (DMZ, interne Zonen).", "priority": 1, "section": "6.1"},
{"id": "O.Arch_3", "title": "Microservices Isolation", "description": "Services isolieren", "requirement_text": "Microservices sollten minimal gekoppelt und isoliert sein.", "priority": 2, "section": "6.1"},
{"id": "O.Arch_4", "title": "Zero Trust", "description": "Kein implizites Vertrauen", "requirement_text": "Interne Kommunikation sollte nach Zero-Trust-Prinzipien abgesichert sein.", "priority": 2, "section": "6.1"},
# Datenspeicherung
{"id": "O.DB_1", "title": "Datenbank-Sicherheit", "description": "DB abhaerten", "requirement_text": "Datenbanken muessen gehaertet sein (keine Default-Credentials, minimale Rechte).", "priority": 1, "section": "6.2"},
{"id": "O.DB_2", "title": "Verschluesselung in DB", "description": "Sensible Felder verschluesseln", "requirement_text": "Sensible Daten sollten in der Datenbank verschluesselt gespeichert werden.", "priority": 1, "section": "6.2"},
{"id": "O.DB_3", "title": "Backup-Verschluesselung", "description": "Backups verschluesseln", "requirement_text": "Datenbank-Backups muessen verschluesselt sein.", "priority": 1, "section": "6.2"},
{"id": "O.DB_4", "title": "Zugriffskontrolle DB", "description": "DB-Zugriffe beschraenken", "requirement_text": "Der Datenbankzugriff muss auf notwendige Dienste beschraenkt sein.", "priority": 1, "section": "6.2"},
{"id": "O.Store_2", "title": "Dateispeicher-Sicherheit", "description": "Uploads isolieren", "requirement_text": "Hochgeladene Dateien muessen isoliert und mit Malware-Scanning verarbeitet werden.", "priority": 1, "section": "6.2"},
# Container & Infrastruktur
{"id": "O.Cont_1", "title": "Container-Sicherheit", "description": "Images scannen", "requirement_text": "Container-Images muessen auf Schwachstellen gescannt werden.", "priority": 1, "section": "6.3"},
{"id": "O.Cont_2", "title": "Rootless Container", "description": "Nicht als Root laufen", "requirement_text": "Container sollten nicht als Root-User ausgefuehrt werden.", "priority": 1, "section": "6.3"},
{"id": "O.Cont_3", "title": "Image-Herkunft", "description": "Vertrauenswuerdige Images", "requirement_text": "Es duerfen nur Images aus vertrauenswuerdigen Quellen verwendet werden.", "priority": 1, "section": "6.3"},
{"id": "O.Cont_4", "title": "Read-Only Filesystem", "description": "Unveraenderliches Dateisystem", "requirement_text": "Container sollten mit Read-Only Root-Filesystem laufen wo moeglich.", "priority": 2, "section": "6.3"},
{"id": "O.Cont_5", "title": "Resource Limits", "description": "CPU/Memory begrenzen", "requirement_text": "Container muessen Resource-Limits (CPU, Memory) konfiguriert haben.", "priority": 2, "section": "6.3"},
# Secrets Management
{"id": "O.Sec_1", "title": "Secrets Management", "description": "Zentrale Secrets-Verwaltung", "requirement_text": "Sensible Konfiguration (Passwoerter, Keys) muss zentral und sicher verwaltet werden.", "priority": 1, "section": "6.4"},
{"id": "O.Sec_2", "title": "Keine Hardcoded Secrets", "description": "Secrets nicht im Code", "requirement_text": "Secrets duerfen nicht im Quellcode oder in Git-Repositories stehen.", "priority": 1, "section": "6.4"},
{"id": "O.Sec_3", "title": "Secret Rotation", "description": "Regelmaessige Rotation", "requirement_text": "Secrets und API-Keys sollten regelmaessig rotiert werden.", "priority": 2, "section": "6.4"},
{"id": "O.Sec_4", "title": "Vault Integration", "description": "Secrets-Vault nutzen", "requirement_text": "Ein Secrets-Management-System (HashiCorp Vault o.ae.) sollte verwendet werden.", "priority": 2, "section": "6.4"},
# Kommunikation
{"id": "O.Comm_1", "title": "Service-to-Service TLS", "description": "Interne Verschluesselung", "requirement_text": "Auch interne Service-Kommunikation sollte verschluesselt sein (mTLS).", "priority": 2, "section": "6.5"},
{"id": "O.Comm_2", "title": "Message Queue Sicherheit", "description": "Queue-Zugriff absichern", "requirement_text": "Message Queues muessen authentifiziert und autorisiert werden.", "priority": 1, "section": "6.5"},
{"id": "O.Comm_3", "title": "API Gateway", "description": "Zentraler Zugangspunkt", "requirement_text": "Ein API Gateway sollte als zentraler Zugangspunkt dienen.", "priority": 2, "section": "6.5"},
# Monitoring & Logging
{"id": "O.Mon_1", "title": "Zentrale Logs", "description": "Log-Aggregation", "requirement_text": "Logs aller Services muessen zentral aggregiert werden.", "priority": 1, "section": "6.6"},
{"id": "O.Mon_2", "title": "Security Monitoring", "description": "Anomalie-Erkennung", "requirement_text": "Sicherheitsrelevante Ereignisse muessen ueberwacht und alarmiert werden.", "priority": 1, "section": "6.6"},
{"id": "O.Mon_3", "title": "Metriken", "description": "Performance-Monitoring", "requirement_text": "System-Metriken (CPU, Memory, Latenz) sollten erfasst und ueberwacht werden.", "priority": 2, "section": "6.6"},
{"id": "O.Mon_4", "title": "Alerting", "description": "Alarmierung konfigurieren", "requirement_text": "Kritische Schwellwerte muessen definiert und alarmiert werden.", "priority": 1, "section": "6.6"},
# CI/CD Sicherheit
{"id": "O.CI_1", "title": "Pipeline-Sicherheit", "description": "CI/CD absichern", "requirement_text": "CI/CD-Pipelines muessen abgesichert sein (Secrets, Zugriffsrechte).", "priority": 1, "section": "6.7"},
{"id": "O.CI_2", "title": "SAST/DAST", "description": "Automatisierte Security-Tests", "requirement_text": "Statische und dynamische Sicherheitsanalysen sollten in die Pipeline integriert sein.", "priority": 2, "section": "6.7"},
{"id": "O.CI_3", "title": "Dependency Scanning", "description": "Abhaengigkeiten pruefen", "requirement_text": "Abhaengigkeiten muessen automatisiert auf Schwachstellen geprueft werden.", "priority": 1, "section": "6.7"},
{"id": "O.CI_4", "title": "SBOM", "description": "Software Bill of Materials", "requirement_text": "Ein SBOM (Software Bill of Materials) sollte generiert und gepflegt werden.", "priority": 2, "section": "6.7"},
# Disaster Recovery
{"id": "O.DR_1", "title": "Backup-Strategie", "description": "3-2-1 Backup-Regel", "requirement_text": "Backups sollten der 3-2-1-Regel folgen (3 Kopien, 2 Medien, 1 offsite).", "priority": 1, "section": "6.8"},
{"id": "O.DR_2", "title": "Recovery-Tests", "description": "Restore regelmaessig testen", "requirement_text": "Die Wiederherstellung aus Backups muss regelmaessig getestet werden.", "priority": 1, "section": "6.8"},
{"id": "O.DR_3", "title": "RTO/RPO", "description": "Recovery-Ziele definieren", "requirement_text": "Recovery Time Objective (RTO) und Recovery Point Objective (RPO) muessen definiert sein.", "priority": 2, "section": "6.8"},
]
return []
def get_known_sources(self) -> List[Dict[str, Any]]:
"""Get list of known regulation sources with metadata."""
sources = []
for code, info in self.KNOWN_SOURCES.items():
# Check database for existing data
regulation = self.reg_repo.get_by_code(code)
requirement_count = 0
if regulation:
requirement_count = self.db.query(RequirementDB).filter(
RequirementDB.regulation_id == regulation.id
).count()
sources.append({
"code": code,
"url": info["url"],
"source_type": info["type"].value,
"regulation_type": info["regulation_type"].value,
"has_data": regulation is not None,
"requirement_count": requirement_count,
})
return sources