Tester: the port-based exposure score put nearly every Windows host at 100 (no separation), and the thing that actually matters — whether a host runs a crown-jewel role enabling lateral movement / domain takeover — wasn't captured. - Migration 034 + model: assets.high_value_score (0-100) + risk_dimensions (JSON roles) + _updated_at. - app/services/risk_dimensions_service.py: detect_risk_dimensions(ports, packages) → roles from syscollector ports (port + process) and installed packages: Domain Controller, ADCS/CA, backup servers, SW-distribution, Exchange, WSUS, MSSQL, DNS, DHCP, WinRM. Score = max(weight) + 0.3·rest (cap 100). risk_factor() maps it to a URS band (>=90→1.5 … else 1.0). - exposure_service: rebalanced port weights — baseline Windows (SMB/MSRPC/NetBIOS/WinRM) now LOW; real remote-control/cleartext exposures (Telnet/VNC/RDP/FTP) stay HIGH. Risk detection runs in the same pass (reuses fetched ports + one get_packages call). - urs_service: URS uses max(operator criticality factor, role factor) — a DC/ADCS host rises to critical weighting even at criticality=normal; operator can still set higher. criticality field untouched. - assets API: high_value_score + risk_dimensions in the response + sortable; Assets page gets a "Risk" column with score + role badges. Verified detection: DC(88+389)→100, SQL pkg+WinRM→79, plain Win→0, Exchange+Veeam→100. Migration 034 required: alembic upgrade head. Roles need Wazuh syscollector (ports+packages); Nessus/Intune-only → v2.
44 lines
1.3 KiB
Python
44 lines
1.3 KiB
Python
"""Add asset risk-dimension (high-value-target) columns
|
|
|
|
Revision ID: 034
|
|
Revises: 033
|
|
Create Date: 2026-06-16 09:00:00.000000
|
|
|
|
"Risk Dimensions": crown-jewel role detection (Domain Controller, ADCS,
|
|
SQL, Exchange, WSUS, backup, ...) computed alongside network exposure and
|
|
fed into the URS. Stores a 0-100 high_value_score + the detected roles.
|
|
|
|
Idempotent — ADD COLUMN IF NOT EXISTS.
|
|
"""
|
|
from alembic import op
|
|
|
|
|
|
revision = "034"
|
|
down_revision = "033"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.execute("""
|
|
ALTER TABLE assets
|
|
ADD COLUMN IF NOT EXISTS high_value_score DOUBLE PRECISION,
|
|
ADD COLUMN IF NOT EXISTS risk_dimensions TEXT,
|
|
ADD COLUMN IF NOT EXISTS risk_dimensions_updated_at TIMESTAMP;
|
|
""")
|
|
op.execute("""
|
|
CREATE INDEX IF NOT EXISTS ix_assets_high_value_score
|
|
ON assets (high_value_score)
|
|
WHERE high_value_score > 0;
|
|
""")
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.execute("DROP INDEX IF EXISTS ix_assets_high_value_score;")
|
|
op.execute("""
|
|
ALTER TABLE assets
|
|
DROP COLUMN IF EXISTS high_value_score,
|
|
DROP COLUMN IF EXISTS risk_dimensions,
|
|
DROP COLUMN IF EXISTS risk_dimensions_updated_at;
|
|
""")
|