From 354121792cd0105d2977ef3d404e1f05a343fa96 Mon Sep 17 00:00:00 2001 From: Charles Costa Date: Tue, 2 Sep 2025 17:24:14 -0300 Subject: [PATCH] feat: adds custom root_dir capability through env var --- ...ov_in_poland_apt28\357\200\277__sysmon.yaral" | 0 .../content_manager/content_manager/__main__.py | 16 ++++++++-------- .../content_manager/common/constants.py | 14 ++++++++++++++ .../content_manager/data_tables.py | 8 ++++---- .../content_manager/reference_lists.py | 8 ++++---- .../content_manager/rule_exclusions.py | 4 ++-- tools/content_manager/content_manager/rules.py | 8 ++++---- .../content_manager/test_data_tables.py | 6 +++--- .../content_manager/test_reference_lists.py | 6 +++--- .../content_manager/test_rule_exclusions.py | 4 ++-- .../content_manager/test_rules.py | 6 +++--- 11 files changed, 47 insertions(+), 33 deletions(-) rename rules/_deprecated/soc_prime_rules/threat_hunting/sysmon/spear_phishing_attack_on_gov_in_poland_apt28?__sysmon.yaral => "rules/_deprecated/soc_prime_rules/threat_hunting/sysmon/spear_phishing_attack_on_gov_in_poland_apt28\357\200\277__sysmon.yaral" (100%) create mode 100644 tools/content_manager/content_manager/common/constants.py diff --git a/rules/_deprecated/soc_prime_rules/threat_hunting/sysmon/spear_phishing_attack_on_gov_in_poland_apt28?__sysmon.yaral "b/rules/_deprecated/soc_prime_rules/threat_hunting/sysmon/spear_phishing_attack_on_gov_in_poland_apt28\357\200\277__sysmon.yaral" similarity index 100% rename from rules/_deprecated/soc_prime_rules/threat_hunting/sysmon/spear_phishing_attack_on_gov_in_poland_apt28?__sysmon.yaral rename to "rules/_deprecated/soc_prime_rules/threat_hunting/sysmon/spear_phishing_attack_on_gov_in_poland_apt28\357\200\277__sysmon.yaral" diff --git a/tools/content_manager/content_manager/__main__.py b/tools/content_manager/content_manager/__main__.py index 29a50cc4..b96df86c 100644 --- a/tools/content_manager/content_manager/__main__.py +++ b/tools/content_manager/content_manager/__main__.py @@ -24,6 +24,7 @@ from typing import Literal import click +from content_manager.common.constants import Constants from content_manager.common import datetime_converter from content_manager.common.custom_exceptions import RuleVerificationError from content_manager.data_tables import DataTables @@ -40,14 +41,13 @@ LOGGER = logging.getLogger() -ROOT_DIR = pathlib.Path(__file__).parent.parent -RULES_DIR = ROOT_DIR / "rules" -RULE_CONFIG_FILE = ROOT_DIR / "rule_config.yaml" -REF_LISTS_DIR = ROOT_DIR / "reference_lists" -REF_LIST_CONFIG_FILE = ROOT_DIR / "reference_list_config.yaml" -DATA_TABLES_DIR = ROOT_DIR / "data_tables" -DATA_TABLE_CONFIG_FILE = ROOT_DIR / "data_table_config.yaml" -RULE_EXCLUSIONS_CONFIG_FILE = ROOT_DIR / "rule_exclusions_config.yaml" +RULES_DIR = Constants.ROOT_DIR / "rules" +RULE_CONFIG_FILE = Constants.ROOT_DIR / "rule_config.yaml" +REF_LISTS_DIR = Constants.ROOT_DIR / "reference_lists" +REF_LIST_CONFIG_FILE = Constants.ROOT_DIR / "reference_list_config.yaml" +DATA_TABLES_DIR = Constants.ROOT_DIR / "data_tables" +DATA_TABLE_CONFIG_FILE = Constants.ROOT_DIR / "data_table_config.yaml" +RULE_EXCLUSIONS_CONFIG_FILE = Constants.ROOT_DIR / "rule_exclusions_config.yaml" dotenv.load_dotenv() diff --git a/tools/content_manager/content_manager/common/constants.py b/tools/content_manager/content_manager/common/constants.py new file mode 100644 index 00000000..4e74905d --- /dev/null +++ b/tools/content_manager/content_manager/common/constants.py @@ -0,0 +1,14 @@ +import os +import pathlib + + +class Constants: + """Handles constants used throughout the content manager.""" + ROOT_DIR = os.getenv("ROOT_DIR", pathlib.Path(__file__).parent.parent) + # Variables for a future support + # RULES_DIR = ROOT_DIR / pathlib.Path(os.getenv("RULES_DIR", "rules")) + # RULE_CONFIG_FILE = ROOT_DIR / pathlib.Path(os.getenv("RULE_CONFIG_FILE", "rules")) + # REF_LISTS_DIR = ROOT_DIR / pathlib.Path(os.getenv("REF_LISTS_DIR", "rules")) + # DATA_TABLES_DIR = ROOT_DIR / pathlib.Path(os.getenv("DATA_TABLES_DIR", "rules")) + # DATA_TABLE_CONFIG_FILE = ROOT_DIR / pathlib.Path(os.getenv("DATA_TABLE_CONFIG_FILE", "rules")) + # RULE_EXCLUSION_CONFIG_FILE = ROOT_DIR / pathlib.Path(os.getenv("RULE_EXCLUSION_CONFIG_FILE", "rules")) \ No newline at end of file diff --git a/tools/content_manager/content_manager/data_tables.py b/tools/content_manager/content_manager/data_tables.py index c8155b47..cc63e526 100644 --- a/tools/content_manager/content_manager/data_tables.py +++ b/tools/content_manager/content_manager/data_tables.py @@ -20,6 +20,7 @@ import pathlib from typing import Any, Literal, Mapping, Sequence +from content_manager.common.constants import Constants from content_manager.common.custom_exceptions import DataTableConfigError from google.auth.transport import requests from google_secops_api.data_table_rows.bulk_create_data_table_rows import bulk_create_data_table_rows @@ -34,9 +35,8 @@ LOGGER = logging.getLogger() -ROOT_DIR = pathlib.Path(__file__).parent.parent -DATA_TABLES_DIR = ROOT_DIR / "data_tables" -DATA_TABLE_CONFIG_FILE = ROOT_DIR / "data_table_config.yaml" +DATA_TABLES_DIR = Constants.ROOT_DIR / "data_tables" +DATA_TABLE_CONFIG_FILE = Constants.ROOT_DIR / "data_table_config.yaml" DATA_TABLE_COLUMN_TYPES = Literal["CIDR", "STRING", "REGEX"] # pylint: disable="invalid-name" # Use ruamel.yaml to raise an exception if a YAML file contains duplicate keys @@ -384,7 +384,7 @@ def dump_data_table_config(self): exclude={"name"} ) - data_table_config_file_path = ROOT_DIR / "data_table_config.yaml" + data_table_config_file_path = Constants.ROOT_DIR / "data_table_config.yaml" LOGGER.info("Writing data table config to %s", data_table_config_file_path) with open( diff --git a/tools/content_manager/content_manager/reference_lists.py b/tools/content_manager/content_manager/reference_lists.py index 341554ca..38585c64 100644 --- a/tools/content_manager/content_manager/reference_lists.py +++ b/tools/content_manager/content_manager/reference_lists.py @@ -22,6 +22,7 @@ import pathlib from typing import Any, List, Literal, Mapping, Sequence, Tuple +from content_manager.common.constants import Constants from content_manager.common.custom_exceptions import ReferenceListConfigError from google.auth.transport import requests from google_secops_api.reference_lists.create_reference_list import create_reference_list @@ -34,9 +35,8 @@ LOGGER = logging.getLogger() -ROOT_DIR = pathlib.Path(__file__).parent.parent -REF_LISTS_DIR = ROOT_DIR / "reference_lists" -REF_LIST_CONFIG_FILE = ROOT_DIR / "reference_list_config.yaml" +REF_LISTS_DIR = Constants.ROOT_DIR / "reference_lists" +REF_LIST_CONFIG_FILE = Constants.ROOT_DIR / "reference_list_config.yaml" REF_LIST_SYNTAX_TYPES = Literal[ # pylint: disable="invalid-name" "REFERENCE_LIST_SYNTAX_TYPE_UNSPECIFIED", "REFERENCE_LIST_SYNTAX_TYPE_PLAIN_TEXT_STRING", @@ -322,7 +322,7 @@ def dump_ref_list_config(self): exclude={"name"} ) - ref_list_config_file_path = ROOT_DIR / "reference_list_config.yaml" + ref_list_config_file_path = Constants.ROOT_DIR / "reference_list_config.yaml" LOGGER.info( "Writing reference list config to %s", ref_list_config_file_path diff --git a/tools/content_manager/content_manager/rule_exclusions.py b/tools/content_manager/content_manager/rule_exclusions.py index 3726f3b5..02cc0911 100644 --- a/tools/content_manager/content_manager/rule_exclusions.py +++ b/tools/content_manager/content_manager/rule_exclusions.py @@ -23,6 +23,7 @@ import re from typing import Any, Literal, Mapping, Sequence +from content_manager.common.constants import Constants from content_manager.common.custom_exceptions import RuleExclusionConfigError from google.auth.transport import requests from google_secops_api.findings_refinements.create_findings_refinement import create_findings_refinement @@ -38,8 +39,7 @@ LOGGER = logging.getLogger() -ROOT_DIR = pathlib.Path(__file__).parent.parent -RULE_EXCLUSIONS_CONFIG_FILE = ROOT_DIR / "rule_exclusions_config.yaml" +RULE_EXCLUSIONS_CONFIG_FILE = Constants.ROOT_DIR / "rule_exclusions_config.yaml" RULE_EXCLUSION_TYPES = Literal["DETECTION_EXCLUSION"] # pylint: disable="invalid-name" EXCLUSION_APPLICATIONS = Literal["curated_rule_sets", "curated_rules"] # pylint: disable="invalid-name" diff --git a/tools/content_manager/content_manager/rules.py b/tools/content_manager/content_manager/rules.py index a5afb605..c0e2ee5d 100644 --- a/tools/content_manager/content_manager/rules.py +++ b/tools/content_manager/content_manager/rules.py @@ -24,6 +24,7 @@ import re from typing import Any, List, Mapping, Sequence, Tuple +from content_manager.common.constants import Constants from content_manager.common.custom_exceptions import DuplicateRuleIdError from content_manager.common.custom_exceptions import DuplicateRuleNameError from content_manager.common.custom_exceptions import RuleConfigError @@ -43,9 +44,8 @@ LOGGER = logging.getLogger() -ROOT_DIR = pathlib.Path(__file__).parent.parent -RULES_DIR = ROOT_DIR / "rules" -RULE_CONFIG_FILE = ROOT_DIR / "rule_config.yaml" +RULES_DIR = Constants.ROOT_DIR / "rules" +RULE_CONFIG_FILE = Constants.ROOT_DIR / "rule_config.yaml" # Use ruamel.yaml to raise an exception if a YAML file contains duplicate keys # (i.e. duplicate rule names) @@ -329,7 +329,7 @@ def dump_rule_config(self): exclude={"name"} ) - rule_config_file_path = ROOT_DIR / "rule_config.yaml" + rule_config_file_path = Constants.ROOT_DIR / "rule_config.yaml" LOGGER.info("Writing rule config to %s", rule_config_file_path) with open(rule_config_file_path, "w", encoding="utf-8") as rule_config_file: diff --git a/tools/content_manager/content_manager/test_data_tables.py b/tools/content_manager/content_manager/test_data_tables.py index 843bc7e4..61bd64a0 100644 --- a/tools/content_manager/content_manager/test_data_tables.py +++ b/tools/content_manager/content_manager/test_data_tables.py @@ -19,6 +19,7 @@ import pathlib from typing import Any, Mapping, Sequence +from content_manager.common.constants import Constants from content_manager.common.custom_exceptions import DataTableConfigError from content_manager.data_tables import DataTable from content_manager.data_tables import DataTableColumn @@ -29,9 +30,8 @@ import ruamel.yaml.constructor -ROOT_DIR = pathlib.Path(__file__).parent.parent -DATA_TABLES_DIR = ROOT_DIR / "data_tables" -DATA_TABLE_CONFIG_FILE = ROOT_DIR / "data_table_config.yaml" +DATA_TABLES_DIR = Constants.ROOT_DIR / "data_tables" +DATA_TABLE_CONFIG_FILE = Constants.ROOT_DIR / "data_table_config.yaml" TEST_DATA_DIR = pathlib.Path(__file__).parent / "test_data" TEST_DATA_TABLES_DIR = TEST_DATA_DIR / "data_tables" TEST_DATA_TABLE_CONFIG_FILE = TEST_DATA_DIR / "test_data_table_config.yaml" diff --git a/tools/content_manager/content_manager/test_reference_lists.py b/tools/content_manager/content_manager/test_reference_lists.py index eaba82a0..8442e034 100644 --- a/tools/content_manager/content_manager/test_reference_lists.py +++ b/tools/content_manager/content_manager/test_reference_lists.py @@ -19,6 +19,7 @@ import pathlib from typing import Any, Mapping, Sequence +from content_manager.common.constants import Constants from content_manager.common.custom_exceptions import ReferenceListConfigError from content_manager.reference_lists import ReferenceList from content_manager.reference_lists import ReferenceListConfigEntry @@ -28,9 +29,8 @@ import ruamel.yaml.constructor -ROOT_DIR = pathlib.Path(__file__).parent.parent -REF_LISTS_DIR = ROOT_DIR / "reference_lists" -REF_LIST_CONFIG_FILE = ROOT_DIR / "reference_list_config.yaml" +REF_LISTS_DIR = Constants.ROOT_DIR / "reference_lists" +REF_LIST_CONFIG_FILE = Constants.ROOT_DIR / "reference_list_config.yaml" TEST_DATA_DIR = pathlib.Path(__file__).parent / "test_data" TEST_REF_LISTS_DIR = TEST_DATA_DIR / "reference_lists" TEST_REF_LISTS_CONFIG_FILE = TEST_DATA_DIR / "test_reference_list_config.yaml" diff --git a/tools/content_manager/content_manager/test_rule_exclusions.py b/tools/content_manager/content_manager/test_rule_exclusions.py index 0b8404dd..0a665428 100644 --- a/tools/content_manager/content_manager/test_rule_exclusions.py +++ b/tools/content_manager/content_manager/test_rule_exclusions.py @@ -18,6 +18,7 @@ import pathlib from typing import Any, Mapping, Sequence +from content_manager.common.constants import Constants from content_manager.common.custom_exceptions import RuleExclusionConfigError from content_manager.rule_exclusions import RuleExclusion from content_manager.rule_exclusions import RuleExclusionConfigEntry @@ -27,8 +28,7 @@ import ruamel.yaml import ruamel.yaml.constructor -ROOT_DIR = pathlib.Path(__file__).parent.parent -RULE_EXCLUSIONS_CONFIG_FILE = ROOT_DIR / "rule_exclusions_config.yaml" +RULE_EXCLUSIONS_CONFIG_FILE = Constants.ROOT_DIR / "rule_exclusions_config.yaml" TEST_DATA_DIR = pathlib.Path(__file__).parent / "test_data" TEST_RULE_EXCLUSIONS_CONFIG_FILE = ( TEST_DATA_DIR / "test_rule_exclusions_config.yaml" diff --git a/tools/content_manager/content_manager/test_rules.py b/tools/content_manager/content_manager/test_rules.py index f7066a40..6b7fa8ec 100644 --- a/tools/content_manager/content_manager/test_rules.py +++ b/tools/content_manager/content_manager/test_rules.py @@ -21,6 +21,7 @@ import pathlib from typing import Any, Mapping, Sequence +from content_manager.common.constants import Constants from content_manager.common.custom_exceptions import DuplicateRuleIdError from content_manager.common.custom_exceptions import DuplicateRuleNameError from content_manager.common.custom_exceptions import RuleConfigError @@ -32,9 +33,8 @@ import pytest import ruamel.yaml.constructor -ROOT_DIR = pathlib.Path(__file__).parent.parent -RULES_DIR = ROOT_DIR / "rules" -RULE_CONFIG_FILE = ROOT_DIR / "rule_config.yaml" +RULES_DIR = Constants.ROOT_DIR / "rules" +RULE_CONFIG_FILE = Constants.ROOT_DIR / "rule_config.yaml" TEST_DATA_DIR = pathlib.Path(__file__).parent / "test_data" TEST_RULES_DIR = TEST_DATA_DIR / "rules" TEST_RULE_CONFIG_FILE = TEST_DATA_DIR / "test_rule_config.yaml"