Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update RBA API Output #379

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -435,12 +435,8 @@ def serialize_model(self):
"datamodel": self.datamodel,
"source": self.source,
"nes_fields": self.nes_fields,
"rba": self.rba,
}
if self.rba is not None:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are encoded in individual risk_objects, I do not believe they should be included at a high-level for the entire RBA section anymore.

model["risk_severity"] = self.rba.severity
model["tags"]["risk_score"] = self.rba.risk_score
else:
model["tags"]["risk_score"] = 0

# Only a subset of macro fields are required:
all_macros: list[dict[str, str | list[str]]] = []
Expand Down
39 changes: 25 additions & 14 deletions contentctl/objects/rba.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@
RiskScoreValue_Type = Annotated[int, Field(ge=1, le=100)]


def risk_score_to_severity(num: int) -> RiskSeverity:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If risk_severity needs to exist both for individual risk_objects AND at a high level for the entire RBA section, then this should be broken out here so it can be re-used.
It is also used in the savedsearches.conf dump logic here:

action.notable.param.severity = {{ detection.rba.severity }}

Is this a required field that MUST still be present in savedsearches.conf?

if 0 <= num <= 20:
return RiskSeverity.INFORMATIONAL
elif 20 < num <= 40:
return RiskSeverity.LOW
elif 40 < num <= 60:
return RiskSeverity.MEDIUM
elif 60 < num <= 80:
return RiskSeverity.HIGH
elif 80 < num <= 100:
return RiskSeverity.CRITICAL
else:
raise Exception(
f"Error getting severity - risk_score must be between 0-100, but was actually {num}"
)


class RiskObjectType(str, Enum):
SYSTEM = "system"
USER = "user"
Expand Down Expand Up @@ -62,6 +79,11 @@ def __lt__(self, other: RiskObject) -> bool:
return True
return False

@computed_field
@property
def severity(self) -> RiskSeverity:
return risk_score_to_severity(self.score)

@model_serializer
def serialize_risk_object(self) -> dict[str, str | int]:
"""
Expand All @@ -74,6 +96,7 @@ def serialize_risk_object(self) -> dict[str, str | int]:
"risk_object_field": self.field,
"risk_object_type": self.type,
"risk_score": self.score,
"severity": self.severity,
}


Expand Down Expand Up @@ -123,25 +146,13 @@ def risk_score(self) -> RiskScoreValue_Type:
@computed_field
@property
def severity(self) -> RiskSeverity:
if 0 <= self.risk_score <= 20:
return RiskSeverity.INFORMATIONAL
elif 20 < self.risk_score <= 40:
return RiskSeverity.LOW
elif 40 < self.risk_score <= 60:
return RiskSeverity.MEDIUM
elif 60 < self.risk_score <= 80:
return RiskSeverity.HIGH
elif 80 < self.risk_score <= 100:
return RiskSeverity.CRITICAL
else:
raise Exception(
f"Error getting severity - risk_score must be between 0-100, but was actually {self.risk_score}"
)
return risk_score_to_severity(self.risk_score)

@model_serializer
def serialize_rba(self) -> dict[str, str | list[dict[str, str | int]]]:
return {
"message": self.message,
"risk_objects": [obj.model_dump() for obj in sorted(self.risk_objects)],
"threat_objects": [obj.model_dump() for obj in sorted(self.threat_objects)],
"severity": self.severity,
}
8 changes: 5 additions & 3 deletions contentctl/output/api_json_output.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from contentctl.objects.baseline import Baseline
from contentctl.objects.deployment import Deployment
from contentctl.objects.detection import Detection
from contentctl.objects.investigation import Investigation
from contentctl.objects.lookup import Lookup
from contentctl.objects.macro import Macro
from contentctl.objects.story import Story
from contentctl.objects.baseline import Baseline
from contentctl.objects.investigation import Investigation
from contentctl.objects.deployment import Deployment

import os
import pathlib
Expand Down Expand Up @@ -39,6 +40,7 @@ def writeDetections(
"id",
"description",
"tags",
"rba",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure that the RBA field is written when a detection is dumped to JSON.

"search",
"how_to_implement",
"known_false_positives",
Expand Down
Loading