Skip to content

Helpers

psengine.malware_intel.helpers.save_rules

save_rules(
    rule_job: AutoYaraJobOut | AutoSigmaJobOut,
    output_directory: str | Path | None = None,
)

Write Auto YARA or Auto Sigma generated rules to file(s).

For AutoYaraJobOut, writes a single .yar file from job.yara_rule_str. For AutoSigmaJobOut, writes one .yml file per item in sigma_rules.

PARAMETER DESCRIPTION
rule_job

Auto YARA or Auto Sigma job result to write to disk.

TYPE: AutoYaraJobOut | AutoSigmaJobOut

output_directory

Path to write to. If not provided, the current working directory will be used.

TYPE: str | Path | None DEFAULT: None

RAISES DESCRIPTION
WriteFileError

If write operations fail.

Source code in psengine/malware_intel/helpers.py
@debug_call
@validate_call
def save_rules(
    rule_job: Annotated[
        AutoYaraJobOut | AutoSigmaJobOut,
        Doc('Auto YARA or Auto Sigma job result to write to disk.'),
    ],
    output_directory: Annotated[
        str | Path | None,
        Doc('Path to write to. If not provided, the current working directory will be used.'),
    ] = None,
):
    """Write Auto YARA or Auto Sigma generated rules to file(s).

    For `AutoYaraJobOut`, writes a single `.yar` file from `job.yara_rule_str`.
    For `AutoSigmaJobOut`, writes one `.yml` file per item in `sigma_rules`.

    Raises:
        WriteFileError: If write operations fail.
    """
    output_directory = Path(output_directory).absolute() if output_directory else Path().cwd()
    OSHelpers.mkdir(output_directory)

    if isinstance(rule_job, AutoYaraJobOut):
        if not rule_job.job.yara_rule_str:
            LOG.info(f'No YARA rule to write for {rule_job.job.job_id}')
            return

        file_name = f'{_safe_job_name(rule_job.job.name, rule_job.job.job_id)}.yar'
        try:
            full_path = output_directory / file_name
            full_path.write_text(rule_job.job.yara_rule_str)
            LOG.info(f'Wrote: {full_path}')
            return
        except (FileNotFoundError, IsADirectoryError, PermissionError, OSError) as err:  # noqa: PERF203
            raise WriteFileError(f"Could not write file '{file_name}': {err}") from err

    if not rule_job.sigma_rules:
        LOG.info(f'No Sigma rules to write for {rule_job.job_id}')
        return

    job_name = _safe_job_name(rule_job.name, rule_job.job_id)
    for i, sigma_rule in enumerate(rule_job.sigma_rules, start=1):
        file_name = f'{job_name} - Rule {i}.yml'
        try:
            full_path = output_directory / file_name
            full_path.write_text(sigma_rule.rule)
            LOG.info(f'Wrote: {full_path}')
        except (FileNotFoundError, IsADirectoryError, PermissionError, OSError) as err:  # noqa: PERF203
            raise WriteFileError(f"Could not write file '{file_name}': {err}") from err