This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BreakPilot Dev 19855efacc
Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
feat: BreakPilot PWA - Full codebase (clean push without large binaries)
All services: admin-v2, studio-v2, website, ai-compliance-sdk,
consent-service, klausur-service, voice-service, and infrastructure.
Large PDFs and compiled binaries excluded via .gitignore.
2026-02-11 13:25:58 +01:00

408 lines
13 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import { useState } from 'react'
import AdminLayout from '@/components/admin/AdminLayout'
import {
WizardStepper,
WizardNavigation,
EducationCard,
ArchitectureContext,
TestRunner,
TestSummary,
type WizardStep,
type TestCategoryResult,
type FullTestResults,
type EducationContent,
type ArchitectureContextType,
} from '@/components/wizard'
// ==============================================
// Constants
// ==============================================
const BACKEND_URL = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000'
const STEPS: WizardStep[] = [
{ id: 'welcome', name: 'Willkommen', icon: '👋', status: 'pending' },
{ id: 'api-health', name: 'API Status', icon: '💚', status: 'pending', category: 'api-health' },
{ id: 'sast', name: 'SAST', icon: '🔍', status: 'pending', category: 'sast' },
{ id: 'sca', name: 'SCA', icon: '📦', status: 'pending', category: 'sca' },
{ id: 'secrets', name: 'Secrets', icon: '🔑', status: 'pending', category: 'secrets' },
{ id: 'sbom', name: 'SBOM', icon: '📋', status: 'pending', category: 'sbom' },
{ id: 'summary', name: 'Zusammenfassung', icon: '📊', status: 'pending' },
]
const EDUCATION_CONTENT: Record<string, EducationContent> = {
'welcome': {
title: 'Willkommen zum Security Wizard',
content: [
'DevSecOps integriert Sicherheit in den gesamten Entwicklungsprozess.',
'',
'In diesem Wizard lernen Sie:',
'• SAST: Statische Code-Analyse mit Semgrep',
'• SCA: Abhaengigkeits-Scans mit Trivy/Grype',
'• Secrets: Erkennung von Credentials im Code',
'• SBOM: Software Bill of Materials',
'',
'Shift Left Security: Fehler frueh finden, nicht in Produktion!',
],
},
'api-health': {
title: 'Security API - DevSecOps Dashboard',
content: [
'Die Security API steuert alle Sicherheitsscans.',
'',
'Endpunkte:',
'• /api/security/scan - Scan starten',
'• /api/security/findings - Ergebnisse abrufen',
'• /api/security/sbom - SBOM generieren',
'• /api/security/dashboard - Uebersicht',
'',
'Verfuegbarkeit kritisch fuer:',
'• CI/CD Pipeline Integration',
'• Automatisierte Security Gates',
'• Compliance Reporting',
],
},
'sast': {
title: 'SAST - Static Application Security Testing',
content: [
'Semgrep analysiert Quellcode OHNE ihn auszufuehren.',
'',
'Findet:',
'• SQL Injection Patterns',
'• XSS Vulnerabilities',
'• Hardcoded Credentials',
'• Insecure Crypto Usage',
'• Path Traversal Risks',
'',
'Vorteile:',
'• Schnell (Minuten, nicht Stunden)',
'• Findet Fehler VOR dem Deployment',
'• Keine laufende Anwendung noetig',
],
},
'sca': {
title: 'SCA - Software Composition Analysis',
content: [
'Prueft Abhaengigkeiten auf bekannte Schwachstellen (CVEs).',
'',
'Gescannt werden:',
'• Python packages (requirements.txt)',
'• Node modules (package.json)',
'• Go modules (go.mod)',
'• Container Images',
'',
'Bekannte Angriffe:',
'• Log4Shell (CVE-2021-44228)',
'• NPM Supply Chain Attacks',
'• PyPI Typosquatting',
],
},
'secrets': {
title: 'Secret Detection mit Gitleaks',
content: [
'Findet versehentlich eingecheckte Secrets:',
'',
'• AWS/GCP/Azure Credentials',
'• Database Passwords',
'• Private SSH Keys',
'• OAuth Tokens',
'• JWT Secrets',
'',
'Risiken ohne Detection:',
'• Kompromittierte Cloud-Accounts',
'• Datenlecks durch DB-Zugriff',
'• Git History: Einmal gepusht, schwer zu entfernen!',
],
},
'sbom': {
title: 'SBOM - Software Bill of Materials',
content: [
'Vollstaendige Inventarliste aller Software-Komponenten.',
'',
'Rechtliche Anforderungen:',
'• US Executive Order 14028 (2021)',
'• EU Cyber Resilience Act',
'• Supply Chain Transparency',
'',
'Inhalt:',
'• Alle Abhaengigkeiten mit Versionen',
'• Lizenzen (GPL, MIT, Apache, etc.)',
'• Bekannte Vulnerabilities',
'',
'Bei Zero-Day: Schnell pruefen wer betroffen ist',
],
},
'summary': {
title: 'Test-Zusammenfassung',
content: [
'Hier sehen Sie eine Uebersicht aller durchgefuehrten Tests:',
'• Anzahl bestandener Tests',
'• Fehlgeschlagene Tests mit Details',
'• Empfehlungen zur Behebung',
],
},
}
const ARCHITECTURE_CONTEXTS: Record<string, ArchitectureContextType> = {
'api-health': {
layer: 'api',
services: ['backend'],
dependencies: ['PostgreSQL', 'Scanner Tools'],
dataFlow: ['API Request', 'Scanner Dispatch', 'Result Storage'],
},
'sast': {
layer: 'service',
services: ['backend'],
dependencies: ['semgrep', 'Git Repository'],
dataFlow: ['Source Code', 'Semgrep Scanner', 'Findings', 'Dashboard'],
},
'sca': {
layer: 'service',
services: ['backend'],
dependencies: ['trivy', 'grype', 'CVE Database'],
dataFlow: ['Dependencies', 'Scanner', 'CVE Lookup', 'Report'],
},
'secrets': {
layer: 'service',
services: ['backend'],
dependencies: ['gitleaks', 'Git Repository'],
dataFlow: ['Git History', 'Pattern Matching', 'Findings'],
},
'sbom': {
layer: 'service',
services: ['backend'],
dependencies: ['syft', 'cyclonedx'],
dataFlow: ['Container/Code', 'Syft Analysis', 'CycloneDX SBOM'],
},
}
// ==============================================
// Main Component
// ==============================================
export default function SecurityWizardPage() {
const [currentStep, setCurrentStep] = useState(0)
const [steps, setSteps] = useState<WizardStep[]>(STEPS)
const [categoryResults, setCategoryResults] = useState<Record<string, TestCategoryResult>>({})
const [fullResults, setFullResults] = useState<FullTestResults | null>(null)
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const currentStepData = steps[currentStep]
const isTestStep = currentStepData?.category !== undefined
const isWelcome = currentStepData?.id === 'welcome'
const isSummary = currentStepData?.id === 'summary'
const runCategoryTest = async (category: string) => {
setIsLoading(true)
setError(null)
try {
const response = await fetch(`${BACKEND_URL}/api/admin/security-tests/${category}`, {
method: 'POST',
})
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
const result: TestCategoryResult = await response.json()
setCategoryResults((prev) => ({ ...prev, [category]: result }))
setSteps((prev) =>
prev.map((step) =>
step.category === category
? { ...step, status: result.failed === 0 ? 'completed' : 'failed' }
: step
)
)
} catch (err) {
setError(err instanceof Error ? err.message : 'Unbekannter Fehler')
} finally {
setIsLoading(false)
}
}
const runAllTests = async () => {
setIsLoading(true)
setError(null)
try {
const response = await fetch(`${BACKEND_URL}/api/admin/security-tests/run-all`, {
method: 'POST',
})
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
const results: FullTestResults = await response.json()
setFullResults(results)
setSteps((prev) =>
prev.map((step) => {
if (step.category) {
const catResult = results.categories.find((c) => c.category === step.category)
if (catResult) {
return { ...step, status: catResult.failed === 0 ? 'completed' : 'failed' }
}
}
return step
})
)
const newCategoryResults: Record<string, TestCategoryResult> = {}
results.categories.forEach((cat) => {
newCategoryResults[cat.category] = cat
})
setCategoryResults(newCategoryResults)
} catch (err) {
setError(err instanceof Error ? err.message : 'Unbekannter Fehler')
} finally {
setIsLoading(false)
}
}
const goToNext = () => {
if (currentStep < steps.length - 1) {
setSteps((prev) =>
prev.map((step, idx) =>
idx === currentStep && step.status === 'pending'
? { ...step, status: 'completed' }
: step
)
)
setCurrentStep((prev) => prev + 1)
}
}
const goToPrev = () => {
if (currentStep > 0) {
setCurrentStep((prev) => prev - 1)
}
}
const handleStepClick = (index: number) => {
if (index <= currentStep || steps[index - 1]?.status !== 'pending') {
setCurrentStep(index)
}
}
return (
<AdminLayout
title="Security Wizard"
description="Interaktives Lernen und Testen der DevSecOps Pipeline"
>
{/* Header */}
<div className="bg-white rounded-lg shadow p-4 mb-6 flex items-center justify-between">
<div className="flex items-center">
<span className="text-3xl mr-3">🛡</span>
<div>
<h2 className="text-lg font-bold text-gray-800">DevSecOps Test Wizard</h2>
<p className="text-sm text-gray-600">SAST, SCA, Secrets, SBOM</p>
</div>
</div>
<a href="/admin/security" className="text-blue-600 hover:text-blue-800 text-sm">
Zurueck zum Security Dashboard
</a>
</div>
{/* Stepper */}
<div className="bg-white rounded-lg shadow p-6 mb-6">
<WizardStepper steps={steps} currentStep={currentStep} onStepClick={handleStepClick} />
</div>
{/* Content */}
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center mb-6">
<span className="text-3xl mr-3">{currentStepData?.icon}</span>
<div>
<h2 className="text-xl font-bold text-gray-800">
Schritt {currentStep + 1}: {currentStepData?.name}
</h2>
<p className="text-gray-500 text-sm">
{currentStep + 1} von {steps.length}
</p>
</div>
</div>
<EducationCard content={EDUCATION_CONTENT[currentStepData?.id || '']} />
{isTestStep && currentStepData?.category && ARCHITECTURE_CONTEXTS[currentStepData.category] && (
<ArchitectureContext
context={ARCHITECTURE_CONTEXTS[currentStepData.category]}
currentStep={currentStepData.name}
/>
)}
{error && (
<div className="bg-red-50 border border-red-200 text-red-700 rounded-lg p-4 mb-6">
<strong>Fehler:</strong> {error}
</div>
)}
{isWelcome && (
<div className="text-center py-8">
<button
onClick={goToNext}
className="bg-blue-600 text-white px-8 py-3 rounded-lg font-medium hover:bg-blue-700 transition-colors"
>
Wizard starten
</button>
</div>
)}
{isTestStep && currentStepData?.category && (
<TestRunner
category={currentStepData.category}
categoryResult={categoryResults[currentStepData.category]}
isLoading={isLoading}
onRunTests={() => runCategoryTest(currentStepData.category!)}
/>
)}
{isSummary && (
<div>
{!fullResults ? (
<div className="text-center py-8">
<p className="text-gray-600 mb-4">
Fuehren Sie alle Tests aus um eine Zusammenfassung zu sehen.
</p>
<button
onClick={runAllTests}
disabled={isLoading}
className={`px-6 py-3 rounded-lg font-medium transition-colors ${
isLoading
? 'bg-gray-400 cursor-not-allowed'
: 'bg-blue-600 text-white hover:bg-blue-700'
}`}
>
{isLoading ? 'Alle Tests laufen...' : 'Alle Tests ausfuehren'}
</button>
</div>
) : (
<TestSummary results={fullResults} />
)}
</div>
)}
<WizardNavigation
currentStep={currentStep}
totalSteps={steps.length}
onPrev={goToPrev}
onNext={goToNext}
showNext={!isSummary}
isLoading={isLoading}
/>
</div>
<div className="text-center text-gray-500 text-sm mt-6">
Diese Tests pruefen die DevSecOps Security-Konfiguration.
Bei Fragen wenden Sie sich an das Security-Team.
</div>
</AdminLayout>
)
}