Skip to content

Commit d2d8f65

Browse files
Add incident runbooks and export formats
1 parent 171353d commit d2d8f65

10 files changed

Lines changed: 922 additions & 52 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,21 @@ jobs:
8585
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/incidents/" >/dev/null
8686
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/incidents/1" >/dev/null
8787
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/incidents/1/nis2-export" >/dev/null
88+
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/incidents/1/nis2-export.html" >/dev/null
89+
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/incidents/1/nis2-export.pdf" >/dev/null
8890
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/api/v1/accounts/users" >/dev/null
8991
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/api/v1/accounts/roles" >/dev/null
9092
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/api/v1/accounts/groups" >/dev/null
9193
curl -fsS -b "$cookie_file" "$RUST_BACKEND_URL/api/v1/accounts/permissions" >/dev/null
9294
curl -fsS -b "$cookie_file" -F import_type='processes' -F "file=@$import_file;filename=preview.csv;type=text/csv" "$RUST_BACKEND_URL/api/v1/import-center/preview" >/dev/null
9395
curl -fsS -b "$cookie_file" -H "content-type: application/json" -d '{"import_type":"business_units","replace_existing":false,"csv_data":"name\nRust Smoke Import"}' "$RUST_BACKEND_URL/api/v1/import-center/csv" >/dev/null
94-
curl -fsS -b "$cookie_file" -F title='Rust Smoke Evidence' -F status='SUBMITTED' -F session_id='1' -F requirement_id='1' -F "file=@$evidence_file;filename=evidence.txt;type=text/plain" "$RUST_BACKEND_URL/api/v1/evidence/uploads" >/dev/null
96+
curl -fsS -b "$cookie_file" -F title='Rust Smoke Evidence' -F status='SUBMITTED' -F session_id='1' -F requirement_id='1' -F incident_id='1' -F "file=@$evidence_file;filename=evidence.txt;type=text/plain" "$RUST_BACKEND_URL/api/v1/evidence/uploads" >/dev/null
9597
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$RUST_BACKEND_URL/api/v1/catalog/domains" >/dev/null
9698
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$RUST_BACKEND_URL/api/v1/requirements" >/dev/null
9799
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$RUST_BACKEND_URL/api/v1/incidents" >/dev/null
98100
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$RUST_BACKEND_URL/api/v1/incidents/1/nis2-export" >/dev/null
101+
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$RUST_BACKEND_URL/api/v1/incidents/1/nis2-export.html" >/dev/null
102+
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$RUST_BACKEND_URL/api/v1/incidents/1/nis2-export.pdf" >/dev/null
99103
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$RUST_BACKEND_URL/api/v1/product-security/overview" >/dev/null
100104
101105
docker-config:

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,22 @@ rust-smoke:
8181
curl -fsS -b "$$cookie_file" "$$url/incidents/" >/dev/null; \
8282
curl -fsS -b "$$cookie_file" "$$url/incidents/1" >/dev/null; \
8383
curl -fsS -b "$$cookie_file" "$$url/incidents/1/nis2-export" >/dev/null; \
84+
curl -fsS -b "$$cookie_file" "$$url/incidents/1/nis2-export.html" >/dev/null; \
85+
curl -fsS -b "$$cookie_file" "$$url/incidents/1/nis2-export.pdf" >/dev/null; \
8486
curl -fsS -b "$$cookie_file" "$$url/api/v1/accounts/users" >/dev/null; \
8587
curl -fsS -b "$$cookie_file" "$$url/api/v1/accounts/roles" >/dev/null; \
8688
curl -fsS -b "$$cookie_file" "$$url/api/v1/accounts/groups" >/dev/null; \
8789
curl -fsS -b "$$cookie_file" "$$url/api/v1/accounts/permissions" >/dev/null; \
8890
curl -fsS -b "$$cookie_file" -F import_type='processes' -F "file=@$$import_file;filename=preview.csv;type=text/csv" "$$url/api/v1/import-center/preview" >/dev/null; \
8991
curl -fsS -b "$$cookie_file" -H "content-type: application/json" -d '{"import_type":"business_units","replace_existing":false,"csv_data":"name\nRust Smoke Import"}' "$$url/api/v1/import-center/csv" >/dev/null; \
90-
curl -fsS -b "$$cookie_file" -F title='Rust Smoke Evidence' -F status='SUBMITTED' -F session_id='1' -F requirement_id='1' -F "file=@$$evidence_file;filename=evidence.txt;type=text/plain" "$$url/api/v1/evidence/uploads" >/dev/null; \
92+
curl -fsS -b "$$cookie_file" -F title='Rust Smoke Evidence' -F status='SUBMITTED' -F session_id='1' -F requirement_id='1' -F incident_id='1' -F "file=@$$evidence_file;filename=evidence.txt;type=text/plain" "$$url/api/v1/evidence/uploads" >/dev/null; \
9193
curl -fsS "$$url/dashboard/?tenant_id=1&user_id=1" >/dev/null; \
9294
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/catalog/domains" >/dev/null; \
9395
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/requirements" >/dev/null; \
9496
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/incidents" >/dev/null; \
9597
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/incidents/1/nis2-export" >/dev/null; \
98+
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/incidents/1/nis2-export.html" >/dev/null; \
99+
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/incidents/1/nis2-export.pdf" >/dev/null; \
96100
curl -fsS -H "x-iscy-tenant-id: 1" -H "x-iscy-user-id: 1" "$$url/api/v1/product-security/overview" >/dev/null; \
97101
echo "Rust smoke OK: $$url"
98102

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Das Backend stellt serverseitige Weboberflaechen und APIs fuer die migrierten Pr
9595
- `/cves/`
9696
- `/admin/users/`
9797

98-
Incidents werden als Rust-Fallakten unter `/incidents/` gefuehrt. Detailseiten unter `/incidents/{id}` erlauben die Bearbeitung von Status, Severity, Meldezeitpunkten und Behoerdenreferenz; das NIS2-Meldepaket kann als Markdown ueber `/incidents/{id}/nis2-export` oder `/api/v1/incidents/{id}/nis2-export` exportiert werden.
98+
Incidents werden als Rust-Fallakten unter `/incidents/` gefuehrt. Detailseiten unter `/incidents/{id}` erlauben die Bearbeitung von Typ, Runbook, Status, Severity, Meldezeitpunkten und Behoerdenreferenz; verknuepfte Evidence wird direkt in der Fallakte angezeigt. Das NIS2-Meldepaket kann als Markdown, HTML oder PDF ueber `/incidents/{id}/nis2-export`, `/incidents/{id}/nis2-export.html`, `/incidents/{id}/nis2-export.pdf` sowie die entsprechenden `/api/v1/incidents/{id}/...` Endpunkte exportiert werden.
9999

100100
## Zero-Trust Agent
101101

docs/ISCY_Handbuch.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ Hier wird aus einer technischen Schwachstellenmeldung eine geschaeftlich nutzbar
551551

552552
### 6.5 Incident- und NIS2-Meldeworkflow
553553

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.
554+
Die Rust-Webroute `/incidents/` fuehrt operative Sicherheitsvorfaelle als mandantenfaehige Fallakten. Ein Incident kann Reporter, Owner, Risiko, Asset und Prozess referenzieren und enthaelt Typ, Runbook, Status, Severity, Stakeholder-Zusammenfassung sowie Behoerden- oder Case-Referenz.
555555

556556
Wenn ein Incident als NIS2-meldepflichtig markiert wird, berechnet ISCY die relevanten Fristen aus dem Erkennungszeitpunkt:
557557

@@ -561,7 +561,7 @@ Wenn ein Incident als NIS2-meldepflichtig markiert wird, berechnet ISCY die rele
561561

562562
Die Uebersicht zeigt offene Faelle, NIS2-relevante Faelle und ueberfaellige Meldeschritte. Gesendete Meldungen koennen ueber die API als Zeitstempel gepflegt werden.
563563

564-
Die Detailseite `/incidents/{id}` dient als operative Fallakte. Dort koennen berechtigte Rollen Status, Severity, Behoerdenreferenz, Zeitlinie und Meldezeitpunkte pflegen. Das Markdown-Meldepaket unter `/incidents/{id}/nis2-export` buendelt Fallakte, betroffene Bezuege, 24h-/72h-/30-Tage-Fristen, Stakeholder-Zusammenfassung und Lessons Learned fuer Audit- oder Meldezwecke.
564+
Die Detailseite `/incidents/{id}` dient als operative Fallakte. Dort koennen berechtigte Rollen Typ, Runbook, Status, Severity, Behoerdenreferenz, Zeitlinie und Meldezeitpunkte pflegen. Evidence-Uploads koennen ueber `incident_id` direkt an einen Incident gekoppelt werden und erscheinen in der Fallakte. Das Meldepaket unter `/incidents/{id}/nis2-export` buendelt Fallakte, Runbook, verknuepfte Evidence, betroffene Bezuege, 24h-/72h-/30-Tage-Fristen, Stakeholder-Zusammenfassung und Lessons Learned; zusaetzlich stehen HTML und PDF ueber `/incidents/{id}/nis2-export.html` und `/incidents/{id}/nis2-export.pdf` bereit.
565565

566566
### 6.6 SOC-Playbook fuer Phishing- und aehnliche Incident-Faelle
567567

docs/RUST_CUTOVER_STATUS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ 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, Fallakten, Detailbearbeitung und Markdown-Meldepaket
28-
- Evidence inklusive Upload
27+
- Incidents inklusive NIS2-Meldefristen, Fallakten, Detailbearbeitung, Runbooks und Markdown-/HTML-/PDF-Meldepaket
28+
- Evidence inklusive Upload und Incident-Verknuepfung
2929
- Reports
3030
- Roadmap
3131
- Assets

rust/iscy-backend/src/db_admin.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ const MIGRATIONS: &[Migration] = &[
7777
sqlite_sql: SQLITE_INCIDENT_SCHEMA,
7878
postgres_sql: POSTGRES_INCIDENT_SCHEMA,
7979
},
80+
Migration {
81+
version: "0010_rust_incident_runbooks_evidence_exports",
82+
sqlite_sql: SQLITE_INCIDENT_RUNBOOK_EVIDENCE_EXPORT_SCHEMA,
83+
postgres_sql: POSTGRES_INCIDENT_RUNBOOK_EVIDENCE_EXPORT_SCHEMA,
84+
},
8085
];
8186

8287
const SQLITE_CATALOG_REQUIREMENTS_SEED: &str =
@@ -399,6 +404,34 @@ CREATE INDEX IF NOT EXISTS idx_incidents_related_asset ON incidents_incident(ten
399404
CREATE INDEX IF NOT EXISTS idx_incidents_related_process ON incidents_incident(tenant_id, related_process_id);
400405
"#;
401406

407+
const SQLITE_INCIDENT_RUNBOOK_EVIDENCE_EXPORT_SCHEMA: &str = r#"
408+
ALTER TABLE incidents_incident ADD COLUMN incident_type varchar(32) NOT NULL DEFAULT 'GENERAL';
409+
ALTER TABLE incidents_incident ADD COLUMN runbook_template TEXT NOT NULL DEFAULT '';
410+
ALTER TABLE evidence_evidenceitem ADD COLUMN incident_id INTEGER NULL;
411+
CREATE INDEX IF NOT EXISTS idx_evidence_items_incident ON evidence_evidenceitem(tenant_id, incident_id);
412+
UPDATE incidents_incident
413+
SET incident_type = 'PHISHING',
414+
runbook_template = '1. Scope erfassen; 2. Eindaemmung durchfuehren; 3. Meldung bewerten'
415+
WHERE runbook_template = '' AND LOWER(title) LIKE '%phishing%';
416+
UPDATE incidents_incident
417+
SET runbook_template = '1. Scope erfassen; 2. Eindaemmung durchfuehren; 3. Kommunikation abstimmen; 4. Lessons Learned dokumentieren'
418+
WHERE runbook_template = '';
419+
"#;
420+
421+
const POSTGRES_INCIDENT_RUNBOOK_EVIDENCE_EXPORT_SCHEMA: &str = r#"
422+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS incident_type varchar(32) NOT NULL DEFAULT 'GENERAL';
423+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS runbook_template TEXT NOT NULL DEFAULT '';
424+
ALTER TABLE evidence_evidenceitem ADD COLUMN IF NOT EXISTS incident_id BIGINT NULL;
425+
CREATE INDEX IF NOT EXISTS idx_evidence_items_incident ON evidence_evidenceitem(tenant_id, incident_id);
426+
UPDATE incidents_incident
427+
SET incident_type = 'PHISHING',
428+
runbook_template = '1. Scope erfassen; 2. Eindaemmung durchfuehren; 3. Meldung bewerten'
429+
WHERE runbook_template = '' AND LOWER(title) LIKE '%phishing%';
430+
UPDATE incidents_incident
431+
SET runbook_template = '1. Scope erfassen; 2. Eindaemmung durchfuehren; 3. Kommunikation abstimmen; 4. Lessons Learned dokumentieren'
432+
WHERE runbook_template = '';
433+
"#;
434+
402435
const SQLITE_AUTH_RBAC_SCHEMA: &str = r#"
403436
CREATE TABLE IF NOT EXISTS accounts_role (
404437
id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -2218,13 +2251,14 @@ INSERT OR IGNORE INTO risks_risk (
22182251
);
22192252
INSERT OR IGNORE INTO incidents_incident (
22202253
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,
2254+
title, summary, incident_type, runbook_template, severity, status, detected_at, confirmed_at, contained_at, resolved_at,
22222255
nis2_reportable, early_warning_due_at, early_warning_sent_at, notification_due_at,
22232256
notification_sent_at, final_report_due_at, final_report_sent_at, authority_reference,
22242257
stakeholder_summary, lessons_learned, created_at, updated_at
22252258
) VALUES (
22262259
1, 1, 1, 1, 1, 1, 1,
22272260
'Credential phishing campaign', 'Demo incident with NIS2 notification tracking.',
2261+
'PHISHING', '1. Scope erfassen; 2. Eindaemmung durchfuehren; 3. Meldung bewerten',
22282262
'HIGH', 'CONFIRMED', '2026-04-22T10:00:00Z', '2026-04-22T11:00:00Z', NULL, NULL,
22292263
1, '2026-04-23T10:00:00Z', NULL, '2026-04-25T10:00:00Z',
22302264
NULL, '2026-05-22T10:00:00Z', NULL, '',
@@ -2265,9 +2299,9 @@ INSERT OR IGNORE INTO requirements_app_requirement (
22652299
);
22662300
INSERT OR IGNORE INTO evidence_evidenceitem (
22672301
id, tenant_id, session_id, domain_id, measure_id, requirement_id, title, description,
2268-
linked_requirement, file, status, owner_id, review_notes, reviewed_by_id, reviewed_at, created_at, updated_at
2302+
incident_id, linked_requirement, file, status, owner_id, review_notes, reviewed_by_id, reviewed_at, created_at, updated_at
22692303
) VALUES (
2270-
1, 1, 1, NULL, NULL, 1, 'MFA rollout evidence', 'Initial MFA rollout evidence.',
2304+
1, 1, 1, NULL, NULL, 1, 'MFA rollout evidence', 'Initial MFA rollout evidence.', 1,
22712305
'NIS2-21-MFA', NULL, 'APPROVED', 1, 'Looks ready for demo.', 1, '2026-04-22T10:00:00Z',
22722306
'2026-04-22T10:00:00Z', '2026-04-22T10:00:00Z'
22732307
);
@@ -2539,13 +2573,14 @@ INSERT INTO risks_risk (
25392573
) ON CONFLICT (id) DO NOTHING;
25402574
INSERT INTO incidents_incident (
25412575
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,
2576+
title, summary, incident_type, runbook_template, severity, status, detected_at, confirmed_at, contained_at, resolved_at,
25432577
nis2_reportable, early_warning_due_at, early_warning_sent_at, notification_due_at,
25442578
notification_sent_at, final_report_due_at, final_report_sent_at, authority_reference,
25452579
stakeholder_summary, lessons_learned, created_at, updated_at
25462580
) VALUES (
25472581
1, 1, 1, 1, 1, 1, 1,
25482582
'Credential phishing campaign', 'Demo incident with NIS2 notification tracking.',
2583+
'PHISHING', '1. Scope erfassen; 2. Eindaemmung durchfuehren; 3. Meldung bewerten',
25492584
'HIGH', 'CONFIRMED', '2026-04-22T10:00:00Z', '2026-04-22T11:00:00Z', NULL, NULL,
25502585
TRUE, '2026-04-23T10:00:00Z', NULL, '2026-04-25T10:00:00Z',
25512586
NULL, '2026-05-22T10:00:00Z', NULL, '',
@@ -2586,9 +2621,9 @@ INSERT INTO requirements_app_requirement (
25862621
) ON CONFLICT (id) DO NOTHING;
25872622
INSERT INTO evidence_evidenceitem (
25882623
id, tenant_id, session_id, domain_id, measure_id, requirement_id, title, description,
2589-
linked_requirement, file, status, owner_id, review_notes, reviewed_by_id, reviewed_at, created_at, updated_at
2624+
incident_id, linked_requirement, file, status, owner_id, review_notes, reviewed_by_id, reviewed_at, created_at, updated_at
25902625
) VALUES (
2591-
1, 1, 1, NULL, NULL, 1, 'MFA rollout evidence', 'Initial MFA rollout evidence.',
2626+
1, 1, 1, NULL, NULL, 1, 'MFA rollout evidence', 'Initial MFA rollout evidence.', 1,
25922627
'NIS2-21-MFA', NULL, 'APPROVED', 1, 'Looks ready for demo.', 1, '2026-04-22T10:00:00Z',
25932628
'2026-04-22T10:00:00Z', '2026-04-22T10:00:00Z'
25942629
) ON CONFLICT (id) DO NOTHING;

0 commit comments

Comments
 (0)