Mini Shell
import json
import logging
import os
import re
from collections import defaultdict
from peewee import SqliteDatabase
from im360.utils import is_apache2nginx_enabled
from im360.subsys.int_config import is_force_use_coraza
RULES_CONF_PATTERN = "<IfModule security2_module>\n{}\n</IfModule>"
GENERAL_RULES = "/var/imunify360/files/modsec/v2/general_rules.json"
logger = logging.getLogger(__name__)
class DatabaseNotFoundError(Exception):
pass
def map_components_versions_to_tags(
components_sqlite_file: str, tags_mapping: dict[str, str]
) -> str:
if not os.path.isfile(components_sqlite_file):
raise DatabaseNotFoundError(
"App detector database '{}' couldn't be found.".format(
components_sqlite_file
)
)
db = SqliteDatabase(components_sqlite_file)
tags_regex = []
for tag, reg in tags_mapping.items():
tags_regex.append((tag, re.compile(reg)))
cursor = db.execute_sql("select path, title from apps")
path_tags = defaultdict(set)
cache = dict()
for path, title in cursor:
tag = cache.get(title, None)
if tag is not None:
path_tags[path].add(tag)
else:
for tag, reg in tags_regex:
if reg.match(title):
path_tags[path].add(tag)
cache[title] = tag
break
return generate_conf(path_tags)
def generate_conf(path_tags) -> str:
"""
Generate conf file with rules
Use json.dumps for converting special symbols like \n and
escape quoters inside quoters
:param path_tags:
:return:
"""
config = []
if is_force_use_coraza() or is_apache2nginx_enabled():
if os.path.exists(GENERAL_RULES):
with open(GENERAL_RULES, "r") as f:
general_rules = json.load(f)
else:
general_rules = ["noshow", "service_im360"]
logger.warning(
"File %s does not exist. Using fallback", GENERAL_RULES
)
for path, tags in path_tags.items():
config.append(
{
"path": path,
"enabled_tags": sorted(list(tags) + general_rules),
}
)
return json.dumps(
sorted(config, key=lambda v: v["path"]), separators=(",", ":")
)
else:
for path, tags in path_tags.items():
config.append(
"""<Directory {}>
SecRuleRemoveByTag ^(?!(?:service.*|noshow|{})$)
</Directory>""".format(
json.dumps(path), "|".join(sorted(tags))
)
)
return RULES_CONF_PATTERN.format("\n".join(sorted(config)))