Skip to content

Commit

Permalink
Merge pull request #1 from frack113/Update_dependencies
Browse files Browse the repository at this point in the history
Update poetry dependencies
  • Loading branch information
thomaspatzke authored Oct 3, 2024
2 parents 477b16d + b069562 commit 3d8d828
Show file tree
Hide file tree
Showing 9 changed files with 726 additions and 584 deletions.
1,145 changes: 640 additions & 505 deletions poetry.lock

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions print-coverage.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Prints code testing coverage as percentage for badge generation.
import xml.etree.ElementTree as et

tree = et.parse("cov.xml")
root = tree.getroot()
coverage = float(root.attrib["line-rate"]) * 100
print(f"COVERAGE={coverage:3.4}%")
if coverage >= 95.0:
print("COVERAGE_COLOR=green")
elif coverage >= 90.0:
print("COVERAGE_COLOR=yellow")
elif coverage >= 85.0:
print("COVERAGE_COLOR=orange")
else:
print("COVERAGE_COLOR=red")
# Prints code testing coverage as percentage for badge generation.
from defusedxml.ElementTree import parse

tree = parse("cov.xml")
root = tree.getroot()
coverage = float(root.attrib["line-rate"]) * 100
print(f"COVERAGE={coverage:3.4}%")
if coverage >= 95.0:
print("COVERAGE_COLOR=green")
elif coverage >= 90.0:
print("COVERAGE_COLOR=yellow")
elif coverage >= 85.0:
print("COVERAGE_COLOR=orange")
else:
print("COVERAGE_COLOR=red")
14 changes: 8 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pySigma-backend-datadog"
version = "0.1.0"
version = "0.1.1"
description = "pySigma Datadog backend"
readme = "README.md"
authors = ["Datadog Cloud SIEM <[email protected]>"]
Expand All @@ -12,16 +12,18 @@ packages = [

[tool.poetry.dependencies]
python = "^3.8"
pysigma = "^0.10.3"
pysigma = "^0.11"

[tool.poetry.dev-dependencies]
black = "^24.1"
defusedxml = "^0.7"

[tool.poetry.group.dev.dependencies]
pytest = "^7.3.1"
pytest-cov = "^4.0.0"
coverage = "^7.2.5"
coverage = "^7.4"
pytest = "^8.0"
pytest-cov = "^4.1"

[build-system]
requires = ["poetry-core>=1.0.0"]
requires = ["poetry-core>=1.8.1"]
build-backend = "poetry.core.masonry.api"

2 changes: 1 addition & 1 deletion scripts/local_pysigma_dd_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# Add the path to the rule that should be converted to the following list:
sigma_rules_to_convert = [
r"/Users/{your.username}/sigma/sigma/rules/{path/to/rule/to/be/converted}",
r"/Users/{your.username}/sigma/sigma/rules/cloud/azure/azure_blocked_account_attempt.yml", # example rule path
r"/Users/{your.username}/sigma/sigma/rules/cloud/azure/azure_blocked_account_attempt.yml", # example rule path
]

sigma_rule_collection = SigmaCollection.load_ruleset(sigma_rules_to_convert)
Expand Down
2 changes: 1 addition & 1 deletion sigma/backends/datadog/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .datadog import DatadogBackend
from .datadog import DatadogBackend
107 changes: 53 additions & 54 deletions sigma/backends/datadog/datadog.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,56 +35,56 @@ class DatadogBackend(TextQueryBackend):
ConditionAND,
ConditionOR,
)
group_expression: ClassVar[
str
] = "({expr})" # Expression for precedence override grouping as format string with {expr} placeholder
group_expression: ClassVar[str] = (
"({expr})" # Expression for precedence override grouping as format string with {expr} placeholder
)
parenthesize: bool = True

# Generated query tokens
token_separator: str = " " # separator inserted between all boolean operators
or_token: ClassVar[str] = "OR"
and_token: ClassVar[str] = "AND"
not_token: ClassVar[str] = "NOT"
eq_token: ClassVar[
str
] = ":" # Token inserted between field and value (without separator)
eq_token: ClassVar[str] = (
":" # Token inserted between field and value (without separator)
)

# String Output Fields Quoting
# field_quote : ClassVar[str] = "'" # Character used to quote field characters if field_quote_pattern matches (or not, depending on field_quote_pattern_negation). No field name quoting is done if not set.
field_quote_pattern: ClassVar[Pattern] = re.compile(
"^\\w+$"
) # Quote field names if this pattern (doesn't) matches, depending on field_quote_pattern_negation. Field name is always quoted if pattern is not set.
field_quote_pattern_negation: ClassVar[
bool
] = True # Negate field_quote_pattern result. Field name is quoted if pattern doesn't matches if set to True (default).
field_quote_pattern_negation: ClassVar[bool] = (
True # Negate field_quote_pattern result. Field name is quoted if pattern doesn't matches if set to True (default).
)

### Escaping
field_escape: ClassVar[
str
] = "\\" # Character to escape particular parts defined in field_escape_pattern.
field_escape_quote: ClassVar[
bool
] = True # Escape quote string defined in field_quote
field_escape: ClassVar[str] = (
"\\" # Character to escape particular parts defined in field_escape_pattern.
)
field_escape_quote: ClassVar[bool] = (
True # Escape quote string defined in field_quote
)

field_escape_pattern: ClassVar[Pattern] = re.compile(
"[\\s*]"
) # All matches of this pattern are prepended with the string contained in field_escape.

## Values
escape_char: ClassVar[
str
] = "\\" # Escaping character for special characters inside string
escape_char: ClassVar[str] = (
"\\" # Escaping character for special characters inside string
)
wildcard_multi: ClassVar[str] = "*" # Character used as multi-character wildcard
wildcard_single: ClassVar[str] = "*" # Character used as single-character wildcard
add_escaped: ClassVar[
str
] = ' + - = && || ! ( ) { } [ ] < > ^ “ ” ~ * ? : " ' # Characters quoted in addition to wildcards and string quote
bool_values: ClassVar[
Dict[bool, str]
] = { # Values to which boolean values are mapped.
True: "true",
False: "false",
}
add_escaped: ClassVar[str] = (
' + - = && || ! ( ) { } [ ] < > ^ “ ” ~ * ? : " ' # Characters quoted in addition to wildcards and string quote
)
bool_values: ClassVar[Dict[bool, str]] = (
{ # Values to which boolean values are mapped.
True: "true",
False: "false",
}
)

# String matching operators. if none is appropriate eq_token is used.
startswith_expression: ClassVar[str] = "{field}:{value}*"
Expand All @@ -93,9 +93,9 @@ class DatadogBackend(TextQueryBackend):
icontains_token: ClassVar[str] = "{field}:*{value}*"

# Numeric comparison operators
compare_op_expression: ClassVar[
str
] = "{field}:{operator}{value}" # Compare operation query as format string with placeholders {field}, {operator} and {value}
compare_op_expression: ClassVar[str] = (
"{field}:{operator}{value}" # Compare operation query as format string with placeholders {field}, {operator} and {value}
)
# Mapping between CompareOperators elements and strings used as replacement for {operator} in compare_op_expression
compare_operators: ClassVar[Dict[SigmaCompareExpression.CompareOperators, str]] = {
SigmaCompareExpression.CompareOperators.GT: ">",
Expand All @@ -105,39 +105,39 @@ class DatadogBackend(TextQueryBackend):
}

# Expression for comparing two event fields
field_equals_field_expression: ClassVar[
Optional[str]
] = None # Field comparison expression with the placeholders {field1} and {field2} corresponding to left field and right value side of Sigma detection item
field_equals_field_expression: ClassVar[Optional[str]] = (
None # Field comparison expression with the placeholders {field1} and {field2} corresponding to left field and right value side of Sigma detection item
)
field_equals_field_escaping_quoting: Tuple[bool, bool] = (
True,
True,
) # If regular field-escaping/quoting is applied to field1 and field2. A custom escaping/quoting can be implemented in the convert_condition_field_eq_field_escape_and_quote method.

# Field existence condition expressions.
field_exists_expression: ClassVar[
str
] = "({field})" # Expression for field existence as format string with {field} placeholder for field name
field_not_exists_expression: ClassVar[
str
] = "NOT ({field})" # Expression for field non-existence as format string with {field} placeholder for field name. If not set, field_exists_expression is negated with boolean NOT.
field_exists_expression: ClassVar[str] = (
"({field})" # Expression for field existence as format string with {field} placeholder for field name
)
field_not_exists_expression: ClassVar[str] = (
"NOT ({field})" # Expression for field non-existence as format string with {field} placeholder for field name. If not set, field_exists_expression is negated with boolean NOT.
)

# Field value in list, e.g. "field in (value list)" or "field contains all (value list)"
# Convert OR as in-expression
convert_and_as_in: ClassVar[bool] = False # Convert AND as in-expression
field_in_list_expression: ClassVar[
str
] = "{field}{op}({list})" # Expression for field in list of values as format string with placeholders {field}, {op} and {list}
field_in_list_expression: ClassVar[str] = (
"{field}{op}({list})" # Expression for field in list of values as format string with placeholders {field}, {op} and {list}
)

# and_in_operator : ClassVar[str] = "contains-all" # Operator used to convert AND into in-expressions. Must be set if convert_and_as_in is set
list_separator: ClassVar[str] = " OR " # List element separator

# Value not bound to a field
unbound_value_str_expression: ClassVar[
str
] = '"{value}"' # Expression for string value not bound to a field as format string with placeholder {value}
unbound_value_num_expression: ClassVar[
str
] = "{value}" # Expression for number value not bound to a field as format string with placeholder {value}
unbound_value_str_expression: ClassVar[str] = (
'"{value}"' # Expression for string value not bound to a field as format string with placeholder {value}
)
unbound_value_num_expression: ClassVar[str] = (
"{value}" # Expression for number value not bound to a field as format string with placeholder {value}
)

def convert_condition_field_eq_val_re(
self, cond: SigmaRegularExpression, state: Any
Expand Down Expand Up @@ -200,9 +200,11 @@ def finalize_query_siem_rule(
"cases": [
{
"name": "",
"status": str(rule.level.name).lower()
if rule.level is not None
else "low",
"status": (
str(rule.level.name).lower()
if rule.level is not None
else "low"
),
"condition": "a > 0",
"notifications": [],
}
Expand All @@ -217,7 +219,6 @@ def finalize_query_siem_rule(
"message": f"Sigma Rule ID: \n {str(rule.id)} \n "
f"False Positives: \n {self.concat_false_positive_as_string(rule.falsepositives)} \n "
f"Description: \n {str(rule.description)} \n "

f"Author: \n {str(rule.author) if rule.author is not None else []} \n ",
"tags": ["source:sigmahq"]
+ [f"{tag.namespace}:{tag.name}" for tag in rule.tags],
Expand All @@ -227,5 +228,3 @@ def finalize_query_siem_rule(

def finalize_output_siem_rule(self, queries: List[Dict]) -> List[Dict]:
return list(queries)


2 changes: 1 addition & 1 deletion sigma/pipelines/datadog/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .datadog import datadog_pipeline
from .datadog import datadog_pipeline
2 changes: 2 additions & 0 deletions sigma/pipelines/datadog/datadog.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from sigma.rule import SigmaRule

import sigma


class AggregateRuleProcessingCondition(RuleProcessingCondition):
def match(
self, pipeline: "sigma.processing.pipeline.ProcessingPipeline", rule: SigmaRule
Expand Down
6 changes: 5 additions & 1 deletion tests/test_pipelines_datadog.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# pylint: disable=too-many-lines
import pytest
from sigma.collection import SigmaCollection
from sigma.exceptions import SigmaTransformationError, SigmaFeatureNotSupportedByBackendError
from sigma.exceptions import (
SigmaTransformationError,
SigmaFeatureNotSupportedByBackendError,
)


from sigma.backends.datadog import DatadogBackend


def test_aws_field_transformations():
assert (
DatadogBackend().convert(
Expand Down

0 comments on commit 3d8d828

Please sign in to comment.