knowledgebase overhaul
This commit is contained in:
parent
e7800724bb
commit
e78e738295
12
.astro/content.d.ts
vendored
12
.astro/content.d.ts
vendored
@ -162,6 +162,16 @@ declare module 'astro:content' {
|
||||
};
|
||||
|
||||
type DataEntryMap = {
|
||||
"knowledgebase": Record<string, {
|
||||
id: string;
|
||||
render(): Render[".md"];
|
||||
slug: string;
|
||||
body: string;
|
||||
collection: "knowledgebase";
|
||||
data: InferEntrySchema<"knowledgebase">;
|
||||
rendered?: RenderedContent;
|
||||
filePath?: string;
|
||||
}>;
|
||||
|
||||
};
|
||||
|
||||
@ -194,6 +204,6 @@ declare module 'astro:content' {
|
||||
LiveContentConfig['collections'][C]['loader']
|
||||
>;
|
||||
|
||||
export type ContentConfig = typeof import("../src/content.config.mjs");
|
||||
export type ContentConfig = typeof import("../src/content/config.js");
|
||||
export type LiveContentConfig = never;
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
1
.astro/types.d.ts
vendored
1
.astro/types.d.ts
vendored
@ -1 +1,2 @@
|
||||
/// <reference types="astro/client" />
|
||||
/// <reference path="content.d.ts" />
|
215
README.md
215
README.md
@ -4,16 +4,17 @@ Ein kuratiertes Verzeichnis für digitale Forensik- und Incident-Response-Tools
|
||||
|
||||
## 🎯 Projektübersicht
|
||||
|
||||
CC24-Hub bietet eine strukturierte Übersicht über bewährte DFIR-Tools und -Methoden mit intelligenten Empfehlungsfunktionen. Das Projekt orientiert sich am NIST-Framework (SP 800-86) und kategorisiert nach forensischen Domänen und Untersuchungsphasen.
|
||||
CC24-Hub bietet eine strukturierte Übersicht über bewährte DFIR-Tools, -Methoden und -Konzepte mit intelligenten Empfehlungsfunktionen. Das Projekt orientiert sich am NIST-Framework (SP 800-86) und kategorisiert nach forensischen Domänen und Untersuchungsphasen.
|
||||
|
||||
### Hauptfunktionen
|
||||
|
||||
- **KI-gestützte Empfehlungen**: Workflow- und Tool-Vorschläge basierend auf forensischen Szenarien
|
||||
- **Tools & Methoden**: Software-Tools UND forensische Verfahren/Prozeduren
|
||||
- **Drei Kategorien**: Software-Tools, forensische Methoden UND Grundlagenkonzepte
|
||||
- **Matrix-Ansicht**: Visualisierung nach Domänen × Prozess-Phasen
|
||||
- **Erweiterte Filter**: Suche nach Name, Tags, Domäne, Phase, Lizenz
|
||||
- **CC24-Server Integration**: Direkte SSO-Links zu gehosteten Instanzen
|
||||
- **Knowledgebase**: Erweiterte Dokumentation mit praktischen Erkenntnissen
|
||||
- **Konzept-Verlinkung**: Automatische Verknüpfung zwischen Tools und Grundlagenkonzepten
|
||||
- **Status-Monitoring**: Live-Überwachung verfügbarer Services
|
||||
- **Responsive Design**: Dark/Light Mode, Mobile-optimiert
|
||||
|
||||
@ -22,7 +23,7 @@ CC24-Hub bietet eine strukturierte Übersicht über bewährte DFIR-Tools und -Me
|
||||
- **Framework**: [Astro](https://astro.build/) mit Server-Side Rendering
|
||||
- **Backend**: Node.js mit API-Routen für KI und Authentifizierung
|
||||
- **Styling**: Vanilla CSS mit CSS Custom Properties
|
||||
- **Datenformat**: YAML für Tool-/Methoden-Definitionen
|
||||
- **Datenformat**: YAML für Tool-/Methoden-/Konzept-Definitionen
|
||||
- **KI-Integration**: Mistral AI über OpenAI-kompatible API
|
||||
- **Authentifizierung**: OIDC (OpenID Connect) mit JWT-Sessions
|
||||
- **Node.js**: >=18.0.0
|
||||
@ -248,16 +249,16 @@ Nextcloud OIDC Einstellungen (sollte auch mit anderen OIDC-Anwendungen klappen):
|
||||
- **Redirect URI**: `https://your-domain.com/auth/callback`
|
||||
- **Logout URI**: `https://your-domain.com`
|
||||
|
||||
## 🔧 Tool-/Methoden-Datenformat
|
||||
## 🔧 Datenformat & Kategorien
|
||||
|
||||
Einträge werden in `src/data/tools.yaml` definiert:
|
||||
Die CC24-Hub verwaltet drei Kategorien von Einträgen in `src/data/tools.yaml`:
|
||||
|
||||
### Software-Tool Beispiel
|
||||
### 1. Software-Tools
|
||||
|
||||
```yaml
|
||||
tools:
|
||||
- name: "Autopsy"
|
||||
icon: "📱"
|
||||
icon: "📦"
|
||||
type: "software"
|
||||
description: "Die führende Open-Source-Alternative zu kommerziellen Forensik-Suiten"
|
||||
domains: ["incident-response", "law-enforcement"]
|
||||
@ -266,18 +267,19 @@ tools:
|
||||
skillLevel: "intermediate"
|
||||
accessType: "download"
|
||||
url: "https://www.autopsy.com/"
|
||||
projectUrl: "https://autopsy.cc24.dev" # CC24-Server URL
|
||||
projectUrl: "https://autopsy.cc24.dev" # CC24-Server URL (optional)
|
||||
license: "Apache 2.0"
|
||||
knowledgebase: true # Hat erweiterte Dokumentation
|
||||
related_concepts: ["Hash Functions & Digital Signatures", "SQL Query Fundamentals"] # Verknüpfung zu Konzepten
|
||||
tags: ["gui", "filesystem", "timeline-analysis"]
|
||||
statusUrl: "https://status.example.com/badge/1/status"
|
||||
statusUrl: "https://status.example.com/badge/1/status" # Status-Badge URL (optional)
|
||||
```
|
||||
|
||||
### Forensische Methode Beispiel
|
||||
### 2. Forensische Methoden
|
||||
|
||||
```yaml
|
||||
- name: "Live Memory Acquisition Procedure"
|
||||
icon: "🧠"
|
||||
icon: "📋"
|
||||
type: "method"
|
||||
description: "Standardisiertes Verfahren zur forensisch korrekten Akquisition des Arbeitsspeichers"
|
||||
domains: ["incident-response", "law-enforcement"]
|
||||
@ -289,9 +291,30 @@ tools:
|
||||
projectUrl: null
|
||||
license: null
|
||||
knowledgebase: false
|
||||
related_concepts: null # Können optional Konzepte verknüpfen
|
||||
tags: ["memory-acquisition", "volatile-evidence", "procedure"]
|
||||
```
|
||||
|
||||
### 3. Grundlagenkonzepte (NEU)
|
||||
|
||||
```yaml
|
||||
- name: "Regular Expressions (Regex)"
|
||||
icon: "🔤"
|
||||
type: "concept"
|
||||
description: "Pattern matching language for searching, extracting, and manipulating text"
|
||||
domains: ["incident-response", "malware-analysis"]
|
||||
phases: ["examination", "analysis"]
|
||||
platforms: [] # Konzepte haben keine Plattformen
|
||||
skillLevel: "intermediate"
|
||||
accessType: null
|
||||
url: "https://regexr.com/"
|
||||
projectUrl: null
|
||||
license: null
|
||||
knowledgebase: true # Erweiterte Erklärung in Knowledgebase
|
||||
related_concepts: null # Konzepte verweisen nicht auf andere Konzepte
|
||||
tags: ["pattern-matching", "text-processing", "log-analysis"]
|
||||
```
|
||||
|
||||
### Verfügbare Kategorien
|
||||
|
||||
**Domänen:**
|
||||
@ -314,6 +337,135 @@ tools:
|
||||
- `collaboration-general` - Übergreifend & Kollaboration
|
||||
- `specific-os` - Betriebssysteme
|
||||
|
||||
## 📚 Knowledgebase-System
|
||||
|
||||
### Erweiterte Dokumentation erstellen
|
||||
|
||||
Die Knowledgebase bietet detaillierte Artikel für Tools, Methoden und Konzepte. So erstellen Sie neue Einträge:
|
||||
|
||||
#### 1. Knowledgebase-Flag setzen
|
||||
|
||||
Setzen Sie in `src/data/tools.yaml` das Flag:
|
||||
```yaml
|
||||
knowledgebase: true
|
||||
```
|
||||
|
||||
#### 2. Artikel-Datei erstellen
|
||||
|
||||
Erstellen Sie eine Markdown-Datei in `src/content/knowledgebase/`:
|
||||
|
||||
**Dateiname-Schema:** `[tool-name-slug].md`
|
||||
|
||||
**Beispiel:** `src/content/knowledgebase/autopsy.md`
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: "Autopsy - Umfassende Forensik-Suite"
|
||||
tool_name: "Autopsy"
|
||||
description: "Detaillierte Anleitung und Best Practices für Autopsy"
|
||||
last_updated: 2024-01-15
|
||||
author: "CC24-Team"
|
||||
difficulty: "intermediate"
|
||||
categories: ["filesystem-analysis", "timeline-analysis"]
|
||||
tags: ["gui", "windows", "linux", "open-source"]
|
||||
sections:
|
||||
overview: true
|
||||
installation: true
|
||||
configuration: true
|
||||
usage_examples: true
|
||||
best_practices: true
|
||||
troubleshooting: true
|
||||
advanced_topics: false
|
||||
review_status: "published"
|
||||
---
|
||||
|
||||
# Übersicht
|
||||
|
||||
Autopsy ist eine grafische Benutzeroberfläche für The Sleuth Kit (TSK) und bietet...
|
||||
|
||||
## Installation
|
||||
|
||||
### Windows
|
||||
1. Download der neuesten Version von [autopsy.com](https://www.autopsy.com/)
|
||||
2. Ausführung des Installers mit Administratorrechten
|
||||
3. ...
|
||||
|
||||
## Konfiguration
|
||||
|
||||
### Grundeinstellungen
|
||||
- Arbeitsverzeichnis festlegen
|
||||
- Hash-Algorithmen auswählen
|
||||
- ...
|
||||
|
||||
## Verwendungsbeispiele
|
||||
|
||||
### Fall 1: Gelöschte Dateien wiederherstellen
|
||||
1. Neuen Fall erstellen
|
||||
2. Image hinzufügen
|
||||
3. ...
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Immer Hash-Verifikation durchführen
|
||||
- Regelmäßige Backups der Case-Datenbank
|
||||
- ...
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Problem: Autopsy startet nicht
|
||||
**Lösung:** Java-Version überprüfen...
|
||||
|
||||
### Problem: Langsame Performance
|
||||
**Lösung:** RAM-Zuteilung erhöhen...
|
||||
|
||||
## Weiterführende Themen
|
||||
|
||||
- Integration mit externen Tools
|
||||
- Custom Modules entwickeln
|
||||
- ...
|
||||
```
|
||||
|
||||
#### 3. Schema-Validierung
|
||||
|
||||
Das System validiert automatisch folgende Felder:
|
||||
|
||||
**Pflichtfelder:**
|
||||
- `title`: Anzeigename des Artikels
|
||||
- `tool_name`: Exakter Name aus tools.yaml
|
||||
- `description`: Kurze Beschreibung
|
||||
- `last_updated`: Datum der letzten Aktualisierung
|
||||
- `difficulty`: `novice|beginner|intermediate|advanced|expert`
|
||||
|
||||
**Optionale Felder:**
|
||||
- `author`: Standard "CC24-Team"
|
||||
- `categories`: Array von Kategorien
|
||||
- `tags`: Array von Tags
|
||||
- `sections`: Welche Abschnitte enthalten sind
|
||||
- `review_status`: `draft|review|published` (Standard: `published`)
|
||||
|
||||
#### 4. Automatische Verlinkung
|
||||
|
||||
- Artikel sind automatisch über `/knowledgebase/[tool-slug]` erreichbar
|
||||
- Links werden automatisch in Tool-Details angezeigt
|
||||
- Suchfunktion indiziert Artikel-Inhalte
|
||||
|
||||
### Konzept-Verlinkung
|
||||
|
||||
Tools können mit Grundlagenkonzepten verknüpft werden:
|
||||
|
||||
```yaml
|
||||
# Tool-Definition
|
||||
- name: "Autopsy"
|
||||
related_concepts: ["Hash Functions & Digital Signatures", "SQL Query Fundamentals"]
|
||||
|
||||
# Konzept-Definition
|
||||
- name: "Hash Functions & Digital Signatures"
|
||||
type: "concept"
|
||||
description: "Cryptographic principles for data integrity verification"
|
||||
```
|
||||
|
||||
Die KI-Empfehlungen nutzen diese Verlinkungen für Hintergrundwissen-Empfehlungen.
|
||||
|
||||
## 🤖 KI-Integration
|
||||
|
||||
### Workflow-Empfehlungen
|
||||
@ -322,6 +474,9 @@ Beschreibung forensischer Szenarien für maßgeschneiderte Workflows mit phasenb
|
||||
### Tool-spezifische Empfehlungen
|
||||
Konkrete Tool-Vorschläge für spezifische Probleme mit detaillierten Begründungen, Implementierungsansätzen und Vor-/Nachteilen.
|
||||
|
||||
### Konzept-Integration
|
||||
Die KI berücksichtigt automatisch verknüpfte Grundlagenkonzepte und empfiehlt relevantes Hintergrundwissen.
|
||||
|
||||
**API-Endpunkt:** `/api/ai/query`
|
||||
- **Rate Limiting**: 10 Anfragen pro Minute pro Benutzer
|
||||
- **Modi**: `workflow` (Szenario-basiert) oder `tool` (Problem-spezifisch)
|
||||
@ -338,31 +493,42 @@ OIDC-Integration mit JWT-Sessions:
|
||||
- `src/utils/auth.ts` - Kern-Authentifizierungslogik
|
||||
- `src/pages/api/auth/` - Auth-API-Endpunkte
|
||||
|
||||
## 📚 Weitere Funktionen
|
||||
## 📁 Datei-Referenz
|
||||
|
||||
### Knowledgebase
|
||||
Erweiterte Dokumentation für Tools mit `knowledgebase: true` in `/knowledgebase`. Bietet praktische Erkenntnisse, Konfigurationshinweise und Lektionen aus der Praxis.
|
||||
### Wichtige Konfigurationsdateien
|
||||
- `src/data/tools.yaml` - Hauptdatenbank für Tools, Methoden und Konzepte
|
||||
- `src/content/config.ts` - Schema für Knowledgebase-Artikel
|
||||
- `src/utils/dataService.js` - Datenverarbeitungslogik
|
||||
- `src/styles/global.css` - Zentrale Stylesheet-Definitionen
|
||||
|
||||
### Status-Monitoring
|
||||
Live-Überwachung gehosteter Services in `/status` mit automatischen Status-Badges und direkten Zugriffs-Links.
|
||||
|
||||
### Tool-Editor
|
||||
Standalone WYSIWYG-Editor unter `/dfir_yaml_editor.html` für die Verwaltung der `tools.yaml` mit Bulk-Operationen und Validierung.
|
||||
### Content-Verzeichnisse
|
||||
- `src/content/knowledgebase/` - Knowledgebase-Artikel (Markdown)
|
||||
- `src/components/` - Wiederverwendbare UI-Komponenten
|
||||
- `src/pages/api/` - Backend-API-Endpunkte
|
||||
|
||||
## 🤝 Beitragen
|
||||
|
||||
### Tool/Methode hinzufügen
|
||||
### Tool/Methode/Konzept hinzufügen
|
||||
|
||||
**Option 1: Direkte YAML-Bearbeitung**
|
||||
1. Fork des Repositories erstellen
|
||||
2. `src/data/tools.yaml` bearbeiten
|
||||
3. Pull Request mit Beschreibung erstellen
|
||||
3. Bei Bedarf Knowledgebase-Artikel erstellen
|
||||
4. Pull Request mit Beschreibung erstellen
|
||||
|
||||
**Option 2: Web-Editor verwenden**
|
||||
1. YAML-Editor öffnen (`/dfir_yaml_editor.html`)
|
||||
2. Tool/Methode hinzufügen
|
||||
2. Eintrag hinzufügen (Tool/Methode/Konzept)
|
||||
3. YAML exportieren und in Pull Request einreichen
|
||||
|
||||
### Knowledgebase-Artikel erweitern
|
||||
|
||||
1. Tool in `tools.yaml` identifizieren
|
||||
2. `knowledgebase: true` setzen
|
||||
3. Artikel in `src/content/knowledgebase/[slug].md` erstellen
|
||||
4. Schema-Validierung beachten
|
||||
5. Pull Request einreichen
|
||||
|
||||
### Korrekturen & Verbesserungen
|
||||
|
||||
- Bug Reports und Feature Requests über Issues melden
|
||||
@ -381,6 +547,11 @@ Standalone WYSIWYG-Editor unter `/dfir_yaml_editor.html` für die Verwaltung der
|
||||
- Redirect-URIs im OIDC-Provider registriert?
|
||||
- `AUTH_SECRET` mindestens 32 Zeichen?
|
||||
|
||||
**Knowledgebase-Artikel werden nicht angezeigt:**
|
||||
- `knowledgebase: true` in tools.yaml gesetzt?
|
||||
- Markdown-Datei existiert in `src/content/knowledgebase/`?
|
||||
- Schema-Validierung erfolgreich?
|
||||
|
||||
**Logs prüfen:**
|
||||
```bash
|
||||
# Anwendungs-Logs
|
||||
|
@ -1,20 +1,16 @@
|
||||
// astro.config.mjs - SSR configuration for authentication
|
||||
import { defineConfig } from 'astro/config';
|
||||
import node from '@astrojs/node';
|
||||
|
||||
export default defineConfig({
|
||||
// Server-side rendering for authentication and API routes
|
||||
output: 'server',
|
||||
adapter: node({
|
||||
mode: 'standalone'
|
||||
}),
|
||||
|
||||
// Build configuration
|
||||
build: {
|
||||
assets: '_astro'
|
||||
},
|
||||
|
||||
// Development server
|
||||
server: {
|
||||
port: 4321,
|
||||
host: true
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^9.3.0",
|
||||
"astro": "^5.3.0",
|
||||
"astro": "^5.12.0",
|
||||
"cookie": "^0.6.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"jose": "^5.2.0",
|
||||
|
@ -383,7 +383,45 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
return `<p style="margin: 0; line-height: 1.6; color: var(--color-text);">${text}</p>`;
|
||||
}
|
||||
|
||||
// Display results for workflow mode (existing functionality)
|
||||
// NEW: Function to render background knowledge concepts
|
||||
function renderBackgroundKnowledge(backgroundKnowledge) {
|
||||
if (!backgroundKnowledge || backgroundKnowledge.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const conceptLinks = backgroundKnowledge.map(concept => `
|
||||
<div class="concept-recommendation" style="background-color: var(--color-concept-bg); border: 1px solid var(--color-concept); border-radius: 0.5rem; padding: 1rem; margin-bottom: 0.75rem;">
|
||||
<div style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.5rem;">
|
||||
<button class="concept-link"
|
||||
onclick="event.stopPropagation(); window.showToolDetails('${concept.concept_name}', 'secondary')"
|
||||
style="background: none; border: none; color: var(--color-concept); font-weight: 600; cursor: pointer; text-decoration: underline; font-size: 0.875rem; padding: 0;"
|
||||
onmouseover="this.style.color='var(--color-concept-hover)';"
|
||||
onmouseout="this.style.color='var(--color-concept)';">
|
||||
📚 ${concept.concept_name}
|
||||
</button>
|
||||
<span class="badge" style="background-color: var(--color-concept); color: white; font-size: 0.625rem;">Hintergrundwissen</span>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 0.8125rem; line-height: 1.5; color: var(--color-text-secondary);">
|
||||
${concept.relevance}
|
||||
</p>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
return `
|
||||
<div class="card" style="margin-bottom: 2rem; border-left: 4px solid var(--color-concept);">
|
||||
<h4 style="margin: 0 0 1rem 0; color: var(--color-concept); display: flex; align-items: center; gap: 0.5rem;">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
|
||||
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
|
||||
</svg>
|
||||
Empfohlenes Hintergrundwissen
|
||||
</h4>
|
||||
${conceptLinks}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// Display results for workflow mode (ENHANCED with concepts)
|
||||
function displayWorkflowResults(recommendation, originalQuery) {
|
||||
// Group tools by phase
|
||||
const toolsByPhase = {};
|
||||
@ -434,6 +472,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${renderBackgroundKnowledge(recommendation.background_knowledge)}
|
||||
|
||||
${phaseOrder.map((phase, index) => {
|
||||
const phaseTools = toolsByPhase[phase];
|
||||
if (phaseTools.length === 0) return '';
|
||||
@ -540,7 +580,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
aiResults.appendChild(tempDiv);
|
||||
}
|
||||
|
||||
// Display results for tool-specific mode (new functionality)
|
||||
// Display results for tool-specific mode (ENHANCED with concepts)
|
||||
function displayToolResults(recommendation, originalQuery) {
|
||||
function getSuitabilityText(score) {
|
||||
const suitabilityTexts = {
|
||||
@ -597,6 +637,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${renderBackgroundKnowledge(recommendation.background_knowledge)}
|
||||
|
||||
<div class="tool-recommendations-grid" style="display: grid; gap: 1.5rem;">
|
||||
${recommendation.recommended_tools?.map((toolRec, index) => {
|
||||
const fullTool = tools.find(t => t.name === toolRec.name);
|
||||
|
29
src/content/config.ts
Normal file
29
src/content/config.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
|
||||
const knowledgebaseCollection = defineCollection({
|
||||
type: 'content',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
tool_name: z.string(),
|
||||
description: z.string(),
|
||||
last_updated: z.date(),
|
||||
author: z.string().default('CC24-Team'),
|
||||
difficulty: z.enum(['novice', 'beginner', 'intermediate', 'advanced', 'expert']),
|
||||
categories: z.array(z.string()).default([]),
|
||||
tags: z.array(z.string()).default([]),
|
||||
sections: z.object({
|
||||
overview: z.boolean().default(true),
|
||||
installation: z.boolean().default(false),
|
||||
configuration: z.boolean().default(false),
|
||||
usage_examples: z.boolean().default(true),
|
||||
best_practices: z.boolean().default(true),
|
||||
troubleshooting: z.boolean().default(false),
|
||||
advanced_topics: z.boolean().default(false),
|
||||
}).default({}),
|
||||
review_status: z.enum(['draft', 'review', 'published']).default('published'),
|
||||
})
|
||||
});
|
||||
|
||||
export const collections = {
|
||||
knowledgebase: knowledgebaseCollection,
|
||||
};
|
141
src/content/knowledgebase/kali-linux.md
Normal file
141
src/content/knowledgebase/kali-linux.md
Normal file
@ -0,0 +1,141 @@
|
||||
---
|
||||
title: "Kali Linux - Die Hacker-Distribution für Forensik & Penetration Testing"
|
||||
tool_name: "Kali Linux"
|
||||
description: "Leitfaden zur Installation, Nutzung und Best Practices für Kali Linux – die All-in-One-Plattform für Security-Profis."
|
||||
last_updated: 2025-07-20
|
||||
author: "CC24-Team"
|
||||
difficulty: "intermediate"
|
||||
categories: ["incident-response", "forensics", "penetration-testing"]
|
||||
tags: ["live-boot", "tool-collection", "penetration-testing", "forensics-suite", "virtualization", "arm-support"]
|
||||
sections:
|
||||
overview: true
|
||||
installation: true
|
||||
configuration: true
|
||||
usage_examples: true
|
||||
best_practices: true
|
||||
troubleshooting: true
|
||||
advanced_topics: true
|
||||
review_status: "published"
|
||||
---
|
||||
|
||||
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
|
||||
|
||||
|
||||
# Übersicht
|
||||
|
||||
Kali Linux ist eine auf Debian basierende Linux-Distribution, die speziell für Penetration Testing, digitale Forensik, Reverse Engineering und Incident Response entwickelt wurde. Mit über 600 vorinstallierten Tools ist sie ein unverzichtbares Werkzeug für Security-Experten, Ermittler und forensische Analysten. Die Live-Boot-Funktion erlaubt es, Systeme ohne Spuren zu hinterlassen zu analysieren – ideal für forensische Untersuchungen.
|
||||
|
||||
## Installation
|
||||
|
||||
### Option 1: Live-System (USB/DVD)
|
||||
|
||||
1. ISO-Image von [kali.org](https://www.kali.org/get-kali/) herunterladen.
|
||||
2. Mit **Rufus** oder **balenaEtcher** auf einen USB-Stick schreiben.
|
||||
3. Vom USB-Stick booten (ggf. Boot-Reihenfolge im BIOS anpassen).
|
||||
4. Kali kann direkt ohne Installation im Live-Modus verwendet werden.
|
||||
|
||||
### Option 2: Installation auf Festplatte
|
||||
|
||||
1. ISO-Image booten und **Graphical Install** wählen.
|
||||
2. Schritt-für-Schritt durch den Installationsassistenten navigieren:
|
||||
- Sprache, Zeitzone und Tastaturlayout auswählen
|
||||
- Partitionierung konfigurieren (automatisch oder manuell)
|
||||
- Benutzerkonten erstellen
|
||||
3. Nach Installation Neustart durchführen.
|
||||
|
||||
### Option 3: Virtuelle Maschine (VM)
|
||||
|
||||
- Offizielle VM-Images für VirtualBox und VMware von der [Kali-Website](https://www.kali.org/get-kali/#kali-virtual-machines)
|
||||
- Importieren, ggf. Netzwerkbrücke und Shared Folders aktivieren
|
||||
|
||||
## Konfiguration
|
||||
|
||||
### Netzwerkeinstellungen
|
||||
|
||||
- Konfiguration über `nmtui` oder `/etc/network/interfaces`
|
||||
- VPN und Proxy-Integration über GUI oder Terminal
|
||||
|
||||
### Updates & Paketquellen
|
||||
|
||||
```bash
|
||||
sudo apt update && sudo apt full-upgrade
|
||||
````
|
||||
|
||||
> Hinweis: `kali-rolling` ist die Standard-Distribution für kontinuierliche Updates.
|
||||
|
||||
### Sprache & Lokalisierung
|
||||
|
||||
```bash
|
||||
sudo dpkg-reconfigure locales
|
||||
sudo dpkg-reconfigure keyboard-configuration
|
||||
```
|
||||
|
||||
## Verwendungsbeispiele
|
||||
|
||||
### 1. Netzwerkscan mit Nmap
|
||||
|
||||
```bash
|
||||
nmap -sS -T4 -A 192.168.1.0/24
|
||||
```
|
||||
|
||||
### 2. Passwort-Cracking mit John the Ripper
|
||||
|
||||
```bash
|
||||
john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
|
||||
```
|
||||
|
||||
### 3. Forensik mit Autopsy
|
||||
|
||||
```bash
|
||||
autopsy &
|
||||
```
|
||||
|
||||
### 4. Android-Analyse mit MobSF (in Docker)
|
||||
|
||||
```bash
|
||||
docker pull opensecurity/mobile-security-framework-mobsf
|
||||
docker run -it -p 8000:8000 mobsf
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
* Nutze immer **aktuelle Snapshots** oder VM-Clones vor gefährlichen Tests
|
||||
* Verwende separate Netzwerke (z. B. Host-only oder NAT) für Tests
|
||||
* Deaktiviere automatisches WLAN bei forensischen Analysen
|
||||
* Prüfe und aktualisiere regelmäßig Toolsets (`apt`, `git`, `pip`)
|
||||
* Halte deine ISO-Images versioniert für forensische Reproduzierbarkeit
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Problem: Keine Internetverbindung nach Installation
|
||||
|
||||
**Lösung:** Netzwerkadapter prüfen, ggf. mit `ifconfig` oder `ip a` überprüfen, DHCP aktivieren.
|
||||
|
||||
### Problem: Tools fehlen nach Update
|
||||
|
||||
**Lösung:** Tool-Gruppen wie `kali-linux-default` manuell nachinstallieren:
|
||||
|
||||
```bash
|
||||
sudo apt install kali-linux-default
|
||||
```
|
||||
|
||||
### Problem: „Permission Denied“ bei Tools
|
||||
|
||||
**Lösung:** Root-Rechte nutzen oder mit `sudo` ausführen.
|
||||
|
||||
## Weiterführende Themen
|
||||
|
||||
* **Kustomisierung von Kali ISOs** mit `live-build`
|
||||
* **NetHunter**: Kali für mobile Geräte (Android)
|
||||
* **Kali Purple**: Defensive Security Suite
|
||||
* Integration mit **Cloud-Infrastrukturen** via WSL oder Azure
|
||||
|
||||
---
|
||||
|
||||
**Links & Ressourcen:**
|
||||
|
||||
* Offizielle Website: [https://kali.org](https://kali.org/)
|
||||
* Dokumentation: [https://docs.kali.org/](https://docs.kali.org/)
|
||||
* GitLab Repo: [https://gitlab.com/kalilinux](https://gitlab.com/kalilinux)
|
||||
* Discord-Community: [https://discord.com/invite/kali-linux](https://discord.com/invite/kali-linux)
|
||||
|
133
src/content/knowledgebase/misp.md
Normal file
133
src/content/knowledgebase/misp.md
Normal file
@ -0,0 +1,133 @@
|
||||
---
|
||||
title: "MISP - Plattform für Threat Intelligence Sharing"
|
||||
tool_name: "MISP"
|
||||
description: "Das Rückgrat des modernen Threat-Intelligence-Sharings mit über 40.000 aktiven Instanzen weltweit."
|
||||
last_updated: 2025-07-20
|
||||
author: "CC24-Team"
|
||||
difficulty: "intermediate"
|
||||
categories: ["incident-response", "law-enforcement", "malware-analysis", "network-forensics", "cloud-forensics"]
|
||||
tags: ["web-based", "threat-intelligence", "api", "correlation", "ioc-sharing", "automation"]
|
||||
sections:
|
||||
overview: true
|
||||
installation: true
|
||||
configuration: true
|
||||
usage_examples: true
|
||||
best_practices: true
|
||||
troubleshooting: true
|
||||
advanced_topics: false
|
||||
review_status: "published"
|
||||
---
|
||||
|
||||
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
|
||||
|
||||
|
||||
# Übersicht
|
||||
|
||||
**MISP (Malware Information Sharing Platform & Threat Sharing)** ist eine freie Open-Source-Plattform zur strukturierten Erfassung, Speicherung, Analyse und gemeinsamen Nutzung von Cyber-Bedrohungsdaten. Mit über 40.000 Instanzen weltweit ist MISP der De-facto-Standard für den Austausch von Indicators of Compromise (IoCs) und Threat Intelligence zwischen CERTs, SOCs, Strafverfolgungsbehörden und anderen sicherheitsrelevanten Organisationen.
|
||||
|
||||
Die föderierte Architektur ermöglicht einen kontrollierten, dezentralen Austausch von Informationen über vertrauenswürdige Partner hinweg. Durch Taxonomien, Tags und integrierte APIs ist eine automatische Anreicherung, Korrelation und Verarbeitung von Informationen in SIEMs, Firewalls oder Endpoint-Lösungen möglich.
|
||||
|
||||
## Installation
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
- **Server-Betriebssystem:** Linux (empfohlen: Debian/Ubuntu)
|
||||
- **Abhängigkeiten:** MariaDB/MySQL, PHP, Apache/Nginx, Redis
|
||||
- **Ressourcen:** Mindestens 4 GB RAM, SSD empfohlen
|
||||
|
||||
### Installationsschritte
|
||||
|
||||
```bash
|
||||
# Beispiel für Debian/Ubuntu:
|
||||
sudo apt update && sudo apt install -y curl gnupg git python3 python3-pip redis-server mariadb-server apache2 php libapache2-mod-php
|
||||
|
||||
# MISP klonen
|
||||
git clone https://github.com/MISP/MISP.git /var/www/MISP
|
||||
|
||||
# Setup-Skript nutzen
|
||||
cd /var/www/MISP && bash INSTALL/INSTALL.debian.sh
|
||||
````
|
||||
|
||||
Weitere Details: [Offizielle Installationsanleitung](https://misp.github.io/MISP/INSTALL.debian/)
|
||||
|
||||
## Konfiguration
|
||||
|
||||
### Webserver
|
||||
|
||||
* HTTPS aktivieren (Let's Encrypt oder Reverse Proxy)
|
||||
* PHP-Konfiguration anpassen (`upload_max_filesize`, `memory_limit`, `post_max_size`)
|
||||
|
||||
### Benutzerrollen
|
||||
|
||||
* Administrator, Org-Admin, Analyst etc.
|
||||
* Zugriffsbeschränkungen nach Organisation/Feed definierbar
|
||||
|
||||
### Feeds und Galaxies
|
||||
|
||||
* Aktivierung von Feeds (z. B. CIRCL, Abuse.ch, OpenCTI)
|
||||
* Nutzung von Galaxies zur Klassifizierung (APT-Gruppen, Malware-Familien)
|
||||
|
||||
## Verwendungsbeispiele
|
||||
|
||||
### Beispiel 1: Import von IoCs aus externem Feed
|
||||
|
||||
1. Feed aktivieren unter **Administration → List Feeds**
|
||||
2. Feed synchronisieren
|
||||
3. Ereignisse durchsuchen, analysieren, ggf. mit eigenen Daten korrelieren
|
||||
|
||||
### Beispiel 2: Automatisierte Anbindung an SIEM
|
||||
|
||||
* REST-API-Token erstellen
|
||||
* API-Calls zur Abfrage neuer Events (z. B. mit Python, Logstash oder MISP Workbench)
|
||||
* Integration in Security-Systeme über JSON/STIX export
|
||||
|
||||
## Best Practices
|
||||
|
||||
* Regelmäßige Backups der Datenbank
|
||||
* Taxonomien konsistent verwenden
|
||||
* Nutzung der Sighting-Funktion zur Validierung von IoCs
|
||||
* Vertrauensstufen (TLP, PAP) korrekt setzen
|
||||
* Nicht nur konsumieren – auch teilen!
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Problem: MISP-Feeds laden nicht
|
||||
|
||||
**Lösung:**
|
||||
|
||||
* Internetverbindung prüfen
|
||||
* Cronjobs aktiv?
|
||||
* Logs prüfen: `/var/www/MISP/app/tmp/logs/error.log`
|
||||
|
||||
### Problem: API gibt 403 zurück
|
||||
|
||||
**Lösung:**
|
||||
|
||||
* Ist der API-Key korrekt und aktiv?
|
||||
* Rechte des Benutzers überprüfen
|
||||
* IP-Filter im MISP-Backend beachten
|
||||
|
||||
### Problem: Hohe Datenbanklast
|
||||
|
||||
**Lösung:**
|
||||
|
||||
* Indizes optimieren
|
||||
* Redis aktivieren
|
||||
* Alte Events regelmäßig archivieren oder löschen
|
||||
|
||||
## Weiterführende Themen
|
||||
|
||||
* STIX2-Import/Export
|
||||
* Erweiterungen mit MISP Modules (z. B. für Virustotal, YARA)
|
||||
* Föderierte Netzwerke und Community-Portale
|
||||
* Integration mit OpenCTI oder TheHive
|
||||
|
||||
---
|
||||
|
||||
**Links:**
|
||||
|
||||
* 🌐 [Offizielle Projektseite](https://misp-project.org/)
|
||||
* 📦 [CC24-MISP-Instanz](https://misp.cc24.dev)
|
||||
* 📊 [Status-Monitoring](https://status.mikoshi.de/api/badge/34/status)
|
||||
|
||||
Lizenz: **AGPL-3.0**
|
124
src/content/knowledgebase/nextcloud.md
Normal file
124
src/content/knowledgebase/nextcloud.md
Normal file
@ -0,0 +1,124 @@
|
||||
---
|
||||
title: "Nextcloud - Sichere Kollaborationsplattform"
|
||||
tool_name: "Nextcloud"
|
||||
description: "Detaillierte Anleitung und Best Practices für Nextcloud in forensischen Einsatzszenarien"
|
||||
last_updated: 2025-07-20
|
||||
author: "CC24-Team"
|
||||
difficulty: "novice"
|
||||
categories: ["collaboration-general"]
|
||||
tags: ["web-based", "collaboration", "file-sharing", "api", "encryption", "document-management"]
|
||||
sections:
|
||||
overview: true
|
||||
installation: true
|
||||
configuration: true
|
||||
usage_examples: true
|
||||
best_practices: true
|
||||
troubleshooting: true
|
||||
advanced_topics: false
|
||||
review_status: "published"
|
||||
---
|
||||
|
||||
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
|
||||
|
||||
|
||||
# Übersicht
|
||||
|
||||
Nextcloud ist eine Open-Source-Cloud-Suite, die speziell für die sichere Zusammenarbeit entwickelt wurde. Sie eignet sich ideal für forensische Teams, da sie eine DSGVO-konforme Umgebung mit verschlüsselter Dateiablage, Office-Integration und Videokonferenzen bereitstellt. Zusätzlich bietet Nextcloud einen integrierten SSO-Provider, der das Identitätsmanagement für andere forensische Tools stark vereinfacht.
|
||||
|
||||
Skalierbar von kleinen Raspberry-Pi-Installationen bis hin zu hochverfügbaren Multi-Node-Setups.
|
||||
|
||||
- **Website:** [nextcloud.com](https://nextcloud.com/)
|
||||
- **Demo/Projektinstanz:** [cloud.cc24.dev](https://cloud.cc24.dev)
|
||||
- **Statusseite:** [Mikoshi Status](https://status.mikoshi.de/api/badge/11/status)
|
||||
- **Lizenz:** AGPL-3.0
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
- Linux-Server oder Raspberry Pi
|
||||
- PHP 8.1 oder höher
|
||||
- MariaDB/PostgreSQL
|
||||
- Webserver (Apache/Nginx)
|
||||
- SSL-Zertifikat (empfohlen: Let's Encrypt)
|
||||
|
||||
### Installationsschritte (Ubuntu Beispiel)
|
||||
|
||||
```bash
|
||||
sudo apt update && sudo apt upgrade
|
||||
sudo apt install apache2 mariadb-server libapache2-mod-php php php-mysql \
|
||||
php-gd php-xml php-mbstring php-curl php-zip php-intl php-bcmath unzip
|
||||
|
||||
wget https://download.nextcloud.com/server/releases/latest.zip
|
||||
unzip latest.zip -d /var/www/
|
||||
chown -R www-data:www-data /var/www/nextcloud
|
||||
````
|
||||
|
||||
Danach den Web-Installer im Browser aufrufen (`https://<your-domain>/nextcloud`) und Setup abschließen.
|
||||
|
||||
## Konfiguration
|
||||
|
||||
* **Trusted Domains** in `config.php` definieren
|
||||
* SSO mit OpenID Connect aktivieren
|
||||
* Dateiverschlüsselung aktivieren (`Settings → Security`)
|
||||
* Benutzer und Gruppen über LDAP oder SAML integrieren
|
||||
|
||||
## Verwendungsbeispiele
|
||||
|
||||
### Gemeinsame Fallbearbeitung
|
||||
|
||||
1. Ermittlungsordner als geteiltes Gruppenverzeichnis anlegen
|
||||
2. Versionierung und Kommentare zu forensischen Berichten aktivieren
|
||||
3. Vorschau für Office-Dateien, PDFs und Bilder direkt im Browser nutzen
|
||||
|
||||
### Videokonferenzen mit "Nextcloud Talk"
|
||||
|
||||
* Sichere Kommunikation zwischen Ermittlern und Sachverständigen
|
||||
* Ende-zu-Ende-verschlüsselt
|
||||
* Bildschirmfreigabe möglich
|
||||
|
||||
### Automatischer Dateiimport per API
|
||||
|
||||
* REST-Schnittstelle nutzen, um z. B. automatisch Logdateien oder Exportdaten hochzuladen
|
||||
* Ideal für Anbindung an SIEM, DLP oder Analyse-Pipelines
|
||||
|
||||
## Best Practices
|
||||
|
||||
* Zwei-Faktor-Authentifizierung aktivieren
|
||||
* Tägliche Backups der Datenbank und Datenstruktur
|
||||
* Nutzung von OnlyOffice oder Collabora für revisionssichere Dokumentenbearbeitung
|
||||
* Zugriff regelmäßig überprüfen, insbesondere bei externen Partnern
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Problem: Langsame Performance
|
||||
|
||||
**Lösung:** APCu aktivieren und Caching optimieren (`config.php → 'memcache.local'`).
|
||||
|
||||
### Problem: Dateien erscheinen nicht im Sync
|
||||
|
||||
**Lösung:** Cronjob für `files:scan` konfigurieren oder manuell ausführen:
|
||||
|
||||
```bash
|
||||
sudo -u www-data php /var/www/nextcloud/occ files:scan --all
|
||||
```
|
||||
|
||||
### Problem: Fehlermeldung "Trusted domain not set"
|
||||
|
||||
**Lösung:** In `config/config.php` Eintrag `trusted_domains` korrekt konfigurieren:
|
||||
|
||||
```php
|
||||
'trusted_domains' =>
|
||||
array (
|
||||
0 => 'yourdomain.tld',
|
||||
1 => 'cloud.cc24.dev',
|
||||
),
|
||||
```
|
||||
|
||||
## Weiterführende Themen
|
||||
|
||||
* **Integration mit Forensik-Plattformen** (über WebDAV, API oder SSO)
|
||||
* **Custom Apps entwickeln** für spezielle Ermittlungs-Workflows
|
||||
* **Auditing aktivieren**: Nutzung und Änderungen nachvollziehen mit Protokollierungsfunktionen
|
110
src/content/knowledgebase/regular-expressions-regex.md
Normal file
110
src/content/knowledgebase/regular-expressions-regex.md
Normal file
@ -0,0 +1,110 @@
|
||||
---
|
||||
title: "Regular Expressions (Regex) – Musterbasierte Textanalyse"
|
||||
tool_name: "Regular Expressions (Regex)"
|
||||
description: "Pattern matching language für Suche, Extraktion und Manipulation von Text in forensischen Analysen."
|
||||
last_updated: 2025-07-20
|
||||
author: "CC24-Team"
|
||||
difficulty: "intermediate"
|
||||
categories: ["incident-response", "malware-analysis", "network-forensics", "fraud-investigation"]
|
||||
tags: ["pattern-matching", "text-processing", "log-analysis", "string-manipulation", "search-algorithms"]
|
||||
sections:
|
||||
overview: true
|
||||
installation: false
|
||||
configuration: false
|
||||
usage_examples: true
|
||||
best_practices: true
|
||||
troubleshooting: false
|
||||
advanced_topics: true
|
||||
review_status: "published"
|
||||
---
|
||||
|
||||
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
|
||||
|
||||
|
||||
# Übersicht
|
||||
|
||||
**Regular Expressions (Regex)** sind ein leistungsfähiges Werkzeug zur Erkennung, Extraktion und Transformation von Zeichenfolgen anhand vordefinierter Muster. In der digitalen Forensik sind Regex-Ausdrücke unverzichtbar: Sie helfen beim Auffinden von IP-Adressen, Hash-Werten, Dateipfaden, Malware-Signaturen oder Kreditkartennummern in großen Mengen unstrukturierter Daten wie Logdateien, Netzwerktraces oder Memory Dumps.
|
||||
|
||||
Regex ist nicht auf eine bestimmte Plattform oder Software beschränkt – es wird in nahezu allen gängigen Programmiersprachen, Texteditoren und forensischen Tools unterstützt.
|
||||
|
||||
## Verwendungsbeispiele
|
||||
|
||||
### 1. IP-Adressen extrahieren
|
||||
|
||||
```regex
|
||||
\b(?:\d{1,3}\.){3}\d{1,3}\b
|
||||
````
|
||||
|
||||
Verwendung:
|
||||
|
||||
* Finden von IP-Adressen in Firewall-Logs oder Packet Captures.
|
||||
* Beispiel-Zeile:
|
||||
|
||||
```
|
||||
Connection from 192.168.1.101 to port 443 established
|
||||
```
|
||||
|
||||
### 2. E-Mail-Adressen identifizieren
|
||||
|
||||
```regex
|
||||
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
|
||||
```
|
||||
|
||||
Verwendung:
|
||||
|
||||
* Erkennung von kompromittierten Accounts in Phishing-E-Mails.
|
||||
* Analyse von Useraktivitäten oder Kommunikationsverläufen.
|
||||
|
||||
### 3. Hash-Werte erkennen (z. B. SHA-256)
|
||||
|
||||
```regex
|
||||
\b[A-Fa-f0-9]{64}\b
|
||||
```
|
||||
|
||||
Verwendung:
|
||||
|
||||
* Extraktion von Malware-Hashes aus Memory Dumps oder YARA-Logs.
|
||||
|
||||
### 4. Zeitstempel in Logdateien extrahieren
|
||||
|
||||
```regex
|
||||
\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}
|
||||
```
|
||||
|
||||
Verwendung:
|
||||
|
||||
* Zeitsensitive Korrelationsanalysen (z. B. bei Intrusion Detection oder Timeline-Rekonstruktionen).
|
||||
|
||||
## Best Practices
|
||||
|
||||
* **Regex testen**: Nutze Plattformen wie [regexr.com](https://regexr.com/) oder [regex101.com](https://regex101.com/) zur Validierung.
|
||||
* **Performance beachten**: Komplexe Ausdrücke können ineffizient sein und Systeme verlangsamen – verwende Lazy Quantifiers (`*?`, `+?`) bei Bedarf.
|
||||
* **Escape-Zeichen korrekt anwenden**: Spezielle Zeichen wie `.` oder `\` müssen bei Bedarf mit `\\` oder `\.` maskiert werden.
|
||||
* **Portabilität prüfen**: Unterschiedliche Regex-Engines (z. B. Python `re`, PCRE, JavaScript) interpretieren manche Syntax leicht unterschiedlich.
|
||||
* **Lesbarkeit fördern**: Verwende benannte Gruppen (`(?P<name>...)`) und Kommentare (`(?x)`), um reguläre Ausdrücke besser wartbar zu machen.
|
||||
|
||||
## Weiterführende Themen
|
||||
|
||||
### Lookaheads und Lookbehinds
|
||||
|
||||
Mit **Lookaheads** (`(?=...)`) und **Lookbehinds** (`(?<=...)`) können Bedingungen formuliert werden, ohne dass der Text Teil des Matchs wird.
|
||||
|
||||
Beispiel: Alle `.exe`-Dateinamen **ohne** das Wort `safe` davor matchen:
|
||||
|
||||
```regex
|
||||
(?<!safe\s)[\w-]+\.exe
|
||||
```
|
||||
|
||||
### Regex in Forensik-Tools
|
||||
|
||||
* **YARA**: Unterstützt Regex zur Erstellung von Malware-Signaturen.
|
||||
* **Wireshark**: Filtert Payloads anhand von Regex-ähnlicher Syntax.
|
||||
* **Splunk & ELK**: Verwenden Regex für Logparsing und Visualisierung.
|
||||
* **Volatility Plugins**: Extrahieren Artefakte mit Regex-basierten Scans.
|
||||
|
||||
---
|
||||
|
||||
> 🔤 **Regex ist ein universelles Werkzeug für Analysten, Ermittler und Entwickler, um versteckte Informationen schnell und flexibel aufzuspüren.**
|
||||
>
|
||||
> Nutze es überall dort, wo Textdaten eine Rolle spielen.
|
||||
|
161
src/content/knowledgebase/velociraptor.md
Normal file
161
src/content/knowledgebase/velociraptor.md
Normal file
@ -0,0 +1,161 @@
|
||||
---
|
||||
title: "Velociraptor – Skalierbare Endpoint-Forensik mit VQL"
|
||||
tool_name: "Velociraptor"
|
||||
description: "Detaillierte Anleitung und Best Practices für Velociraptor – Remote-Forensik der nächsten Generation"
|
||||
last_updated: 2025-07-20
|
||||
author: "CC24-Team"
|
||||
difficulty: "advanced"
|
||||
categories: ["incident-response", "malware-analysis", "network-forensics"]
|
||||
tags: ["web-based", "endpoint-monitoring", "artifact-extraction", "scripting", "live-forensics", "hunting"]
|
||||
sections:
|
||||
overview: true
|
||||
installation: true
|
||||
configuration: true
|
||||
usage_examples: true
|
||||
best_practices: true
|
||||
troubleshooting: true
|
||||
advanced_topics: true
|
||||
review_status: "published"
|
||||
---
|
||||
|
||||
> **⚠️ Hinweis**: Dies ist ein vorläufiger, KI-generierter Knowledgebase-Eintrag. Wir freuen uns über Verbesserungen und Ergänzungen durch die Community!
|
||||
|
||||
|
||||
# Übersicht
|
||||
|
||||
Velociraptor ist ein Open-Source-Tool zur Endpoint-Forensik mit Fokus auf Skalierbarkeit, Präzision und Geschwindigkeit. Es ermöglicht die zielgerichtete Erfassung und Analyse digitaler Artefakte über eine eigene Query Language – VQL (Velociraptor Query Language). Die Architektur erlaubt remote Zugriff auf tausende Endpoints gleichzeitig, ohne dass vollständige Disk-Images erforderlich sind.
|
||||
|
||||
## Hauptmerkmale
|
||||
|
||||
- 🌐 Web-basierte Benutzeroberfläche
|
||||
- 💡 VQL – mächtige, SQL-ähnliche Abfragesprache
|
||||
- 🚀 Hochskalierbare Hunt-Funktionalität
|
||||
- 🔍 Artefaktbasierte Sammlung (ohne Full-Image)
|
||||
- 🖥️ Plattformunterstützung für Windows, macOS, Linux
|
||||
- 📦 Apache 2.0 Lizenz – Open Source
|
||||
|
||||
Weitere Infos: [velociraptor.app](https://www.velociraptor.app/)
|
||||
Projektspiegel: [raptor.cc24.dev](https://raptor.cc24.dev)
|
||||
Status: 
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
- Python ≥ 3.9
|
||||
- Adminrechte auf dem System
|
||||
- Firewall-Freigaben für Webport (Standard: 8000)
|
||||
|
||||
### Installation unter Linux/macOS
|
||||
|
||||
```bash
|
||||
wget https://github.com/Velocidex/velociraptor/releases/latest/download/velociraptor
|
||||
chmod +x velociraptor
|
||||
sudo mv velociraptor /usr/local/bin/
|
||||
````
|
||||
|
||||
### Installation unter Windows
|
||||
|
||||
1. Download der `.exe` von der [Release-Seite](https://github.com/Velocidex/velociraptor/releases)
|
||||
2. Ausführung in PowerShell mit Adminrechten:
|
||||
|
||||
```powershell
|
||||
.\velociraptor.exe config generate > server.config.yaml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Konfiguration
|
||||
|
||||
### Server Setup
|
||||
|
||||
1. Generiere die Konfigurationsdatei:
|
||||
|
||||
```bash
|
||||
velociraptor config generate > server.config.yaml
|
||||
```
|
||||
2. Starte den Server:
|
||||
|
||||
```bash
|
||||
velociraptor --config server.config.yaml frontend
|
||||
```
|
||||
3. Zugriff über Browser via `https://<hostname>:8000`
|
||||
|
||||
### Client Deployment
|
||||
|
||||
* MSI/EXE für Windows, oder `deb/rpm` für Linux
|
||||
* Unterstützt automatische Registrierung am Server
|
||||
* Deployment über GPO, Puppet, Ansible etc. möglich
|
||||
|
||||
---
|
||||
|
||||
## Verwendungsbeispiele
|
||||
|
||||
### 1. Live-Memory-Artefakte sammeln
|
||||
|
||||
```vql
|
||||
SELECT * FROM Artifact.MemoryInfo()
|
||||
```
|
||||
|
||||
### 2. Hunt starten auf verdächtige Prozesse
|
||||
|
||||
```vql
|
||||
SELECT * FROM pslist()
|
||||
WHERE Name =~ "mimikatz|cobaltstrike"
|
||||
```
|
||||
|
||||
### 3. Dateiinhalt extrahieren
|
||||
|
||||
```vql
|
||||
SELECT * FROM glob(globs="C:\\Users\\*\\AppData\\*.dat")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
* Erstelle eigene Artefakte für unternehmensspezifische Bedrohungsmodelle
|
||||
* Verwende "Notebook"-Funktion für strukturierte Analysen
|
||||
* Nutze "Labels", um Endpoints zu organisieren (z. B. `location:Berlin`)
|
||||
* Kombiniere Velociraptor mit SIEM/EDR-Systemen über REST API
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Problem: Keine Verbindung vom Client zum Server
|
||||
|
||||
**Lösung:**
|
||||
|
||||
* Ports freigegeben? (Default: 8000/tcp)
|
||||
* TLS-Zertifikate korrekt generiert?
|
||||
* `server.config.yaml` auf korrekte `public_ip` prüfen
|
||||
|
||||
### Problem: Hunt hängt in Warteschleife
|
||||
|
||||
**Lösung:**
|
||||
|
||||
* Genügend Worker-Prozesse aktiv?
|
||||
* Endpoint online?
|
||||
* `log_level` auf `debug` setzen und Log analysieren
|
||||
|
||||
---
|
||||
|
||||
## Weiterführende Themen
|
||||
|
||||
* Eigene Artefakte schreiben mit VQL
|
||||
* Integration mit ELK Stack
|
||||
* Automatisiertes Incident Response Playbook
|
||||
* Velociraptor als IR-as-a-Service einsetzen
|
||||
|
||||
---
|
||||
|
||||
🧠 **Tipp:** Die Lernkurve bei VQL ist steil – aber mit hohem ROI. Testumgebung aufsetzen und mit Community-Artefakten starten.
|
||||
|
||||
📚 Weitere Ressourcen:
|
||||
|
||||
* [Offizielle Doku](https://docs.velociraptor.app/)
|
||||
* [YouTube Channel](https://www.youtube.com/c/VelociraptorDFIR)
|
||||
* [Community auf Discord](https://www.velociraptor.app/community/)
|
@ -1,6 +1,5 @@
|
||||
tools:
|
||||
- name: Autopsy
|
||||
icon: 📦
|
||||
type: software
|
||||
description: >-
|
||||
Die führende Open-Source-Alternative zu kommerziellen Forensik-Suiten mit
|
||||
@ -9,6 +8,16 @@ tools:
|
||||
Plugin-Architektur erlaubt Erweiterungen für spezielle
|
||||
Untersuchungsszenarien. Zwar komplexer als kommerzielle Lösungen, aber
|
||||
dafür vollständig transparent und kostenfrei.
|
||||
skillLevel: intermediate
|
||||
url: https://www.autopsy.com/
|
||||
tags:
|
||||
- gui
|
||||
- filesystem
|
||||
- timeline-analysis
|
||||
- carving
|
||||
- artifact-extraction
|
||||
- keyword-search
|
||||
icon: 📦
|
||||
domains:
|
||||
- incident-response
|
||||
- law-enforcement
|
||||
@ -18,26 +27,15 @@ tools:
|
||||
phases:
|
||||
- examination
|
||||
- analysis
|
||||
related_concepts:
|
||||
- SQL Query Fundamentals
|
||||
- Hash Functions & Digital Signatures
|
||||
platforms:
|
||||
- Windows
|
||||
- Linux
|
||||
related_concepts:
|
||||
- "SQL Query Fundamentals"
|
||||
- "Hash Functions & Digital Signatures"
|
||||
domain-agnostic-software: null
|
||||
skillLevel: intermediate
|
||||
accessType: download
|
||||
url: https://www.autopsy.com/
|
||||
projectUrl: ''
|
||||
accessType: Download
|
||||
license: Apache 2.0
|
||||
knowledgebase: false
|
||||
tags:
|
||||
- gui
|
||||
- filesystem
|
||||
- timeline-analysis
|
||||
- carving
|
||||
- artifact-extraction
|
||||
- keyword-search
|
||||
- name: Volatility 3
|
||||
icon: 📦
|
||||
type: software
|
||||
@ -62,8 +60,8 @@ tools:
|
||||
- Linux
|
||||
- macOS
|
||||
related_concepts:
|
||||
- "Hash Functions & Digital Signatures"
|
||||
- "Regular Expressions (Regex)"
|
||||
- Hash Functions & Digital Signatures
|
||||
- Regular Expressions (Regex)
|
||||
domain-agnostic-software: null
|
||||
skillLevel: advanced
|
||||
accessType: download
|
||||
@ -170,8 +168,8 @@ tools:
|
||||
platforms:
|
||||
- Web
|
||||
related_concepts:
|
||||
- "Regular Expressions (Regex)"
|
||||
- "SQL Query Fundamentals"
|
||||
- Regular Expressions (Regex)
|
||||
- SQL Query Fundamentals
|
||||
domain-agnostic-software: null
|
||||
skillLevel: intermediate
|
||||
accessType: server-based
|
||||
@ -609,7 +607,7 @@ tools:
|
||||
- Linux
|
||||
- macOS
|
||||
related_concepts:
|
||||
- "Regular Expressions (Regex)"
|
||||
- Regular Expressions (Regex)
|
||||
domain-agnostic-software: null
|
||||
skillLevel: novice
|
||||
accessType: download
|
||||
@ -682,7 +680,7 @@ tools:
|
||||
- macOS
|
||||
- Web
|
||||
related_concepts:
|
||||
- "SQL Query Fundamentals"
|
||||
- SQL Query Fundamentals
|
||||
domain-agnostic-software: null
|
||||
skillLevel: intermediate
|
||||
accessType: server-based
|
||||
@ -973,7 +971,7 @@ tools:
|
||||
platforms:
|
||||
- Windows
|
||||
related_concepts:
|
||||
- "Hash Functions & Digital Signatures"
|
||||
- Hash Functions & Digital Signatures
|
||||
domain-agnostic-software: null
|
||||
skillLevel: beginner
|
||||
accessType: download
|
||||
@ -1005,7 +1003,7 @@ tools:
|
||||
platforms:
|
||||
- Linux
|
||||
related_concepts:
|
||||
- "Hash Functions & Digital Signatures"
|
||||
- Hash Functions & Digital Signatures
|
||||
domain-agnostic-software: null
|
||||
skillLevel: novice
|
||||
accessType: download
|
||||
@ -1072,7 +1070,7 @@ tools:
|
||||
- Linux
|
||||
- macOS
|
||||
related_concepts:
|
||||
- "SQL Query Fundamentals"
|
||||
- SQL Query Fundamentals
|
||||
domain-agnostic-software: null
|
||||
skillLevel: intermediate
|
||||
accessType: download
|
||||
@ -1240,7 +1238,7 @@ tools:
|
||||
platforms:
|
||||
- Linux
|
||||
related_concepts:
|
||||
- "Hash Functions & Digital Signatures"
|
||||
- Hash Functions & Digital Signatures
|
||||
domain-agnostic-software: null
|
||||
skillLevel: intermediate
|
||||
accessType: download
|
||||
@ -1480,8 +1478,8 @@ tools:
|
||||
- Linux
|
||||
- macOS
|
||||
related_concepts:
|
||||
- "Regular Expressions (Regex)"
|
||||
- "Hash Functions & Digital Signatures"
|
||||
- Regular Expressions (Regex)
|
||||
- Hash Functions & Digital Signatures
|
||||
accessType: download
|
||||
license: BSD-3-Clause
|
||||
knowledgebase: false
|
||||
@ -1504,7 +1502,7 @@ tools:
|
||||
- Linux
|
||||
- macOS
|
||||
related_concepts:
|
||||
- "Regular Expressions (Regex)"
|
||||
- Regular Expressions (Regex)
|
||||
domain-agnostic-software: null
|
||||
skillLevel: novice
|
||||
accessType: built-in
|
||||
@ -1977,9 +1975,10 @@ tools:
|
||||
icon: 🔤
|
||||
type: concept
|
||||
description: >-
|
||||
Pattern matching language for searching, extracting, and manipulating text.
|
||||
Essential for log analysis, malware signature creation, and data extraction from
|
||||
unstructured sources. Forms the backbone of many forensic tools and custom scripts.
|
||||
Pattern matching language for searching, extracting, and manipulating
|
||||
text. Essential for log analysis, malware signature creation, and data
|
||||
extraction from unstructured sources. Forms the backbone of many forensic
|
||||
tools and custom scripts.
|
||||
domains:
|
||||
- incident-response
|
||||
- malware-analysis
|
||||
@ -1996,21 +1995,21 @@ tools:
|
||||
url: https://regexr.com/
|
||||
projectUrl: null
|
||||
license: null
|
||||
knowledgebase: false
|
||||
knowledgebase: true
|
||||
tags:
|
||||
- pattern-matching
|
||||
- text-processing
|
||||
- log-analysis
|
||||
- string-manipulation
|
||||
- search-algorithms
|
||||
|
||||
- name: SQL Query Fundamentals
|
||||
icon: 🗃️
|
||||
type: concept
|
||||
description: >-
|
||||
Structured Query Language for database interrogation and analysis. Critical for
|
||||
examining application databases, SQLite artifacts from mobile devices, and
|
||||
browser history databases. Enables complex correlation and filtering of large datasets.
|
||||
Structured Query Language for database interrogation and analysis.
|
||||
Critical for examining application databases, SQLite artifacts from
|
||||
mobile devices, and browser history databases. Enables complex
|
||||
correlation and filtering of large datasets.
|
||||
domains:
|
||||
- incident-response
|
||||
- mobile-forensics
|
||||
@ -2034,14 +2033,14 @@ tools:
|
||||
- data-correlation
|
||||
- mobile-artifacts
|
||||
- browser-forensics
|
||||
|
||||
- name: Hash Functions & Digital Signatures
|
||||
icon: 🔐
|
||||
type: concept
|
||||
description: >-
|
||||
Cryptographic principles for data integrity verification and authentication.
|
||||
Fundamental for evidence preservation, malware identification, and establishing
|
||||
chain of custody. Understanding of MD5, SHA, and digital signature validation.
|
||||
Cryptographic principles for data integrity verification and
|
||||
authentication. Fundamental for evidence preservation, malware
|
||||
identification, and establishing chain of custody. Understanding of MD5,
|
||||
SHA, and digital signature validation.
|
||||
domains:
|
||||
- incident-response
|
||||
- law-enforcement
|
||||
|
12
src/env.d.ts
vendored
12
src/env.d.ts
vendored
@ -9,10 +9,16 @@ declare global {
|
||||
getStoredTheme: () => string;
|
||||
};
|
||||
toolsData: any[];
|
||||
showToolDetails: (toolName: string) => void;
|
||||
hideToolDetails: () => void;
|
||||
showToolDetails: (toolName: string, modalType?: string) => void;
|
||||
hideToolDetails: (modalType?: string) => void;
|
||||
hideAllToolDetails: () => void;
|
||||
toggleKbEntry: (entryId: string) => void;
|
||||
toggleDomainAgnosticSection: (sectionId: string) => void;
|
||||
restoreAIResults?: () => void;
|
||||
switchToAIView?: () => void;
|
||||
clearTagFilters?: () => void;
|
||||
clearAllFilters?: () => void;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Also declare the modules that might not be recognized
|
||||
|
@ -94,6 +94,17 @@ function createWorkflowSystemPrompt(toolsData: any): string {
|
||||
skillLevel: tool.skillLevel,
|
||||
license: tool.license,
|
||||
tags: tool.tags,
|
||||
related_concepts: tool.related_concepts || []
|
||||
}));
|
||||
|
||||
// NEW: Include concepts for background knowledge
|
||||
const conceptsList = toolsData.concepts.map((concept: any) => ({
|
||||
name: concept.name,
|
||||
description: concept.description,
|
||||
domains: concept.domains,
|
||||
phases: concept.phases,
|
||||
skillLevel: concept.skillLevel,
|
||||
tags: concept.tags
|
||||
}));
|
||||
|
||||
// Get regular phases (no more filtering needed)
|
||||
@ -135,9 +146,12 @@ function createWorkflowSystemPrompt(toolsData: any): string {
|
||||
|
||||
return `Du bist ein DFIR (Digital Forensics and Incident Response) Experte, der Ermittlern bei der Auswahl von Software und Methoden hilft.
|
||||
|
||||
VERFÜGBARE DATENBASIS:
|
||||
VERFÜGBARE TOOLS/METHODEN:
|
||||
${JSON.stringify(toolsList, null, 2)}
|
||||
|
||||
VERFÜGBARE HINTERGRUNDWISSEN-KONZEPTE:
|
||||
${JSON.stringify(conceptsList, null, 2)}
|
||||
|
||||
UNTERSUCHUNGSPHASEN (NIST Framework):
|
||||
${phasesDescription}
|
||||
|
||||
@ -152,6 +166,8 @@ WICHTIGE REGELN:
|
||||
5. Deutsche Antworten für deutsche Anfragen, English for English queries
|
||||
6. Bewerbe NIEMALS Proprietäre Software fälschlicherweise als Open-Source-Software, erkenne aber an, falls diese besser geeignet sein könnte.
|
||||
7. Bevorzuge alles, was nicht proprietär ist (license != "Proprietary"), aber erkenne an, wenn proprietäre Software besser geeignet ist.
|
||||
8. WICHTIG: Erwähne relevante Hintergrundwissen-Konzepte wenn Tools verwendet werden, die related_concepts haben
|
||||
9. Konzepte sind NICHT Tools - empfehle sie nicht als actionable Schritte, sondern als Wissensbasis
|
||||
|
||||
SOFTWARE/METHODEN-AUSWAHL NACH PHASE:
|
||||
${phaseDescriptions}
|
||||
@ -164,13 +180,19 @@ ANTWORT-FORMAT (strict JSON):
|
||||
"scenario_analysis": "Detaillierte Analyse des Szenarios auf Deutsch/English",
|
||||
"recommended_tools": [
|
||||
{
|
||||
"name": "EXAKTER Name aus der Database",
|
||||
"name": "EXAKTER Name aus der Tools-Database",
|
||||
"priority": "high|medium|low",
|
||||
"phase": "${validPhases}",
|
||||
"justification": "Warum diese Methode für diese Phase und Szenario geeignet ist"
|
||||
}
|
||||
],
|
||||
"workflow_suggestion": "Vorgeschlagener Untersuchungsablauf",
|
||||
"background_knowledge": [
|
||||
{
|
||||
"concept_name": "EXAKTER Name aus der Konzepte-Database",
|
||||
"relevance": "Warum dieses Konzept für das Szenario relevant ist, und bei welchen der empfohlenen Methoden/Tools."
|
||||
}
|
||||
],
|
||||
"additional_notes": "Wichtige Überlegungen und Hinweise"
|
||||
}
|
||||
|
||||
@ -189,14 +211,28 @@ function createToolSystemPrompt(toolsData: any): string {
|
||||
license: tool.license,
|
||||
tags: tool.tags,
|
||||
url: tool.url,
|
||||
projectUrl: tool.projectUrl
|
||||
projectUrl: tool.projectUrl,
|
||||
related_concepts: tool.related_concepts || []
|
||||
}));
|
||||
|
||||
// NEW: Include concepts for background knowledge
|
||||
const conceptsList = toolsData.concepts.map((concept: any) => ({
|
||||
name: concept.name,
|
||||
description: concept.description,
|
||||
domains: concept.domains,
|
||||
phases: concept.phases,
|
||||
skillLevel: concept.skillLevel,
|
||||
tags: concept.tags
|
||||
}));
|
||||
|
||||
return `Du bist ein DFIR (Digital Forensics and Incident Response) Experte, der bei der Auswahl spezifischer Software/Methoden für konkrete Probleme hilft.
|
||||
|
||||
VERFÜGBARE DATENBASIS:
|
||||
VERFÜGBARE TOOLS/METHODEN:
|
||||
${JSON.stringify(toolsList, null, 2)}
|
||||
|
||||
VERFÜGBARE HINTERGRUNDWISSEN-KONZEPTE:
|
||||
${JSON.stringify(conceptsList, null, 2)}
|
||||
|
||||
WICHTIGE REGELN:
|
||||
1. Analysiere das spezifische Problem/die Anforderung sorgfältig
|
||||
2. Empfehle 1-3 Tools, sortiert nach Eignung (beste Empfehlung zuerst)
|
||||
@ -207,13 +243,15 @@ WICHTIGE REGELN:
|
||||
7. Erwähne sowohl Stärken als auch Schwächen/Limitationen
|
||||
8. Schlage alternative Ansätze vor, wenn sinnvoll
|
||||
9. Gib grundsätzliche Hinweise, WIE das Tool konkret eingesetzt wird
|
||||
10. WICHTIG: Erwähne relevante Hintergrundwissen-Konzepte wenn Tools verwendet werden, die related_concepts haben
|
||||
11. Konzepte sind NICHT Tools - empfehle sie nicht als actionable Schritte, sondern als Wissensbasis
|
||||
|
||||
ANTWORT-FORMAT (strict JSON):
|
||||
{
|
||||
"problem_analysis": "Detaillierte Analyse des Problems/der Anforderung",
|
||||
"recommended_tools": [
|
||||
{
|
||||
"name": "EXAKTER Name aus der Database",
|
||||
"name": "EXAKTER Name aus der Tools-Database",
|
||||
"rank": 1,
|
||||
"suitability_score": "high|medium|low",
|
||||
"detailed_explanation": "Detaillierte Erklärung, warum dieses Tool/diese Methode das Problem löst",
|
||||
@ -223,6 +261,12 @@ ANTWORT-FORMAT (strict JSON):
|
||||
"alternatives": "Alternative Ansätze oder ergänzende Tools/Methoden, falls relevant"
|
||||
}
|
||||
],
|
||||
"background_knowledge": [
|
||||
{
|
||||
"concept_name": "EXAKTER Name aus der Konzepte-Database",
|
||||
"relevance": "Warum dieses Konzept für die empfohlenen Tools/das Problem relevant ist, und für welche der empfohlenen Methoden/Tools."
|
||||
}
|
||||
],
|
||||
"additional_considerations": "Wichtige Überlegungen, Voraussetzungen oder Warnungen"
|
||||
}
|
||||
|
||||
@ -353,12 +397,13 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Validate tool names against database based on mode
|
||||
// Validate tool names and concept names against database
|
||||
const validToolNames = new Set(toolsData.tools.map((t: any) => t.name));
|
||||
const validConceptNames = new Set(toolsData.concepts.map((c: any) => c.name));
|
||||
|
||||
let validatedRecommendation;
|
||||
|
||||
if (mode === 'workflow') {
|
||||
// Existing validation for workflow mode
|
||||
validatedRecommendation = {
|
||||
...recommendation,
|
||||
recommended_tools: recommendation.recommended_tools?.filter((tool: any) => {
|
||||
@ -367,10 +412,16 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}) || [],
|
||||
background_knowledge: recommendation.background_knowledge?.filter((concept: any) => {
|
||||
if (!validConceptNames.has(concept.concept_name)) {
|
||||
console.warn(`AI referenced unknown concept: ${concept.concept_name}`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}) || []
|
||||
};
|
||||
} else {
|
||||
// New validation for tool mode
|
||||
validatedRecommendation = {
|
||||
...recommendation,
|
||||
recommended_tools: recommendation.recommended_tools?.filter((tool: any) => {
|
||||
@ -385,12 +436,19 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
suitability_score: tool.suitability_score || 'medium', // Default suitability
|
||||
pros: Array.isArray(tool.pros) ? tool.pros : [],
|
||||
cons: Array.isArray(tool.cons) ? tool.cons : []
|
||||
})) || []
|
||||
})) || [],
|
||||
background_knowledge: recommendation.background_knowledge?.filter((concept: any) => {
|
||||
if (!validConceptNames.has(concept.concept_name)) {
|
||||
console.warn(`AI referenced unknown concept: ${concept.concept_name}`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}) || []
|
||||
};
|
||||
}
|
||||
|
||||
// Log successful query
|
||||
console.log(`[AI Query] Mode: ${mode}, User: ${userId}, Query length: ${sanitizedQuery.length}, Tools: ${validatedRecommendation.recommended_tools.length}`);
|
||||
console.log(`[AI Query] Mode: ${mode}, User: ${userId}, Query length: ${sanitizedQuery.length}, Tools: ${validatedRecommendation.recommended_tools.length}, Concepts: ${validatedRecommendation.background_knowledge?.length || 0}`);
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
|
@ -2,11 +2,10 @@
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import { getToolsData } from '../utils/dataService.js';
|
||||
|
||||
|
||||
// Load tools data
|
||||
const data = await getToolsData();
|
||||
|
||||
// Filter tools that have knowledgebase entries
|
||||
// Filter tools that have knowledgebase flag set to true
|
||||
const knowledgebaseTools = data.tools.filter((tool: any) => tool.knowledgebase === true);
|
||||
|
||||
// Sort alphabetically by name
|
||||
@ -26,7 +25,7 @@ knowledgebaseTools.sort((a: any, b: any) => a.name.localeCompare(b.name));
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Search and Filter -->
|
||||
<!-- Search -->
|
||||
<div style="margin-bottom: 2rem;">
|
||||
<input
|
||||
type="text"
|
||||
@ -56,219 +55,167 @@ knowledgebaseTools.sort((a: any, b: any) => a.name.localeCompare(b.name));
|
||||
</svg>
|
||||
<h3 style="color: var(--color-text-secondary); margin-bottom: 0.5rem;">Noch keine Knowledgebase-Einträge</h3>
|
||||
<p class="text-muted">
|
||||
Knowledgebase-Einträge werden automatisch angezeigt, sobald Datenbankeinträge das Attribut "knowledgebase: true" haben. Wenn hier noch nichts drinsteht, habe ich noch nichts dazu geschrieben.
|
||||
Knowledgebase-Einträge werden automatisch angezeigt, sobald Datenbankeinträge das Attribut "knowledgebase: true" haben.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div id="kb-entries">
|
||||
{knowledgebaseTools.map((tool: any, index: number) => (
|
||||
<article class="kb-entry card kb-entry-collapsed" id={`kb-${tool.name.toLowerCase().replace(/\s+/g, '-')}`} data-tool-name={tool.name.toLowerCase()}>
|
||||
<!-- Collapsed Header (default state) -->
|
||||
<div class="kb-entry-header" onclick={`toggleKbEntry('${tool.name.toLowerCase().replace(/\s+/g, '-')}')`} style="cursor: pointer;">
|
||||
{knowledgebaseTools.map((tool: any, index: number) => {
|
||||
const hasValidProjectUrl = tool.projectUrl !== undefined &&
|
||||
tool.projectUrl !== null &&
|
||||
tool.projectUrl !== "" &&
|
||||
tool.projectUrl.trim() !== "";
|
||||
|
||||
const toolSlug = tool.name.toLowerCase()
|
||||
.replace(/[^a-z0-9\s-]/g, '') // Remove special characters
|
||||
.replace(/\s+/g, '-') // Replace spaces with hyphens
|
||||
.replace(/-+/g, '-') // Remove duplicate hyphens
|
||||
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
|
||||
|
||||
return (
|
||||
<article
|
||||
class="kb-entry card"
|
||||
id={`kb-${toolSlug}`}
|
||||
data-tool-name={tool.name.toLowerCase()}
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="display: flex; align-items: center; gap: 1rem;">
|
||||
<h3 style="margin: 0; color: var(--color-primary);">{tool.name}</h3>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
{(() => {
|
||||
const hasValidProjectUrl = tool.projectUrl !== undefined &&
|
||||
tool.projectUrl !== null &&
|
||||
tool.projectUrl !== "" &&
|
||||
tool.projectUrl.trim() !== "";
|
||||
return (
|
||||
<>
|
||||
<h3 style="margin: 0; color: var(--color-primary);">
|
||||
{tool.icon && <span style="margin-right: 0.5rem;">{tool.icon}</span>}
|
||||
{tool.name}
|
||||
</h3>
|
||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||||
<!-- Type indicator badges -->
|
||||
{tool.type === 'concept' && <span class="badge" style="background-color: var(--color-concept); color: white;">Konzept</span>}
|
||||
{tool.type === 'method' && <span class="badge" style="background-color: var(--color-method); color: white;">Methode</span>}
|
||||
{tool.type === 'software' && <span class="badge" style="background-color: var(--color-primary); color: white;">Software</span>}
|
||||
|
||||
{hasValidProjectUrl && <span class="badge badge-primary">CC24-Server</span>}
|
||||
{tool.license !== 'Proprietary' && <span class="badge badge-success">Open Source</span>}
|
||||
<span class="badge badge-error">Infos 📖</span>
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
<div class="kb-expand-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted" style="font-size: 0.875rem; margin: 0.5rem 0 0 0;">
|
||||
{tool.description}
|
||||
</p>
|
||||
</div>
|
||||
{tool.license !== 'Proprietary' && tool.type !== 'concept' && tool.type !== 'method' && <span class="badge badge-success">Open Source</span>}
|
||||
|
||||
<!-- Expanded Content (hidden by default) -->
|
||||
<div class="kb-entry-content" style="display: none;">
|
||||
<!-- Quick Info -->
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin: 1.5rem 0; padding: 1rem; background-color: var(--color-bg-secondary); border-radius: 0.5rem;">
|
||||
<div>
|
||||
<strong style="font-size: 0.75rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em;">Plattformen</strong>
|
||||
<p style="margin: 0.25rem 0 0 0; font-size: 0.875rem;">{tool.platforms.join(', ')}</p>
|
||||
</div>
|
||||
<div>
|
||||
<strong style="font-size: 0.75rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em;">Skill Level</strong>
|
||||
<p style="margin: 0.25rem 0 0 0; font-size: 0.875rem;">{tool.skillLevel}</p>
|
||||
</div>
|
||||
<div>
|
||||
<strong style="font-size: 0.75rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em;">Lizenz</strong>
|
||||
<p style="margin: 0.25rem 0 0 0; font-size: 0.875rem;">{tool.license}</p>
|
||||
</div>
|
||||
<div>
|
||||
<strong style="font-size: 0.75rem; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em;">Phasen</strong>
|
||||
<p style="margin: 0.25rem 0 0 0; font-size: 0.875rem;">{tool.phases.join(', ')}</p>
|
||||
<!-- Difficulty indicator -->
|
||||
<span class="badge" style="background-color: var(--color-text-secondary); color: white; font-size: 0.75rem;">
|
||||
{tool.skillLevel || 'intermediate'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Knowledge Content Area -->
|
||||
<div class="kb-content">
|
||||
<h4 style="margin-bottom: 1rem; color: var(--color-text); font-size: 1.125rem;">Praktische Erkenntnisse</h4>
|
||||
|
||||
{tool.knowledgebaseContent ? (
|
||||
<div style="line-height: 1.7;">
|
||||
<p>{tool.knowledgebaseContent}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div style="padding: 2rem; text-align: center; background-color: var(--color-bg-secondary); border-radius: 0.5rem; border: 2px dashed var(--color-border);">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="var(--color-text-secondary)" stroke-width="1.5" style="margin-bottom: 0.75rem;">
|
||||
<path d="M14.828 14.828a4 4 0 0 1-5.656 0"/>
|
||||
<path d="M9 9a3 3 0 1 1 6 0c0 .749-.269 1.433-.73 1.96L11 14v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1l-3.27-3.04A3 3 0 0 1 5 9a3 3 0 0 1 6 0"/>
|
||||
<path d="M12 17h.01"/>
|
||||
</svg>
|
||||
<p class="text-muted" style="margin: 0; font-style: italic;">
|
||||
Inhalt wird manuell hinzugefügt
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<!-- Action Links -->
|
||||
<div style="display: flex; gap: 1rem; margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--color-border);">
|
||||
{(() => {
|
||||
const hasValidProjectUrl = tool.projectUrl !== undefined &&
|
||||
tool.projectUrl !== null &&
|
||||
tool.projectUrl !== "" &&
|
||||
tool.projectUrl.trim() !== "";
|
||||
return (
|
||||
<>
|
||||
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<!-- Action button -->
|
||||
<a href={`/knowledgebase/${toolSlug}`} class="btn btn-primary" style="font-size: 0.8125rem;">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
|
||||
<polyline points="15 3 21 3 21 9"/>
|
||||
<line x1="10" y1="14" x2="21" y2="3"/>
|
||||
</svg>
|
||||
Software-Homepage
|
||||
Artikel öffnen
|
||||
</a>
|
||||
{hasValidProjectUrl && (
|
||||
<a href={tool.projectUrl} target="_blank" rel="noopener noreferrer" class="btn btn-primary">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<path d="M12 16l4-4-4-4"/>
|
||||
<path d="M8 12h8"/>
|
||||
</svg>
|
||||
Zugreifen
|
||||
</a>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<p style="margin: 1rem 0; color: var(--color-text-secondary); line-height: 1.5;">
|
||||
{tool.description}
|
||||
</p>
|
||||
|
||||
<!-- Tags and Metadata -->
|
||||
<div style="display: flex; gap: 1rem; flex-wrap: wrap; align-items: center; margin-top: 1rem;">
|
||||
{tool.tags && tool.tags.length > 0 && (
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem;">
|
||||
{tool.tags.map((tag: string) => (
|
||||
<span class="tag" style="font-size: 0.75rem;">{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tool.phases && tool.phases.length > 0 && (
|
||||
<div style="font-size: 0.8125rem; color: var(--color-text-secondary);">
|
||||
<strong>Phasen:</strong> {tool.phases.join(', ')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tool.platforms && tool.platforms.length > 0 && tool.type !== 'concept' && tool.type !== 'method' && (
|
||||
<div style="font-size: 0.8125rem; color: var(--color-text-secondary);">
|
||||
<strong>Plattformen:</strong> {tool.platforms.join(', ')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<!-- No Results Message -->
|
||||
<div id="no-kb-results" style="display: none; text-align: center; padding: 4rem 0;">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="var(--color-text-secondary)" stroke-width="1.5" style="margin-bottom: 1rem;">
|
||||
<circle cx="11" cy="11" r="8"/>
|
||||
<path d="M21 21l-4.35-4.35"/>
|
||||
</svg>
|
||||
<!-- No Results -->
|
||||
<div id="no-kb-results" class="card" style="text-align: center; padding: 3rem; display: none;">
|
||||
<h3 style="color: var(--color-text-secondary); margin-bottom: 0.5rem;">Keine Ergebnisse gefunden</h3>
|
||||
<p class="text-muted">Versuchen Sie es mit anderen Suchbegriffen.</p>
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
/* Simplified knowledgebase styles */
|
||||
.kb-entry {
|
||||
margin-bottom: 1.5rem;
|
||||
border-left: 4px solid var(--color-accent);
|
||||
transition: var(--transition-fast);
|
||||
}
|
||||
|
||||
.kb-entry:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dark .kb-entry:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Toggle knowledgebase entry expansion
|
||||
function toggleKbEntry(entryId: string) {
|
||||
const entry = document.getElementById(`kb-${entryId}`);
|
||||
if (!entry) return;
|
||||
|
||||
const content = entry.querySelector('.kb-entry-content') as HTMLElement;
|
||||
const icon = entry.querySelector('.kb-expand-icon svg') as HTMLElement;
|
||||
|
||||
if (!content || !icon) return;
|
||||
|
||||
const isExpanded = entry.classList.contains('kb-entry-expanded');
|
||||
|
||||
if (isExpanded) {
|
||||
// Collapse
|
||||
entry.classList.remove('kb-entry-expanded');
|
||||
entry.classList.add('kb-entry-collapsed');
|
||||
content.style.display = 'none';
|
||||
icon.style.transform = 'rotate(0deg)';
|
||||
} else {
|
||||
// Expand
|
||||
entry.classList.remove('kb-entry-collapsed');
|
||||
entry.classList.add('kb-entry-expanded');
|
||||
content.style.display = 'block';
|
||||
icon.style.transform = 'rotate(180deg)';
|
||||
}
|
||||
}
|
||||
|
||||
// Make toggle function globally available
|
||||
(window as any).toggleKbEntry = toggleKbEntry;
|
||||
|
||||
// Search functionality
|
||||
// Enhanced knowledgebase functionality with search
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const searchInput = document.getElementById('kb-search') as HTMLInputElement;
|
||||
const entries = document.querySelectorAll('.kb-entry');
|
||||
const visibleCount = document.getElementById('visible-count');
|
||||
const noResults = document.getElementById('no-kb-results');
|
||||
const entriesContainer = document.getElementById('kb-entries');
|
||||
const searchInput = document.getElementById('kb-search') as HTMLInputElement | null;
|
||||
const entries = document.querySelectorAll('.kb-entry') as NodeListOf<HTMLElement>;
|
||||
const visibleCount = document.getElementById('visible-count') as HTMLElement | null;
|
||||
const noResults = document.getElementById('no-kb-results') as HTMLElement | null;
|
||||
|
||||
if (!searchInput || !entries.length) return;
|
||||
|
||||
// Check if page loaded with hash for specific entry
|
||||
if (window.location.hash && window.location.hash.startsWith('#kb-')) {
|
||||
const targetId = window.location.hash.replace('#kb-', '');
|
||||
setTimeout(() => toggleKbEntry(targetId), 100);
|
||||
function updateVisibleCount(count: number) {
|
||||
if (visibleCount) {
|
||||
visibleCount.textContent = count.toString();
|
||||
}
|
||||
}
|
||||
|
||||
searchInput.addEventListener('input', () => {
|
||||
const searchTerm = searchInput.value.toLowerCase().trim();
|
||||
function filterEntries(searchTerm: string) {
|
||||
let visibleEntries = 0;
|
||||
|
||||
entries.forEach(entry => {
|
||||
entries.forEach((entry) => {
|
||||
const toolName = entry.getAttribute('data-tool-name') || '';
|
||||
const entryText = entry.textContent?.toLowerCase() || '';
|
||||
const matches = entryText.includes(searchTerm.toLowerCase()) ||
|
||||
toolName.includes(searchTerm.toLowerCase());
|
||||
|
||||
if (searchTerm === '' ||
|
||||
toolName.includes(searchTerm) ||
|
||||
entryText.includes(searchTerm)) {
|
||||
(entry as HTMLElement).style.display = 'block';
|
||||
if (matches) {
|
||||
entry.style.display = 'block';
|
||||
visibleEntries++;
|
||||
} else {
|
||||
(entry as HTMLElement).style.display = 'none';
|
||||
entry.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Update count
|
||||
if (visibleCount) {
|
||||
visibleCount.textContent = visibleEntries.toString();
|
||||
}
|
||||
updateVisibleCount(visibleEntries);
|
||||
|
||||
// Show/hide no results message
|
||||
if (noResults && entriesContainer) {
|
||||
if (visibleEntries === 0 && searchTerm !== '') {
|
||||
(noResults as HTMLElement).style.display = 'block';
|
||||
(entriesContainer as HTMLElement).style.display = 'none';
|
||||
} else {
|
||||
(noResults as HTMLElement).style.display = 'none';
|
||||
(entriesContainer as HTMLElement).style.display = 'block';
|
||||
if (noResults) {
|
||||
noResults.style.display = visibleEntries === 0 && searchTerm.length > 0 ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Search functionality
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
filterEntries(target.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
169
src/pages/knowledgebase/[slug].astro
Normal file
169
src/pages/knowledgebase/[slug].astro
Normal file
@ -0,0 +1,169 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { getToolsData } from '../../utils/dataService.js';
|
||||
|
||||
// Prerender these pages at build time
|
||||
export const prerender = true;
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const knowledgebaseEntries = await getCollection('knowledgebase');
|
||||
|
||||
console.log('Building static paths for:', knowledgebaseEntries.map(e => e.slug));
|
||||
|
||||
return knowledgebaseEntries.map((entry) => {
|
||||
return {
|
||||
params: { slug: entry.slug },
|
||||
props: { entry },
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const { entry }: { entry: any } = Astro.props;
|
||||
|
||||
// Render the content
|
||||
const { Content } = await entry.render();
|
||||
|
||||
// Load tools data to get the tool details
|
||||
const data = await getToolsData();
|
||||
const tool = data.tools.find((t: any) => t.name === entry.data.tool_name);
|
||||
|
||||
if (!tool) {
|
||||
console.warn(`Tool not found for knowledgebase entry: ${entry.data.tool_name}`);
|
||||
return Astro.redirect('/knowledgebase');
|
||||
}
|
||||
|
||||
// Determine tool type for styling
|
||||
const isMethod = tool.type === 'method';
|
||||
const isConcept = tool.type === 'concept';
|
||||
const hasValidProjectUrl = tool.projectUrl !== undefined &&
|
||||
tool.projectUrl !== null &&
|
||||
tool.projectUrl !== "" &&
|
||||
tool.projectUrl.trim() !== "";
|
||||
---
|
||||
|
||||
<BaseLayout title={entry.data.title} description={entry.data.description}>
|
||||
<article style="max-width: 900px; margin: 0 auto;">
|
||||
<!-- Header -->
|
||||
<header style="margin-bottom: 2rem; padding: 2rem; background: linear-gradient(135deg, var(--color-bg-secondary) 0%, var(--color-bg-tertiary) 100%); border-radius: 1rem; border: 1px solid var(--color-border);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem;">
|
||||
<div style="flex: 1;">
|
||||
<h1 style="margin: 0 0 0.5rem 0; color: var(--color-primary);">
|
||||
{tool.icon && <span style="margin-right: 0.75rem; font-size: 1.5rem;">{tool.icon}</span>}
|
||||
{entry.data.title}
|
||||
</h1>
|
||||
<p style="margin: 0; color: var(--color-text-secondary); font-size: 1.125rem;">
|
||||
{entry.data.description}
|
||||
</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 0.5rem; align-items: end;">
|
||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||||
{isConcept && <span class="badge" style="background-color: var(--color-concept); color: white;">Konzept</span>}
|
||||
{isMethod && <span class="badge" style="background-color: var(--color-method); color: white;">Methode</span>}
|
||||
{!isMethod && !isConcept && <span class="badge" style="background-color: var(--color-primary); color: white;">Software</span>}
|
||||
{!isMethod && !isConcept && hasValidProjectUrl && <span class="badge badge-primary">CC24-Server</span>}
|
||||
{!isMethod && !isConcept && tool.license !== 'Proprietary' && <span class="badge badge-success">Open Source</span>}
|
||||
<span class="badge badge-error">📖</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Metadata -->
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--color-border);">
|
||||
<div>
|
||||
<strong style="font-size: 0.875rem; color: var(--color-text-secondary);">Schwierigkeit</strong>
|
||||
<p style="margin: 0; font-size: 0.9375rem;">{entry.data.difficulty}</p>
|
||||
</div>
|
||||
<div>
|
||||
<strong style="font-size: 0.875rem; color: var(--color-text-secondary);">Letztes Update</strong>
|
||||
<p style="margin: 0; font-size: 0.9375rem;">{entry.data.last_updated.toLocaleDateString('de-DE')}</p>
|
||||
</div>
|
||||
<div>
|
||||
<strong style="font-size: 0.875rem; color: var(--color-text-secondary);">Autor</strong>
|
||||
<p style="margin: 0; font-size: 0.9375rem;">{entry.data.author}</p>
|
||||
</div>
|
||||
{entry.data.categories && entry.data.categories.length > 0 && (
|
||||
<div>
|
||||
<strong style="font-size: 0.875rem; color: var(--color-text-secondary);">Kategorien</strong>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.25rem;">
|
||||
{entry.data.categories.map((cat: string) => (
|
||||
<span class="tag" style="font-size: 0.75rem;">{cat}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav style="margin-bottom: 2rem; position: relative; z-index: 50;">
|
||||
<a href="/knowledgebase" class="btn btn-secondary">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<polyline points="15,18 9,12 15,6"></polyline>
|
||||
</svg>
|
||||
Zurück zur Knowledgebase
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="card" style="padding: 2rem;">
|
||||
<div class="kb-content markdown-content" style="line-height: 1.7;">
|
||||
<Content />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tool Actions -->
|
||||
<div class="card" style="margin-top: 2rem; background-color: var(--color-bg-secondary);">
|
||||
<h3 style="margin: 0 0 1rem 0; color: var(--color-text);">Tool-Aktionen</h3>
|
||||
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
|
||||
{isConcept ? (
|
||||
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="background-color: var(--color-concept); border-color: var(--color-concept);">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
|
||||
<polyline points="15 3 21 3 21 9"/>
|
||||
<line x1="10" y1="14" x2="21" y2="3"/>
|
||||
</svg>
|
||||
Mehr erfahren
|
||||
</a>
|
||||
) : isMethod ? (
|
||||
<a href={tool.projectUrl || tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="background-color: var(--color-method); border-color: var(--color-method);">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
|
||||
<polyline points="15 3 21 3 21 9"/>
|
||||
<line x1="10" y1="14" x2="21" y2="3"/>
|
||||
</svg>
|
||||
Zur Methode
|
||||
</a>
|
||||
) : (
|
||||
<>
|
||||
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
|
||||
<polyline points="15 3 21 3 21 9"/>
|
||||
<line x1="10" y1="14" x2="21" y2="3"/>
|
||||
</svg>
|
||||
Software-Homepage
|
||||
</a>
|
||||
{hasValidProjectUrl && (
|
||||
<a href={tool.projectUrl} target="_blank" rel="noopener noreferrer" class="btn btn-primary">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<path d="M12 16l4-4-4-4"/>
|
||||
<path d="M8 12h8"/>
|
||||
</svg>
|
||||
Zugreifen
|
||||
</a>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<a href="/" class="btn btn-secondary">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
|
||||
<polyline points="9,22 9,12 15,12 15,22"/>
|
||||
</svg>
|
||||
Zur Hauptseite
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</BaseLayout>
|
@ -614,7 +614,10 @@ input[type="checkbox"] {
|
||||
}
|
||||
|
||||
.badge-primary { background-color: var(--color-primary); color: white; }
|
||||
.badge-secondary { background-color: var(--color-bg-secondary); color: var(--color-text); border: 1px solid var(--color-border); }
|
||||
.badge-success { background-color: var(--color-accent); color: white; }
|
||||
.badge-accent { background-color: var(--color-accent); color: white; }
|
||||
.badge-warning { background-color: var(--color-warning); color: white; }
|
||||
.badge-error { background-color: var(--color-error); color: white; }
|
||||
|
||||
/* Tags */
|
||||
@ -1258,20 +1261,8 @@ Collaboration Section Collapse */
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.kb-expand-icon {
|
||||
transition: var(--transition-medium);
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.kb-expand-icon svg { transition: var(--transition-medium); }
|
||||
|
||||
.kb-entry-content {
|
||||
margin-top: 1rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--color-border);
|
||||
animation: slideDown 0.3s ease-out;
|
||||
}
|
||||
|
||||
.kb-content { line-height: 1.7; }
|
||||
|
||||
/* Footer */
|
||||
@ -1494,3 +1485,92 @@ footer {
|
||||
padding: 0.25rem 0.375rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.markdown-content h1,
|
||||
.markdown-content h2,
|
||||
.markdown-content h3,
|
||||
.markdown-content h4,
|
||||
.markdown-content h5,
|
||||
.markdown-content h6 {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.markdown-content h1:first-child,
|
||||
.markdown-content h2:first-child,
|
||||
.markdown-content h3:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.markdown-content p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.markdown-content ul,
|
||||
.markdown-content ol {
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.markdown-content li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.markdown-content pre {
|
||||
background-color: var(--color-bg-tertiary);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
margin: 1.5rem 0;
|
||||
overflow-x: auto;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.markdown-content code:not(pre code) {
|
||||
background-color: var(--color-bg-secondary);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.125rem 0.375rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.markdown-content table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1.5rem 0;
|
||||
background-color: var(--color-bg);
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.markdown-content th,
|
||||
.markdown-content td {
|
||||
padding: 0.75rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.markdown-content th {
|
||||
background-color: var(--color-bg-secondary);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-content blockquote {
|
||||
border-left: 4px solid var(--color-primary);
|
||||
background-color: var(--color-bg-secondary);
|
||||
padding: 1rem 1.5rem;
|
||||
margin: 1.5rem 0;
|
||||
border-radius: 0 0.5rem 0.5rem 0;
|
||||
}
|
||||
|
||||
.markdown-content hr {
|
||||
border: none;
|
||||
border-top: 1px solid var(--color-border);
|
||||
margin: 2rem 0;
|
||||
}
|
@ -51,6 +51,7 @@ interface ToolsData {
|
||||
|
||||
interface CompressedToolsData extends Omit<ToolsData, 'tools'> {
|
||||
tools: any[];
|
||||
concepts: any[]; // NEW: Add concepts for AI background knowledge
|
||||
}
|
||||
|
||||
let cachedData: ToolsData | null = null;
|
||||
@ -128,21 +129,30 @@ export async function getToolsData(): Promise<ToolsData> {
|
||||
return cachedRandomizedData;
|
||||
}
|
||||
|
||||
// Get compressed data for AI (removes projectUrl and statusUrl, excludes concepts)
|
||||
// Get compressed data for AI (excludes concepts from tools, but includes them separately for background knowledge)
|
||||
export async function getCompressedToolsDataForAI(): Promise<CompressedToolsData> {
|
||||
if (!cachedCompressedData) {
|
||||
const data = await getToolsData();
|
||||
|
||||
// Filter out concepts and compress remaining tools
|
||||
// Separate tools and concepts
|
||||
const compressedTools = data.tools
|
||||
.filter(tool => tool.type !== 'concept') // Exclude concepts from AI
|
||||
.filter(tool => tool.type !== 'concept') // Exclude concepts from tool recommendations
|
||||
.map(tool => {
|
||||
const { projectUrl, statusUrl, ...compressedTool } = tool;
|
||||
return compressedTool;
|
||||
});
|
||||
|
||||
// Extract concepts for background knowledge - keep essential fields only
|
||||
const concepts = data.tools
|
||||
.filter(tool => tool.type === 'concept')
|
||||
.map(concept => {
|
||||
const { projectUrl, statusUrl, platforms, accessType, license, ...compressedConcept } = concept;
|
||||
return compressedConcept;
|
||||
});
|
||||
|
||||
cachedCompressedData = {
|
||||
tools: compressedTools,
|
||||
concepts: concepts,
|
||||
domains: data.domains,
|
||||
phases: data.phases,
|
||||
'domain-agnostic-software': data['domain-agnostic-software']
|
||||
|
Loading…
x
Reference in New Issue
Block a user