590 lines
26 KiB
Markdown
590 lines
26 KiB
Markdown
> **Hinweis:** Dies ist der unveränderte externe Vertragstext „CANONICAL_MODEL
|
|
> 1.0.0", geliefert zusammen mit [`RESULT_CONTRACT.md`](RESULT_CONTRACT.md) und
|
|
> validiert gegen ein eigenständiges PostgreSQL-16-DDL. Er beschreibt ein
|
|
> vollständiges eigenständiges Datenmodell (u. a. eine eigene `canonical_result`-
|
|
> Haupttabelle, typspezifische Blöcke, Asset-/Kantenschicht) und ist **nicht**
|
|
> identisch mit dem tatsächlich implementierten ASSESSOR-Modell.
|
|
>
|
|
> Der fachlich verbindliche, implementierte Stand ist
|
|
> [`docs/CANONICAL_MODEL.md`](CANONICAL_MODEL.md) (Schema-Version 1,
|
|
> `src/domain/canonical-model.ts`). Die Integrationsentscheidung vom 2026-07-23
|
|
> (Pfad A, additiv) bildet die Neuerungen dieses Vertrags — `result_type`,
|
|
> `is_ioe`, die Asset-/Kantenschicht — auf das bestehende Modell ab, statt es zu
|
|
> ersetzen. Abweichungen und Begründungen stehen in
|
|
> [`RESULT_CONTRACT.md`](RESULT_CONTRACT.md#abweichungen-der-assessor-realisierung).
|
|
>
|
|
> Diese Datei wird nicht mit `docs/CANONICAL_MODEL.md` zusammengeführt und dient
|
|
> ausschließlich als unveränderte Referenz auf den gelieferten Vertragsstand.
|
|
|
|
---
|
|
|
|
# CANONICAL_MODEL
|
|
|
|
```
|
|
model_version : 1.0.0
|
|
realisiert : RESULT_CONTRACT 1.0.0
|
|
status : vollstaendiges logisches Datenmodell, implementierungsreif
|
|
zielort : docs/CANONICAL_MODEL.md
|
|
gilt_fuer : Purple Knight, PingCastle, Maester, CIS-CAT Pro, GPO-/Baseline-Analyse
|
|
konsumenten : ASSESSOR UI, lokales LLM, Exporte, Graph, weitere Tools
|
|
```
|
|
|
|
Dies ist die eine kanonische, filterbare Datenbasis. Sie ist so geschnitten, dass alle toolübergreifenden Filter ohne Join in typspezifische Blöcke oder JSONB funktionieren, und dass Graph- und GPO-Schicht ohne Vertragsänderung darauf aufsetzen können.
|
|
|
|
Das Modell trennt drei Verantwortungen: normalisierte Filterschicht (Haupttabelle), toolspezifische Wahrheit (typspezifische Blöcke plus `original_fields`), und Graph-Grundlage (Asset- und Kantenschicht). Fehlende Information bleibt NULL beziehungsweise `unknown`; sie wird nie erfunden oder aus ungeeigneten Feldern abgeleitet.
|
|
|
|
## Überblick
|
|
|
|
```
|
|
PROJECT
|
|
└─ ASSESSMENT
|
|
└─ SCAN_RUN
|
|
├─ IMPORT_ARTIFACT (Quelldatei, SHA-256, Tool, Version)
|
|
└─ CANONICAL_RESULT (Haupttabelle, normalisierte Filterschicht)
|
|
├─ RESULT_EXPOSURE (1:1, nur bei result_type = exposure_finding)
|
|
├─ RESULT_COMPLIANCE (1:1, nur bei result_type = compliance_check)
|
|
├─ RESULT_DEVIATION (1:1, nur bei result_type = policy_deviation)
|
|
├─ RESULT_CATEGORY (1:N)
|
|
├─ RESULT_ASSET (1:N, verknuepft mit CANONICAL_ASSET)
|
|
├─ RESULT_EVIDENCE (1:N)
|
|
├─ RESULT_REMEDIATION_STEP (1:N)
|
|
├─ RESULT_REFERENCE (1:N)
|
|
└─ RESULT_REVIEW (1:1, aktueller Stand)
|
|
|
|
Graph-Schicht (assessmentweit, referenziert Results):
|
|
CANONICAL_ASSET (deduplizierte Knoten)
|
|
├─ ASSET_PROPERTY (finding-abgeleitete Knoten-Eigenschaften)
|
|
ASSET_EDGE (gerichtete Kanten zwischen Knoten)
|
|
EDGE_COVERAGE (welche Kantentypen erhoben wurden)
|
|
```
|
|
|
|
Notation in den Feldlisten: `PK` Primärschlüssel, `FK` Fremdschlüssel, `NN` NOT NULL, `IX` indiziert (Filter- oder Join-relevant), `enum X` verweist auf den Enum-Katalog am Ende.
|
|
|
|
## Scope-Tabellen
|
|
|
|
```
|
|
project
|
|
────────────────────────────────
|
|
id uuid PK
|
|
key text NN fachlicher Kundenschluessel
|
|
name text
|
|
created_at timestamptz NN
|
|
|
|
assessment
|
|
────────────────────────────────
|
|
id uuid PK
|
|
project_id uuid FK NN IX
|
|
name text
|
|
period text
|
|
created_at timestamptz NN
|
|
|
|
scan_run
|
|
────────────────────────────────
|
|
id uuid PK
|
|
assessment_id uuid FK NN IX
|
|
label text
|
|
run_kind text NN import | evaluation
|
|
started_at timestamptz
|
|
completed_at timestamptz
|
|
created_at timestamptz NN
|
|
```
|
|
|
|
## Import-Provenienz
|
|
|
|
```
|
|
import_artifact
|
|
────────────────────────────────
|
|
id uuid PK
|
|
scan_run_id uuid FK NN IX
|
|
source_tool enum source_tool NN IX
|
|
source_tool_version text
|
|
source_format enum source_format NN html | xml | json | xccdf | arf | gpo_backup | unknown
|
|
file_name text
|
|
file_sha256 text NN IX Dublettenerkennung
|
|
byte_size bigint
|
|
extractor_id text
|
|
extractor_version text
|
|
profile_id text
|
|
profile_version text
|
|
imported_at timestamptz NN
|
|
parser_warnings jsonb Importdiagnostik
|
|
original_fields jsonb
|
|
```
|
|
|
|
`file_sha256` trägt die Dublettenerkennung. Ein bewusster Reimport erzeugt einen neuen `scan_run`-Kontext; bestehende Results werden nicht überschrieben.
|
|
|
|
## Haupttabelle: CANONICAL_RESULT
|
|
|
|
Die normalisierte Filterschicht. Jede toolübergreifend vergleichbare Achse ist hier eine reale, indizierte Spalte. Kein Konsument muss in einen typspezifischen Block oder nach JSONB greifen, um zu filtern.
|
|
|
|
```
|
|
canonical_result
|
|
──────────────────────────────────────────────────────────
|
|
Identität
|
|
id uuid PK
|
|
model_version text NN
|
|
project_id uuid FK NN IX
|
|
assessment_id uuid FK NN IX
|
|
scan_run_id uuid FK NN IX
|
|
import_artifact_id uuid FK IX
|
|
finding_definition_id text IX stabile Regelidentitaet (z. B. RiskId)
|
|
finding_occurrence_id text IX konkretes Auftreten
|
|
parent_result_id uuid FK IX optionale Hierarchie
|
|
|
|
Herkunft
|
|
source_tool enum source_tool NN IX
|
|
source_tool_version text
|
|
source_rule_id text IX RiskId / PK-ID / XCCDF rule-id / setting_key
|
|
source_rule_name text
|
|
source_locator text HTML-Selektor / XML-Pfad / Dateipfad
|
|
source_original_status text Nativwert, unveraendert
|
|
source_original_severity text Nativwert, unveraendert
|
|
source_original_category text Nativwert, unveraendert
|
|
source_original_score text Nativwert, unveraendert
|
|
|
|
Klassifikation (Achse 1: Art der Aussage)
|
|
result_type enum result_type NN IX
|
|
is_ioe boolean NN IX abgeleitet, materialisiert
|
|
ioe_rule_id text
|
|
ioe_rule_version text
|
|
ioe_derivation_method text
|
|
|
|
Bewertung (Achse 2: Ausgang der Aussage)
|
|
result_state enum result_state NN IX
|
|
severity_normalized enum severity NN IX default unknown
|
|
severity_rank smallint IX fuer Sortierung innerhalb einer Severity-Skala
|
|
severity_original text
|
|
severity_mapping_rule_id text
|
|
severity_mapping_version text
|
|
score_original numeric
|
|
score_normalized numeric NICHT tooluebergreifend vergleichbar
|
|
score_max numeric
|
|
score_unit text
|
|
|
|
Inhalt
|
|
title text NN
|
|
summary text
|
|
description text
|
|
rationale text
|
|
technical_details text
|
|
impact text
|
|
risk_statement text
|
|
remediation_summary text
|
|
remediation_details text
|
|
|
|
Aggregierte Anzeigehilfen (denormalisiert fuer schnelle Listen)
|
|
affected_asset_summary text
|
|
evidence_count integer NN default 0 IX
|
|
has_detailed_evidence boolean NN default false
|
|
primary_category_label text IX gespiegelt aus RESULT_CATEGORY (is_primary)
|
|
primary_category_namespace text IX
|
|
|
|
Quality / Provenance
|
|
recognition_confidence numeric
|
|
mapping_confidence numeric
|
|
classification_confidence numeric
|
|
severity_confidence numeric
|
|
identity_confidence numeric
|
|
evidence_completeness numeric
|
|
mapping_method text
|
|
mapping_rule_id text
|
|
mapping_rule_version text
|
|
extractor_id text
|
|
extractor_version text
|
|
|
|
Lifecycle
|
|
lifecycle_state enum lifecycle_state NN IX default new
|
|
first_seen_at timestamptz NN
|
|
last_seen_at timestamptz NN
|
|
resolved_at timestamptz
|
|
reoccurred_at timestamptz
|
|
previous_result_id uuid FK
|
|
comparison_id uuid
|
|
|
|
Zeit / Erweiterung
|
|
source_observed_at timestamptz
|
|
imported_at timestamptz
|
|
evaluated_at timestamptz
|
|
created_at timestamptz NN
|
|
extensions jsonb bekannte, noch nicht kanonisierte Zusatzwerte
|
|
original_fields jsonb vollstaendige unveraenderte Quellfelder
|
|
```
|
|
|
|
Regel für die denormalisierten Anzeigehilfen (`primary_category_label`, `affected_asset_summary`, `evidence_count`): Sie sind gespiegelte Bequemlichkeitsfelder für schnelle Listenansichten. Die Wahrheit liegt in den Kindtabellen. Die Spiegelung erfolgt deterministisch beim Aufbau des Results, nicht in der UI.
|
|
|
|
## Typspezifische Blöcke
|
|
|
|
Genau ein Block ist pro Result vorhanden, abhängig von `result_type`. Die Blöcke tragen die native Wahrheit der Quelle; die Haupttabelle trägt die normalisierte Projektion daraus.
|
|
|
|
```
|
|
result_exposure (1:1, nur bei result_type = exposure_finding)
|
|
────────────────────────────────
|
|
result_id uuid PK FK
|
|
exposure_state enum exposure_state NN IX
|
|
detected | not_detected | not_evaluated | execution_error | unknown
|
|
native_severity text
|
|
points_original numeric PingCastle
|
|
weight_original numeric Purple Knight
|
|
test_result_native text Maester
|
|
```
|
|
|
|
```
|
|
result_compliance (1:1, nur bei result_type = compliance_check)
|
|
────────────────────────────────
|
|
result_id uuid PK FK
|
|
xccdf_result enum xccdf_result NN IX
|
|
pass | fail | error | unknown | notapplicable | notchecked | notselected | informational | fixed
|
|
benchmark_id text IX
|
|
benchmark_version text
|
|
rule_id text IX
|
|
profile_id text
|
|
weight numeric
|
|
check_content_ref text
|
|
```
|
|
|
|
```
|
|
result_deviation (1:1, nur bei result_type = policy_deviation)
|
|
────────────────────────────────
|
|
result_id uuid PK FK
|
|
setting_key text NN IX kanonischer Policy-Schluessel, nie Anzeigetext
|
|
setting_namespace text NN registry | privilege_right | system_access | audit | gptmpl | ...
|
|
baseline_value text
|
|
subject_value text
|
|
verdict enum verdict NN IX
|
|
match | deviation | missing_on_subject | extra_on_subject | not_comparable
|
|
baseline_ref text IX Referenz auf das versionierte Baseline-Objekt
|
|
baseline_version text IX
|
|
gpo_asset_id uuid FK betroffener GPO-Knoten, falls zutreffend
|
|
```
|
|
|
|
Der `result_deviation`-Block ist strukturell vollständig definiert, aber seine Vergleichs- und Verdikt-Logik (Setting-Identität pro Namespace, Behandlung von „nicht konfiguriert" versus „abwesend", Baseline-Registry) ist Gegenstand des noch offenen GPO-Submodells. Bis dahin bleibt der Block ungenutzt; das Modell ist bereits dafür ausgelegt.
|
|
|
|
## Kindtabellen
|
|
|
|
```
|
|
result_category (1:N)
|
|
────────────────────────────────
|
|
id uuid PK
|
|
result_id uuid FK NN IX
|
|
namespace text NN IX pingcastle | purple-knight | maester | cis | anssi | mitre | ...
|
|
label text NN IX
|
|
path text optionaler Hierarchiepfad
|
|
is_primary boolean NN default false
|
|
```
|
|
|
|
Kategorien sind mehrwertig und namespaced. Eine Kategorie darf nie in eine Severity umgedeutet werden. `is_primary` markiert die Leitkategorie, die in `canonical_result.primary_category_label` gespiegelt wird.
|
|
|
|
```
|
|
result_asset (1:N) Verknuepfung Result zu Knoten
|
|
────────────────────────────────
|
|
id uuid PK
|
|
result_id uuid FK NN IX
|
|
canonical_asset_id uuid FK NN IX dedupliziert, siehe Graph-Schicht
|
|
role text affected | subject | related
|
|
is_primary boolean NN default false
|
|
source_locator text
|
|
```
|
|
|
|
Betroffene Objekte werden nie als kommaseparierter String gespeichert, sondern als Verknüpfung auf deduplizierte Knoten. Das ist zugleich die Brücke zur Graph-Schicht.
|
|
|
|
```
|
|
result_evidence (1:N)
|
|
────────────────────────────────
|
|
id uuid PK
|
|
result_id uuid FK NN IX
|
|
evidence_type enum evidence_type NN
|
|
table | table_row | object | property | text | configuration
|
|
| command_output | policy_observation | reference | screenshot_reference | unknown
|
|
title text
|
|
summary text
|
|
structured_data jsonb strukturierte Detailzeile, nicht Freitext
|
|
text_value text
|
|
source_view_id text
|
|
source_locator text NN
|
|
sequence integer NN Reihenfolge bleibt erhalten
|
|
```
|
|
|
|
Detailzeilen dürfen nicht in eine große Textspalte gepresst werden. Jede Zeile behält ihren `source_locator` und ihre `sequence`.
|
|
|
|
```
|
|
result_remediation_step (1:N)
|
|
────────────────────────────────
|
|
id uuid PK
|
|
result_id uuid FK NN IX
|
|
sequence integer NN
|
|
title text
|
|
instruction text
|
|
command text
|
|
validation text
|
|
```
|
|
|
|
Liefert ein Tool nur Remediation-Freitext, landet dieser in `canonical_result.remediation_details`; strukturierte Schritte bleiben leer und können später ergänzt werden, ohne den Originaltext zu überschreiben.
|
|
|
|
```
|
|
result_reference (1:N) Compliance und externe Referenzen
|
|
────────────────────────────────
|
|
id uuid PK
|
|
result_id uuid FK NN IX
|
|
reference_type text NN framework_control | mitre_attack | cve | cwe | vendor_doc | anssi | ...
|
|
namespace text IX CIS | enterprise-attack | ...
|
|
reference_value text NN IX z. B. T1078, 5.2.3
|
|
title text
|
|
url text
|
|
```
|
|
|
|
MITRE-ATT&CK- und ANSSI-Zuordnungen sind hier als Annotation abgelegt. Sie sind eine Taxonomie der Findings, keine Angriffskette.
|
|
|
|
```
|
|
result_review (1:1, aktueller Stand)
|
|
────────────────────────────────
|
|
result_id uuid PK FK
|
|
review_status enum review_status NN default open IX
|
|
review_disposition text
|
|
review_priority text
|
|
review_owner text
|
|
review_due_date date
|
|
review_comment text
|
|
accepted_risk_reason text
|
|
compensating_control text
|
|
updated_at timestamptz
|
|
```
|
|
|
|
Reviewdaten sind strikt von Importdaten getrennt und verändern keine importierten Werte.
|
|
|
|
## Graph-Schicht
|
|
|
|
### CANONICAL_ASSET
|
|
|
|
Deduplizierter Knotenregister. Jede reale Entität erscheint genau einmal. Identität ausschließlich über autoritativen Schlüssel; Anzeigename führt nie zu einem Merge.
|
|
|
|
```
|
|
canonical_asset
|
|
────────────────────────────────
|
|
id uuid PK
|
|
assessment_id uuid FK NN IX
|
|
asset_key text NN IX deterministischer Dedup-Schluessel, namespaced
|
|
asset_key_kind enum asset_key_kind NN
|
|
sid | object_guid | gpo_guid | domain_sid | trust_key | synthetic
|
|
asset_type enum asset_type NN IX
|
|
user | group | computer | domain_controller | domain
|
|
| ou | gpo | trust | tenant | service_principal | unknown
|
|
primary_name text nicht autoritativ
|
|
domain text IX
|
|
key_confidence numeric NN 1.0 bei autoritativem Schluessel, < 1.0 bei synthetic
|
|
resolution_method text
|
|
source_tools text[]
|
|
first_seen_at timestamptz NN
|
|
last_seen_at timestamptz NN
|
|
original_fields jsonb
|
|
extensions jsonb
|
|
|
|
UNIQUE (assessment_id, asset_key)
|
|
```
|
|
|
|
Merge-Regel (verbindlich in 1.0.0): Zusammenführung nur bei identischem autoritativem Schlüssel. `synthetic`-Knoten (nur-Name-Meldung ohne SID/GUID) verschmelzen nie automatisch mit autoritativen Knoten, auch nicht bei exaktem Namens- und Domänen-Match. Eine Bindung erfolgt ausschließlich über eine explizite, versionierte, protokollierte Rekonziliationsregel. Sichtbare Dubletten sind einer stillen Fehlverschmelzung vorzuziehen. Kein erfundener SID.
|
|
|
|
```
|
|
asset_property (1:N) finding-abgeleitete Knoten-Eigenschaften
|
|
────────────────────────────────
|
|
id uuid PK
|
|
canonical_asset_id uuid FK NN IX
|
|
property_key text NN IX z. B. kerberoastable, asrep_roastable, unconstrained_delegation
|
|
property_value text
|
|
source_result_id uuid FK Finding, aus dem die Eigenschaft stammt
|
|
mapping_rule_version text
|
|
```
|
|
|
|
Fähigkeiten eines Knotens (Kerberoastable, AS-REP-Roastable, Unconstrained Delegation) sind Eigenschaften, keine Kanten. Die Zuordnung Finding zu Eigenschaft läuft über eine versionierte Regel.
|
|
|
|
### ASSET_EDGE
|
|
|
|
Kanten sind erste Klasse, getrennt von Findings. Gerichtet, mit Pflicht-Provenienz.
|
|
|
|
```
|
|
asset_edge
|
|
────────────────────────────────
|
|
id uuid PK
|
|
assessment_id uuid FK NN IX
|
|
source_asset_id uuid FK NN IX
|
|
target_asset_id uuid FK NN IX
|
|
edge_type enum edge_type NN IX
|
|
direction text NN gerichtet: source -> target
|
|
edge_source text NN Tool + Import-Artefakt
|
|
collection_method text NN
|
|
collector_version text NN
|
|
source_locator text
|
|
mapping_method text
|
|
mapping_rule_version text
|
|
confidence numeric
|
|
first_seen_at timestamptz NN
|
|
last_seen_at timestamptz NN
|
|
properties jsonb
|
|
original_fields jsonb
|
|
```
|
|
|
|
`edge_source`, `collection_method`, `collector_version` sind verpflichtend. Sie ermöglichen die ehrliche Abdeckungsdeklaration.
|
|
|
|
Kantentyp-Katalog (Stufe A aus dem Bestand erhebbar, Stufe B noch nicht in den Quellen):
|
|
|
|
```
|
|
Stufe A MemberOf, Trusts, AllowedToDelegate, AllowedToActOnBehalfOf,
|
|
GpLink, Contains, GPO-DACL
|
|
Stufe B HasSession, AdminTo, CanRDP, CanPSRemote, ExecuteDCOM, Objekt-DACL
|
|
```
|
|
|
|
### EDGE_COVERAGE
|
|
|
|
Macht ehrlich sichtbar, welche Kantentypen erhoben wurden. Grundlage jeder korrekten Blast-Radius-Aussage.
|
|
|
|
```
|
|
edge_coverage
|
|
────────────────────────────────
|
|
id uuid PK
|
|
assessment_id uuid FK NN IX
|
|
scan_run_id uuid FK IX
|
|
edge_type enum edge_type NN
|
|
edge_source text
|
|
collected boolean NN
|
|
collector_version text
|
|
```
|
|
|
|
Jede Erreichbarkeits- oder Blast-Radius-Berechnung läuft über einen deklarierten Kantentyp-Filter und liefert `computed_over_edge_types` und `uncollected_edge_types` (Katalog minus erhoben) mit. Ein Blast Radius über eine unvollständige Kantenmenge unterschätzt die reale Erreichbarkeit und darf nie als vollständig dargestellt werden.
|
|
|
|
## Enum-Katalog
|
|
|
|
```
|
|
result_type exposure_finding | compliance_check | policy_deviation | informational | unknown
|
|
result_state fail | pass | warning | error | not_applicable | not_evaluated | informational | unknown
|
|
severity critical | high | medium | low | info | unknown
|
|
exposure_state detected | not_detected | not_evaluated | execution_error | unknown
|
|
xccdf_result pass | fail | error | unknown | notapplicable | notchecked | notselected | informational | fixed
|
|
verdict match | deviation | missing_on_subject | extra_on_subject | not_comparable
|
|
lifecycle_state new | persistent | resolved | reoccurred | changed | not_comparable | unknown
|
|
review_status open | in_review | accepted | remediated | risk_accepted | false_positive | unknown
|
|
asset_type user | group | computer | domain_controller | domain | ou | gpo | trust | tenant | service_principal | unknown
|
|
asset_key_kind sid | object_guid | gpo_guid | domain_sid | trust_key | synthetic
|
|
edge_type MemberOf | Trusts | AllowedToDelegate | AllowedToActOnBehalfOf | GpLink | Contains
|
|
| GPO-DACL | HasSession | AdminTo | CanRDP | CanPSRemote | ExecuteDCOM | ObjectDACL
|
|
evidence_type table | table_row | object | property | text | configuration | command_output
|
|
| policy_observation | reference | screenshot_reference | unknown
|
|
source_tool purple-knight | pingcastle | maester | cis-cat | gpo-analysis | unknown
|
|
source_format html | xml | json | xccdf | arf | gpo_backup | unknown
|
|
```
|
|
|
|
Enums sind geschlossen und versioniert. Keine Quelle führt Ad-hoc-Werte ein; unklassifizierbares fällt auf `unknown` zurück.
|
|
|
|
## Filteroberfläche
|
|
|
|
Die folgenden Spalten sind indiziert und bilden die vollständige toolübergreifende Filterebene. Kein Filter erfordert einen Join in einen typspezifischen Block oder JSONB.
|
|
|
|
```
|
|
canonical_result.result_type
|
|
canonical_result.result_state
|
|
canonical_result.is_ioe
|
|
canonical_result.severity_normalized
|
|
canonical_result.source_tool
|
|
canonical_result.lifecycle_state
|
|
canonical_result.primary_category_namespace
|
|
canonical_result.primary_category_label
|
|
canonical_result.evidence_count
|
|
result_category.namespace / label (fuer Mehrfachkategorien)
|
|
result_review.review_status
|
|
```
|
|
|
|
Typspezifische Verfeinerung über einen bewussten Join:
|
|
|
|
```
|
|
result_exposure.exposure_state nur exposure_finding
|
|
result_compliance.xccdf_result nur compliance_check
|
|
result_deviation.verdict nur policy_deviation
|
|
```
|
|
|
|
Beispiel-Abfragen:
|
|
|
|
```
|
|
IOE, tooluebergreifend
|
|
WHERE is_ioe = true
|
|
|
|
High-IOEs, tooluebergreifend
|
|
WHERE is_ioe = true AND severity_normalized = 'high'
|
|
|
|
Alle CIS-Haertungsluecken
|
|
WHERE result_type = 'compliance_check' AND result_state = 'fail'
|
|
|
|
Alle Policy-Abweichungen
|
|
WHERE result_type = 'policy_deviation' AND verdict = 'deviation'
|
|
|
|
Alle Fails, tooluebergreifend, unabhaengig vom Typ
|
|
WHERE result_state = 'fail'
|
|
|
|
Nur PingCastle-IOEs
|
|
WHERE is_ioe = true AND source_tool = 'pingcastle'
|
|
|
|
Findings mit strukturierter Evidenz
|
|
WHERE evidence_count > 0
|
|
```
|
|
|
|
## Determinismus- und Provenance-Regeln
|
|
|
|
```
|
|
1. result_type ist geschlossen und versioniert. Keine Ad-hoc-Typen.
|
|
2. result_state wird abgeleitet, nie roh aus Quell-String oder Spaltenname uebernommen.
|
|
3. is_ioe wird per expliziter, versionierter Regel abgeleitet und materialisiert;
|
|
nie aus der Quelle uebernommen; nie fuer compliance_check oder policy_deviation per Default true.
|
|
4. Nativwerte bleiben parallel vollstaendig erhalten (typspezifischer Block plus original_fields).
|
|
5. Jede Ableitung traegt mapping_method und mapping_rule_version.
|
|
6. Severity nur aus nativem Wert oder versionierter, freigegebener Mappingregel.
|
|
Kategorie wird nie in Severity umgedeutet. Sonst severity_normalized = unknown.
|
|
7. score ist tooluebergreifend nicht vergleichbar und darf typuebergreifend nicht
|
|
sortiert oder schwellwertgefiltert werden.
|
|
8. Fehlend ist NULL bzw. unknown, nie erfunden.
|
|
9. Mehrwertige Daten (Kategorien, Assets, Evidenz, Referenzen, Schritte) nie als
|
|
kommaseparierter String; immer relationale Kindtabelle.
|
|
10. Knotenidentitaet nur ueber autoritativen Schluessel; Name fuehrt nie zu Merge.
|
|
11. synthetic-Knoten verschmelzen nie automatisch mit autoritativen Knoten.
|
|
12. Kanten sind erste Klasse; jede Kante traegt edge_source, collection_method, collector_version.
|
|
13. Erreichbarkeit nur ueber deklarierten Kantentyp-Filter; Ergebnis nennt uncollected_edge_types.
|
|
14. Finding zu Graph-Rolle (Eigenschaft, Kante, Overlay) nur ueber versionierte Regel.
|
|
15. Filterrelevante Werte liegen als indizierte Spalten vor, nie ausschliesslich in JSONB.
|
|
```
|
|
|
|
## Konsumierbare API-Projektion
|
|
|
|
Konsumenten (UI, LLM, Export) erhalten nicht das rohe Schema, sondern eine versionierte Projektion. Damit bleibt das interne Schema erweiterbar, ohne Konsumenten zu brechen.
|
|
|
|
```
|
|
GET /api/v1/results
|
|
GET /api/v1/results/{id}
|
|
GET /api/v1/results/{id}/evidence
|
|
GET /api/v1/results/schema
|
|
GET /api/v1/assets
|
|
GET /api/v1/edges
|
|
```
|
|
|
|
Die UI rendert ausschließlich gelieferte Facetten und Resultwerte. Keine toolabhängige Sonderlogik im Client.
|
|
|
|
## Bewusst deferiert
|
|
|
|
```
|
|
- GPO-/Baseline-Vergleichs-Submodell: Setting-Identitaet pro Namespace, Verdikt-Logik,
|
|
"nicht konfiguriert" vs. "abwesend", Baseline-Registry. Der result_deviation-Block ist
|
|
strukturell bereits vorhanden.
|
|
- CIS-CAT-Adapter: XCCDF/ARF vs. JSON nach Verifikation der Lizenzausgabe.
|
|
- Elevationsregeln, die einzelne Compliance-/Policy-Befunde auf is_ioe = true heben.
|
|
- Rekonziliationsregeln fuer synthetic-Knoten.
|
|
- Stufe-B-Kanten (Session, AdminTo, DACL) aus BloodHound-/SharpHound-Klasse-Quellen.
|
|
- Mandanten-/Isolationsmodell ueber project_id hinaus.
|
|
- Physisches DDL: aus diesem Modell mechanisch ableitbar (Typen, Indizes, Constraints
|
|
sind bereits annotiert).
|
|
```
|
|
|
|
## Changelog
|
|
|
|
```
|
|
1.0.0 Erstfassung des konsolidierten Modells. Vereint das kanonische Result-Modell
|
|
(Haupttabelle, Kindtabellen, Provenance, Lifecycle) mit RESULT_CONTRACT 1.0.0
|
|
(result_type-Achsen, is_ioe als abgeleitete Facette, typspezifische Bloecke)
|
|
und der Asset-/Edge-Graphschicht. Filteroberfläche als indizierte Spaltenmenge
|
|
definiert. Implementierungsreif bis auf das deferierte GPO-Submodell.
|
|
```
|