File: //opt/imunify360/venv/lib64/python3.11/site-packages/defence360agent/wordpress/wp_rules.py
"""WordPress rules file management.
This module provides utilities for loading and parsing wp-rules.yaml
from the files.imunify360.com index system.
Available for both AV and IM360 modes.
"""
import logging
import yaml
import zipfile
from pathlib import Path
from defence360agent.files import Index
logger = logging.getLogger(__name__)
# WordPress rules file names within the index
WP_RULES_ZIP_FILENAME = "wp-rules.zip"
WP_RULES_VERSION_FILENAME = "VERSION"
def find_file_in_index(index: Index, filename: str) -> Path | None:
"""
Find a file path from the index by filename.
Args:
index: files.Index object
filename: Name of the file to find (e.g., WP_RULES_ZIP_FILENAME)
Returns:
Path to the file or None if not found
"""
for item in index.items():
if item["name"] == filename:
file_path = Path(index.localfilepath(item["url"]))
if file_path.exists():
return file_path
logger.error("%s not found in %s", filename, index.files_path(index.type))
return None
def extract_wp_rules_yaml(zip_path: Path) -> dict | None:
"""
Extract and parse wp-rules.yaml from the zip file.
Args:
zip_path: Path to wp-rules.zip file
Returns:
Parsed YAML data as dict or None if extraction/parsing fails
"""
try:
with zipfile.ZipFile(zip_path, "r") as zip_file:
with zip_file.open("wp-rules.yaml") as yaml_file:
rules_data = yaml.safe_load(yaml_file)
except (zipfile.BadZipFile, KeyError, yaml.YAMLError) as e:
logger.error("Failed to extract or parse wp-rules.yaml: %s", e)
return None
if not isinstance(rules_data, dict):
logger.error("Invalid wp-rules.yaml format: %s", rules_data)
return None
return rules_data
def get_wp_rules_data(index: Index) -> dict | None:
"""
Retrieve the latest WordPress rules and return them as a dictionary.
Args:
index: The files.Index object used to locate the wp-rules.zip file.
Returns:
The parsed wp-rules data as a dictionary.
If the wp-rules archive or data cannot be found or parsed, returns None.
Note:
This function returns the raw rules data. Callers that need to modify
rules based on product mode (e.g., ANTIVIRUS_MODE) should do so after
calling this function.
"""
# Find wp-rules.zip file
zip_path = find_file_in_index(index, WP_RULES_ZIP_FILENAME)
if not zip_path:
return None
# Extract and parse wp-rules.yaml
rules_data = extract_wp_rules_yaml(zip_path)
if not rules_data:
return None
logger.info("Successfully parsed wp-rules.yaml")
return rules_data
def get_wp_ruleset_version(index: Index) -> str:
"""
Retrieve the WordPress ruleset version string from the VERSION file.
Args:
index: The files.Index object used to locate the VERSION file.
Returns:
The version string from the VERSION file.
If the VERSION file cannot be found or read, returns "NA".
"""
# Find VERSION file
version_path = find_file_in_index(index, WP_RULES_VERSION_FILENAME)
if not version_path:
return "NA"
try:
version_string = version_path.read_text().strip()
logger.info("Successfully read wp-rules version: %s", version_string)
return version_string
except Exception as e:
logger.error("Failed to read VERSION file: %s", e)
return "NA"