From 3e212e2b745ea22699a4f235ef7efe5b1b606034 Mon Sep 17 00:00:00 2001 From: Terrance DeJesus <99630311+terrancedejesus@users.noreply.github.com> Date: Thu, 12 Oct 2023 10:51:12 -0400 Subject: [PATCH] [FR] Add ML Jobs to Schemas and Unit Test for Validation (#3161) * adding machine learning job id validation * Update rules/ml/credential_access_ml_auth_spike_in_logon_events_from_a_source_ip.toml * Update tests/test_all_rules.py * adding integration manifests and schemas from main * rebuilt manifests and schemas with lmd * fixed unit test linting * adding manifests and schemas for other analytic packages * updated manifests and schemas; adjusted unit test for verbosity * sorted imports --- .../etc/integration-manifests.json.gz | Bin 7684 -> 8113 bytes .../etc/integration-schemas.json.gz | Bin 2622511 -> 2623052 bytes detection_rules/integrations.py | 14 ++++- tests/test_all_rules.py | 55 ++++++++++++++++-- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/detection_rules/etc/integration-manifests.json.gz b/detection_rules/etc/integration-manifests.json.gz index d7f09bdfc50b23605b29f8336a31105d265539e7..9529c165b233ca1de3d9492479cb886faa5b66e1 100644 GIT binary patch literal 8113 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

nQx^XH0=J({di;z4B8Iad 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 P{`~&~=USiy%3o6g>cuum delta 16137 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 diff --git a/detection_rules/integrations.py b/detection_rules/integrations.py index faa305175..2c264d051 100644 --- a/detection_rules/integrations.py +++ b/detection_rules/integrations.py @@ -23,6 +23,7 @@ from . import ecs from .beats import flatten_ecs_schema from .misc import load_current_package_version from .utils import cached, get_etc_path, read_gzip, unzip +from .schemas import definitions MANIFEST_FILE_PATH = Path(get_etc_path('integration-manifests.json.gz')) SCHEMA_FILE_PATH = Path(get_etc_path('integration-schemas.json.gz')) @@ -137,12 +138,12 @@ def build_integrations_schemas(overwrite: bool, integration: str = None) -> None # Open the zip file with unzip(response.content) as zip_ref: for file in zip_ref.namelist(): + file_data_bytes = zip_ref.read(file) # Check if the file is a match if glob.fnmatch.fnmatch(file, '*/fields/*.yml'): integration_name = Path(file).parent.parent.name final_integration_schemas[package][version].setdefault(integration_name, {}) - file_data = zip_ref.read(file) - schema_fields = yaml.safe_load(file_data) + schema_fields = yaml.safe_load(file_data_bytes) # Parse the schema and add to the integration_manifests data = flatten_ecs_schema(schema_fields) @@ -150,7 +151,14 @@ def build_integrations_schemas(overwrite: bool, integration: str = None) -> None final_integration_schemas[package][version][integration_name].update(flat_data) - del file_data + # add machine learning jobs to the schema + if integration in list(map(str.lower, definitions.MACHINE_LEARNING_PACKAGES)): + if glob.fnmatch.fnmatch(file, '*/ml_module/*ml.json'): + ml_module = json.loads(file_data_bytes) + job_ids = [job['id'] for job in ml_module['attributes']['jobs']] + final_integration_schemas[package][version]['jobs'] = job_ids + + del file_data_bytes # Write the final integration schemas to disk with gzip.open(SCHEMA_FILE_PATH, "w") as schema_file: diff --git a/tests/test_all_rules.py b/tests/test_all_rules.py index 67aeb151a..ec0a2c79e 100644 --- a/tests/test_all_rules.py +++ b/tests/test_all_rules.py @@ -10,24 +10,27 @@ import unittest import uuid import warnings from collections import defaultdict -from marshmallow import ValidationError from pathlib import Path import eql.ast +from marshmallow import ValidationError from semver import Version import kql from detection_rules import attack from detection_rules.beats import parse_beats_from_index -from detection_rules.integrations import load_integrations_schemas +from detection_rules.integrations import (find_latest_compatible_version, + load_integrations_manifests, + load_integrations_schemas) from detection_rules.misc import load_current_package_version from detection_rules.packaging import current_stack_version -from detection_rules.rule import (QueryRuleData, TOMLRuleContents, - load_integrations_manifests, QueryValidator) +from detection_rules.rule import (QueryRuleData, QueryValidator, + TOMLRuleContents) from detection_rules.rule_loader import FILE_PATTERN from detection_rules.rule_validators import EQLValidator, KQLValidator from detection_rules.schemas import definitions, get_stack_schemas -from detection_rules.utils import INTEGRATION_RULE_DIR, get_path, load_etc_dump, PatchedTemplate +from detection_rules.utils import (INTEGRATION_RULE_DIR, PatchedTemplate, + get_path, load_etc_dump) from detection_rules.version_lock import default_version_lock from rta import get_available_tests @@ -894,6 +897,48 @@ class TestIntegrationRules(BaseRuleTest): self.fail(f'The following ({len(failures)}) rules have a `min_stack_version` defined but missing comments:' f'\n{err_msg}') + def test_ml_integration_jobs_exist(self): + """Test that machine learning jobs exist in the integration.""" + failures = [] + + ml_integration_names = list(map(str.lower, definitions.MACHINE_LEARNING_PACKAGES)) + integration_schemas = load_integrations_schemas() + integration_manifests = load_integrations_manifests() + + for rule in self.all_rules: + if rule.contents.data.type == "machine_learning": + ml_integration_name = next((i for i in rule.contents.metadata.integration + if i in ml_integration_names), None) + if ml_integration_name: + if "machine_learning_job_id" not in dir(rule.contents.data): + failures.append(f'{self.rule_str(rule)} missing `machine_learning_job_id`') + else: + rule_job_id = rule.contents.data.machine_learning_job_id + ml_schema = integration_schemas.get(ml_integration_name) + min_version = Version.parse( + rule.contents.metadata.min_stack_version or load_current_package_version(), + optional_minor_and_patch=True + ) + latest_compat_ver = find_latest_compatible_version( + package=ml_integration_name, + integration="", + rule_stack_version=min_version, + packages_manifest=integration_manifests + ) + compat_integration_schema = ml_schema[latest_compat_ver[0]] + if rule_job_id not in compat_integration_schema['jobs']: + failures.append( + f'{self.rule_str(rule)} machine_learning_job_id `{rule_job_id}` not found ' + f'in version `{latest_compat_ver[0]}` of `{ml_integration_name}` integration. ' + f'existing jobs: {compat_integration_schema["jobs"]}' + ) + + if failures: + err_msg = '\n'.join(failures) + self.fail( + f'The following ({len(failures)}) rules are missing a valid `machine_learning_job_id`:\n{err_msg}' + ) + class TestRuleTiming(BaseRuleTest): """Test rule timing and timestamps."""