Skip to content

Commit c002a1e

Browse files
committed
chore: added integration test
1 parent 43268b6 commit c002a1e

2 files changed

Lines changed: 113 additions & 0 deletions

File tree

src/secops/cli/commands/parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ def setup_parser_command(subparsers):
225225
)
226226
run_parser_sub.add_argument(
227227
"--parse-statedump",
228+
"--parse_statedump",
228229
action="store_true",
229230
help=("Parse statedump results into readable format"),
230231
)

tests/cli/test_integration.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,118 @@ def test_cli_parser_run_error_cases(cli_env, common_args):
748748
os.unlink(parser_file)
749749

750750

751+
@pytest.mark.integration
752+
def test_cli_parser_run_evaluation_with_parsed_statedump(cli_env, common_args):
753+
"""
754+
Test the 'parser run' command functionality with parsed statedump, covering
755+
reading parser code and logs from files, and providing logs via multiple
756+
--log arguments.
757+
"""
758+
test_log_type = f"RESERVED_LOG_TYPE_1"
759+
760+
# Sample YARA-L parser code
761+
sample_parser_code = r"""
762+
filter {
763+
mutate {
764+
replace => {
765+
"event1.idm.read_only_udm.metadata.event_type" => "GENERIC_EVENT"
766+
"event1.idm.read_only_udm.metadata.vendor_name" => "ACME Labs"
767+
}
768+
}
769+
grok {
770+
match => {
771+
"message" => ["^(?P<_firstWord>[^\s]+)\s.*$"]
772+
}
773+
on_error => "_grok_message_failed"
774+
}
775+
if ![_grok_message_failed] {
776+
mutate {
777+
replace => {
778+
"event1.idm.read_only_udm.metadata.description" => "%{_firstWord}"
779+
}
780+
}
781+
}
782+
mutate {
783+
merge => {
784+
"@output" => "event1"
785+
}
786+
}
787+
statedump{}
788+
}
789+
"""
790+
791+
# Sample log data for --logs-file
792+
sample_logs_file_content = """
793+
{"appDisplayName":"Azure Active Directory PowerShell","appId":"1b730912-1644-4b74-9bfd-dac224a7b894","appliedConditionalAccessPolicies":[],"clientAppUsed":"Mobile Apps and Desktop clients","conditionalAccessStatus":"success","correlationId":"8bdadb11-5851-4ff2-ad57-799c0149f606","createdDateTime":"2025-06-15T04:31:56Z","deviceDetail":{"browser":"Rich Client 5.2.8.0","deviceId":"","displayName":"","isCompliant":false,"isManaged":false,"operatingSystem":"Windows 8","trustType":""},"id":"ba6e48d0-85e9-45b0-9ce4-83eb83432200","ipAddress":"79.116.213.193","isInteractive":true,"location":{"city":"Madrid","countryOrRegion":"ES","geoCoordinates":{"altitude":null,"latitude":40.416,"longitude":-3.703},"state":"Madrid"},"resourceDisplayName":"Windows Azure Active Directory","resourceId":"00000001-0000-0000-d000-000000000000","riskDetail":"none","riskEventTypes":[],"riskEventTypes_v2":[],"riskLevelAggregated":"none","riskLevelDuringSignIn":"none","riskState":"none","status":{"additionalDetails":null,"errorCode":0,"failureReason":"Other."},"userDisplayName":"Admin Read Only","userId":"6838ec00-f384-40d8-b288-989103aed42b","userPrincipalName":"reports@example.onmicrosoft.com"}
794+
"""
795+
796+
parser_code_file_path = None
797+
logs_file_path = None
798+
799+
try:
800+
# Create temporary parser code file
801+
with tempfile.NamedTemporaryFile(
802+
suffix=".yara", mode="w+", delete=False
803+
) as temp_file:
804+
temp_file.write(sample_parser_code)
805+
parser_code_file_path = temp_file.name
806+
807+
# Create temporary logs file
808+
with tempfile.NamedTemporaryFile(
809+
suffix=".log", mode="w+", delete=False
810+
) as temp_file:
811+
temp_file.write(sample_logs_file_content)
812+
logs_file_path = temp_file.name
813+
814+
# --- Scenario 1: Using --parser-code-file and --logs-file ---
815+
run_cmd_file_input = (
816+
[
817+
"secops", # Replace with your actual CLI entry point
818+
]
819+
+ common_args
820+
+ [
821+
"parser",
822+
"run",
823+
"--log-type",
824+
test_log_type,
825+
"--parser-code-file",
826+
parser_code_file_path,
827+
"--logs-file",
828+
logs_file_path,
829+
"--statedump-allowed",
830+
"--parse_statedump",
831+
]
832+
)
833+
834+
run_result_file_input = subprocess.run(
835+
run_cmd_file_input, env=cli_env, capture_output=True, text=True
836+
)
837+
838+
# Assert CLI command execution success
839+
assert run_result_file_input.returncode == 0, (
840+
"Parser run with files failed: "
841+
f"{run_result_file_input.stderr}\n{run_result_file_input.stdout}"
842+
)
843+
844+
# Parse and assert the output
845+
run_output_file_input = json.loads(run_result_file_input.stdout)
846+
assert "parsedEvents" in run_output_file_input["runParserResults"][0]
847+
848+
statedump_results = run_output_file_input["runParserResults"][0].get(
849+
"statedumpResults"
850+
)
851+
assert len(statedump_results)
852+
assert statedump_results[0].get("statedumpResult")
853+
assert statedump_results[0].get("statedumpResult").get("state")
854+
855+
finally:
856+
# Clean up temporary files regardless of test outcome
857+
if parser_code_file_path and os.path.exists(parser_code_file_path):
858+
os.unlink(parser_code_file_path)
859+
if logs_file_path and os.path.exists(logs_file_path):
860+
os.unlink(logs_file_path)
861+
862+
751863
@pytest.mark.integration
752864
def test_cli_rule_list(cli_env, common_args):
753865
"""Test the rule list command."""

0 commit comments

Comments
 (0)