Skip to content

Commit 231a0ab

Browse files
Add Rust incident notification workflow
1 parent ee718d5 commit 231a0ab

9 files changed

Lines changed: 2444 additions & 10 deletions

File tree

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ rust-smoke:
7878
curl -fsS -b "$$cookie_file" "$$url/dashboard/" >/dev/null; \
7979
curl -fsS -b "$$cookie_file" "$$url/admin/users/" >/dev/null; \
8080
curl -fsS -b "$$cookie_file" "$$url/imports/" >/dev/null; \
81+
curl -fsS -b "$$cookie_file" "$$url/incidents/" >/dev/null; \
8182
curl -fsS -b "$$cookie_file" "$$url/api/v1/accounts/users" >/dev/null; \
8283
curl -fsS -b "$$cookie_file" "$$url/api/v1/accounts/roles" >/dev/null; \
8384
curl -fsS -b "$$cookie_file" "$$url/api/v1/accounts/groups" >/dev/null; \
@@ -88,6 +89,7 @@ rust-smoke:
8889
curl -fsS "$$url/dashboard/?tenant_id=1&user_id=1" >/dev/null; \
8990
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/catalog/domains" >/dev/null; \
9091
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/requirements" >/dev/null; \
92+
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/incidents" >/dev/null; \
9193
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/product-security/overview" >/dev/null; \
9294
echo "Rust smoke OK: $$url"
9395

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ISCY V23.7.2 / Rust 0.3.0
22

3-
ISCY ist eine ISMS-/Cybersecurity-Plattform mit ISO 27001-, NIS2- und KRITIS-Unterstuetzung, Product Security, Zero-Trust-Agent-Posture, lokalem CVE-Enrichment und lokalem LLM-Betrieb.
3+
ISCY ist eine ISMS-/Cybersecurity-Plattform mit ISO 27001-, NIS2- und KRITIS-Unterstuetzung, Incident-/Meldeworkflow, Product Security, Zero-Trust-Agent-Posture, lokalem CVE-Enrichment und lokalem LLM-Betrieb.
44

55
Der Runtime-Cutover nach Rust ist abgeschlossen: Die produktive Anwendung laeuft ueber den Rust-Axum-Service in `rust/iscy-backend`. Die fruehere Django/Python-Anwendung, ihre Templates, Settings, Requirements und Startpfade wurden aus dem Repository entfernt.
66

@@ -84,6 +84,7 @@ Das Backend stellt serverseitige Weboberflaechen und APIs fuer die migrierten Pr
8484
- `/assessments/`
8585
- `/organizations/`
8686
- `/risks/`
87+
- `/incidents/`
8788
- `/evidence/`
8889
- `/reports/`
8990
- `/roadmap/`

docs/ISCY_Handbuch.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,19 @@ Hier wird aus einer technischen Schwachstellenmeldung eine geschaeftlich nutzbar
549549
4. Risiko und Vulnerability automatisch verknuepfen
550550
5. Massnahmen ueber Roadmap oder Behandlung steuern
551551

552-
### 6.5 SOC-Playbook fuer Phishing- und aehnliche Incident-Faelle
552+
### 6.5 Incident- und NIS2-Meldeworkflow
553+
554+
Die Rust-Webroute `/incidents/` fuehrt operative Sicherheitsvorfaelle als mandantenfaehige Fallakten. Ein Incident kann Reporter, Owner, Risiko, Asset und Prozess referenzieren und enthaelt Status, Severity, Stakeholder-Zusammenfassung sowie Behoerden- oder Case-Referenz.
555+
556+
Wenn ein Incident als NIS2-meldepflichtig markiert wird, berechnet ISCY die relevanten Fristen aus dem Erkennungszeitpunkt:
557+
558+
1. 24h-Fruehwarnung
559+
2. 72h-Meldung
560+
3. Abschlussbericht nach 30 Tagen
561+
562+
Die Uebersicht zeigt offene Faelle, NIS2-relevante Faelle und ueberfaellige Meldeschritte. Gesendete Meldungen koennen ueber die API als Zeitstempel gepflegt werden.
563+
564+
### 6.6 SOC-Playbook fuer Phishing- und aehnliche Incident-Faelle
553565

554566
Empfohlene Kette fuer die operative Bearbeitung:
555567

@@ -574,7 +586,7 @@ Empfohlene Kette fuer die operative Bearbeitung:
574586

575587
Merksatz: Erst verstehen, dann bewerten, dann eindaemmen, dann eskalieren - wenn Risiko oder Komplexitaet es verlangen.
576588

577-
### 6.6 ISCY lokal starten
589+
### 6.7 ISCY lokal starten
578590

579591
Einfachster lokaler Start:
580592

docs/RUST_CUTOVER_STATUS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ISCY Rust-Cutover-Status
22

3-
Stand: 2026-06-07
3+
Stand: 2026-06-08
44

55
## Kurzfassung
66

@@ -24,6 +24,7 @@ ISCY startet produktiv und lokal ueber den Rust-Axum-Service in `rust/iscy-backe
2424
- Assessments
2525
- Organizations
2626
- Risks
27+
- Incidents inklusive NIS2-Meldefristen und Fallakten
2728
- Evidence inklusive Upload
2829
- Reports
2930
- Roadmap

rust/iscy-backend/src/db_admin.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ const MIGRATIONS: &[Migration] = &[
7272
sqlite_sql: SQLITE_AGENT_ENROLLMENT_HARDENING_SCHEMA,
7373
postgres_sql: POSTGRES_AGENT_ENROLLMENT_HARDENING_SCHEMA,
7474
},
75+
Migration {
76+
version: "0009_rust_incident_core",
77+
sqlite_sql: SQLITE_INCIDENT_SCHEMA,
78+
postgres_sql: POSTGRES_INCIDENT_SCHEMA,
79+
},
7580
];
7681

7782
const SQLITE_CATALOG_REQUIREMENTS_SEED: &str =
@@ -320,6 +325,80 @@ CREATE INDEX IF NOT EXISTS idx_zero_trust_agent_token_hash ON zero_trust_agent_e
320325
CREATE INDEX IF NOT EXISTS idx_zero_trust_agent_device_auth ON zero_trust_agent_device(tenant_id, auth_model, enrollment_status);
321326
"#;
322327

328+
const SQLITE_INCIDENT_SCHEMA: &str = r#"
329+
CREATE TABLE IF NOT EXISTS incidents_incident (
330+
id INTEGER PRIMARY KEY AUTOINCREMENT,
331+
tenant_id INTEGER NOT NULL,
332+
reporter_id INTEGER NULL,
333+
owner_id INTEGER NULL,
334+
related_risk_id INTEGER NULL,
335+
related_asset_id INTEGER NULL,
336+
related_process_id INTEGER NULL,
337+
title varchar(255) NOT NULL,
338+
summary TEXT NOT NULL DEFAULT '',
339+
severity varchar(16) NOT NULL DEFAULT 'MEDIUM',
340+
status varchar(32) NOT NULL DEFAULT 'TRIAGE',
341+
detected_at TEXT NULL,
342+
confirmed_at TEXT NULL,
343+
contained_at TEXT NULL,
344+
resolved_at TEXT NULL,
345+
nis2_reportable bool NOT NULL DEFAULT 0,
346+
early_warning_due_at TEXT NULL,
347+
early_warning_sent_at TEXT NULL,
348+
notification_due_at TEXT NULL,
349+
notification_sent_at TEXT NULL,
350+
final_report_due_at TEXT NULL,
351+
final_report_sent_at TEXT NULL,
352+
authority_reference varchar(255) NOT NULL DEFAULT '',
353+
stakeholder_summary TEXT NOT NULL DEFAULT '',
354+
lessons_learned TEXT NOT NULL DEFAULT '',
355+
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
356+
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
357+
);
358+
CREATE INDEX IF NOT EXISTS idx_incidents_tenant_status ON incidents_incident(tenant_id, status, severity);
359+
CREATE INDEX IF NOT EXISTS idx_incidents_tenant_nis2 ON incidents_incident(tenant_id, nis2_reportable, notification_due_at);
360+
CREATE INDEX IF NOT EXISTS idx_incidents_related_risk ON incidents_incident(tenant_id, related_risk_id);
361+
CREATE INDEX IF NOT EXISTS idx_incidents_related_asset ON incidents_incident(tenant_id, related_asset_id);
362+
CREATE INDEX IF NOT EXISTS idx_incidents_related_process ON incidents_incident(tenant_id, related_process_id);
363+
"#;
364+
365+
const POSTGRES_INCIDENT_SCHEMA: &str = r#"
366+
CREATE TABLE IF NOT EXISTS incidents_incident (
367+
id BIGSERIAL PRIMARY KEY,
368+
tenant_id BIGINT NOT NULL,
369+
reporter_id BIGINT NULL,
370+
owner_id BIGINT NULL,
371+
related_risk_id BIGINT NULL,
372+
related_asset_id BIGINT NULL,
373+
related_process_id BIGINT NULL,
374+
title varchar(255) NOT NULL,
375+
summary TEXT NOT NULL DEFAULT '',
376+
severity varchar(16) NOT NULL DEFAULT 'MEDIUM',
377+
status varchar(32) NOT NULL DEFAULT 'TRIAGE',
378+
detected_at TEXT NULL,
379+
confirmed_at TEXT NULL,
380+
contained_at TEXT NULL,
381+
resolved_at TEXT NULL,
382+
nis2_reportable BOOLEAN NOT NULL DEFAULT FALSE,
383+
early_warning_due_at TEXT NULL,
384+
early_warning_sent_at TEXT NULL,
385+
notification_due_at TEXT NULL,
386+
notification_sent_at TEXT NULL,
387+
final_report_due_at TEXT NULL,
388+
final_report_sent_at TEXT NULL,
389+
authority_reference varchar(255) NOT NULL DEFAULT '',
390+
stakeholder_summary TEXT NOT NULL DEFAULT '',
391+
lessons_learned TEXT NOT NULL DEFAULT '',
392+
created_at TEXT NOT NULL DEFAULT (CURRENT_TIMESTAMP)::text,
393+
updated_at TEXT NOT NULL DEFAULT (CURRENT_TIMESTAMP)::text
394+
);
395+
CREATE INDEX IF NOT EXISTS idx_incidents_tenant_status ON incidents_incident(tenant_id, status, severity);
396+
CREATE INDEX IF NOT EXISTS idx_incidents_tenant_nis2 ON incidents_incident(tenant_id, nis2_reportable, notification_due_at);
397+
CREATE INDEX IF NOT EXISTS idx_incidents_related_risk ON incidents_incident(tenant_id, related_risk_id);
398+
CREATE INDEX IF NOT EXISTS idx_incidents_related_asset ON incidents_incident(tenant_id, related_asset_id);
399+
CREATE INDEX IF NOT EXISTS idx_incidents_related_process ON incidents_incident(tenant_id, related_process_id);
400+
"#;
401+
323402
const SQLITE_AUTH_RBAC_SCHEMA: &str = r#"
324403
CREATE TABLE IF NOT EXISTS accounts_role (
325404
id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -2137,6 +2216,21 @@ INSERT OR IGNORE INTO risks_risk (
21372216
'Roll out phishing-resistant MFA', '2026-06-30', NULL, NULL, '2026-07-15',
21382217
'2026-04-22T10:00:00Z', '2026-04-22T10:00:00Z'
21392218
);
2219+
INSERT OR IGNORE INTO incidents_incident (
2220+
id, tenant_id, reporter_id, owner_id, related_risk_id, related_asset_id, related_process_id,
2221+
title, summary, severity, status, detected_at, confirmed_at, contained_at, resolved_at,
2222+
nis2_reportable, early_warning_due_at, early_warning_sent_at, notification_due_at,
2223+
notification_sent_at, final_report_due_at, final_report_sent_at, authority_reference,
2224+
stakeholder_summary, lessons_learned, created_at, updated_at
2225+
) VALUES (
2226+
1, 1, 1, 1, 1, 1, 1,
2227+
'Credential phishing campaign', 'Demo incident with NIS2 notification tracking.',
2228+
'HIGH', 'CONFIRMED', '2026-04-22T10:00:00Z', '2026-04-22T11:00:00Z', NULL, NULL,
2229+
1, '2026-04-23T10:00:00Z', NULL, '2026-04-25T10:00:00Z',
2230+
NULL, '2026-05-22T10:00:00Z', NULL, '',
2231+
'Credential phishing affects the customer portal operating process.',
2232+
'', '2026-04-22T10:00:00Z', '2026-04-22T11:00:00Z'
2233+
);
21402234
INSERT OR IGNORE INTO wizard_assessmentsession (
21412235
id, tenant_id, started_by_id, assessment_type, status, current_step, applicability_result,
21422236
applicability_reasoning, executive_summary, progress_percent, completed_at, created_at, updated_at
@@ -2443,6 +2537,21 @@ INSERT INTO risks_risk (
24432537
'Roll out phishing-resistant MFA', '2026-06-30', NULL, NULL, '2026-07-15',
24442538
'2026-04-22T10:00:00Z', '2026-04-22T10:00:00Z'
24452539
) ON CONFLICT (id) DO NOTHING;
2540+
INSERT INTO incidents_incident (
2541+
id, tenant_id, reporter_id, owner_id, related_risk_id, related_asset_id, related_process_id,
2542+
title, summary, severity, status, detected_at, confirmed_at, contained_at, resolved_at,
2543+
nis2_reportable, early_warning_due_at, early_warning_sent_at, notification_due_at,
2544+
notification_sent_at, final_report_due_at, final_report_sent_at, authority_reference,
2545+
stakeholder_summary, lessons_learned, created_at, updated_at
2546+
) VALUES (
2547+
1, 1, 1, 1, 1, 1, 1,
2548+
'Credential phishing campaign', 'Demo incident with NIS2 notification tracking.',
2549+
'HIGH', 'CONFIRMED', '2026-04-22T10:00:00Z', '2026-04-22T11:00:00Z', NULL, NULL,
2550+
TRUE, '2026-04-23T10:00:00Z', NULL, '2026-04-25T10:00:00Z',
2551+
NULL, '2026-05-22T10:00:00Z', NULL, '',
2552+
'Credential phishing affects the customer portal operating process.',
2553+
'', '2026-04-22T10:00:00Z', '2026-04-22T11:00:00Z'
2554+
) ON CONFLICT (id) DO NOTHING;
24462555
INSERT INTO wizard_assessmentsession (
24472556
id, tenant_id, started_by_id, assessment_type, status, current_step, applicability_result,
24482557
applicability_reasoning, executive_summary, progress_percent, completed_at, created_at, updated_at

0 commit comments

Comments
 (0)