diff --git a/requirements-qa.txt b/requirements-qa.txt index ff85146..b030b93 100644 --- a/requirements-qa.txt +++ b/requirements-qa.txt @@ -2,4 +2,4 @@ pytest==7.4.3 pytest-openfiles==0.5.0 pytest-random-order==1.1.0 bump-my-version==0.17.3 -setuptools==70.0.0 \ No newline at end of file +setuptools==78.1.1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 78b24d5..1824909 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,5 +13,5 @@ azure-monitor-query==1.4.1 splunk-sdk==2.0.1 colorama==0.4.6 python-json-logger==2.0.7 -requests==2.32.3 +requests==2.32.4 elasticsearch==8.14.0 \ No newline at end of file diff --git a/src/droid/__main__.py b/src/droid/__main__.py index fd011ed..9083b5f 100644 --- a/src/droid/__main__.py +++ b/src/droid/__main__.py @@ -42,7 +42,7 @@ def init_argparse() -> argparse.ArgumentParser: parser.add_argument("-p", "--platform", help="Platform target", choices=["splunk", "microsoft_sentinel", "microsoft_xdr", "esql", "eql"]) parser.add_argument("-sx", "--sentinel-xdr", help="Use Microsoft Sentinel as a search head for Microsoft XDR", action="store_true") parser.add_argument("-u", "--update", help="Update from source", choices=["sigmahq-core"]) - parser.add_argument("-l", "--list", help="List items from rules", choices=["unique_fields", "pipelines"]) + parser.add_argument("-l", "--list", help="List items from rules", choices=["unique_fields", "pipelines", "validators"]) parser.add_argument("-m", "--mssp", help="Enable MSSP mode", action="store_true") parser.add_argument("-mo", "--module", help="Module mode to return converted rules as a list", action="store_true") parser.add_argument("-j", "--json", help="Drop a JSON log file", action="store_true") diff --git a/src/droid/list.py b/src/droid/list.py index 9c5b135..2106fcf 100644 --- a/src/droid/list.py +++ b/src/droid/list.py @@ -92,4 +92,13 @@ def list_keys(parameters, logger_param) -> None: plugins = InstalledSigmaPlugins.autodiscover() pipeline_resolver = plugins.get_pipeline_resolver() pipeline_list = list(pipeline_resolver.pipelines.keys()) - print(*pipeline_list, sep='\n') \ No newline at end of file + print(*pipeline_list, sep='\n') + + elif 'validators' in parameters.list: + plugins = InstalledSigmaPlugins.autodiscover() + validators = plugins.validators + if validators: + validator_names = list(validators.keys()) + print(*sorted(validator_names), sep='\n') + else: + print("No validators found in installed pySigma plugins") \ No newline at end of file diff --git a/src/droid/validate.py b/src/droid/validate.py index 620f718..7eb62f9 100644 --- a/src/droid/validate.py +++ b/src/droid/validate.py @@ -21,12 +21,48 @@ def __init__(self, base_config, logger_param) -> None: self.logger.debug("Initializing droid.validate.SigmaValidation") - def validators(self) -> None: - return InstalledSigmaPlugins.autodiscover().validators + def get_installed_validators(self) -> dict: + """Get all installed validators from pySigma plugins. + + This method autodiscovers validators from installed pySigma plugins, + similar to how backends and pipelines are discovered. + + Returns: + dict: A dictionary of validator names to validator classes. + """ + plugins = InstalledSigmaPlugins.autodiscover() + validators = plugins.validators + self.logger.debug(f"Discovered {len(validators)} validators from installed plugins") + return validators + + def list_validators(self) -> list: + """List all available validator names. + + Returns: + list: A list of validator names. + """ + validators = self.get_installed_validators() + validator_names = list(validators.keys()) + self.logger.debug(f"Available validators: {validator_names}") + return validator_names def init_validator(self) -> None: + """Initialize the SigmaValidator with installed validators. + + Loads the validation configuration from the YAML file and initializes + the SigmaValidator with all autodiscovered validators from pySigma plugins. + """ + validators = self.get_installed_validators() + + if validators: + self.logger.info(f"Loaded {len(validators)} validators from installed pySigma plugins") + for validator_name in validators: + self.logger.debug(f" - {validator_name}") + else: + self.logger.warning("No validators discovered from installed pySigma plugins") + with open(self._validation_config_path) as validation_config: - self._rule_validator = SigmaValidator.from_yaml(validation_config.read(), self.validators()) + self._rule_validator = SigmaValidator.from_yaml(validation_config.read(), validators) def init_sigma_rule(self, rule, rule_file) -> None: try: