Mini Shell
import gzip
import logging
import os
from pathlib import Path
import shutil
from defence360agent.utils import atomic_rewrite, check_run, CheckRunError
from im360 import files
from im360.contracts.config import ProactiveDefence
logger = logging.getLogger(__name__)
PHP_IMMUNITY_FILENAME = "/usr/share/i360-php-opts/autorules.yaml"
PHP_IMMUNITY_FILESDIR = Path("/usr/share/i360-php-opts")
PHP_IMMUNITY_COMPILED_RULES = (
"/usr/share/i360-php-opts/phpimunity.compiled.rules"
)
I360_STORAGE_BIN = "/usr/bin/i360-storage-mkcustom"
I360_STORAGE_NEW_BIN = "/usr/bin/i360-storage-new"
I360_STORAGE_REPLACEHDB_BIN = "/usr/bin/i360-storage-replacehdb-v2"
_RULES_UMASK = 0o022
async def update_php_immunity_files():
index = files.Index(files.PHP_IMMUNITY)
try:
item = next(
i for i in index.items() if i["name"] == "autorules_opt.yaml.gz"
)
except StopIteration:
logger.warning("PHP Immunity rules are not found in index")
return
local_path = index.localfilepath(item["url"])
tmp = PHP_IMMUNITY_FILENAME + ".tmp"
with gzip.open(local_path, "rt", encoding="utf-8") as src, open(
tmp, "w"
) as dst:
shutil.copyfileobj(src, dst)
os.rename(tmp, PHP_IMMUNITY_FILENAME)
async def apply_php_immunity_rules():
try:
await check_run([I360_STORAGE_BIN, PHP_IMMUNITY_FILENAME])
except FileNotFoundError as err:
logger.error("i360-storage is not found: %s", err)
except CheckRunError as err:
logger.error("Failed to apply new php immunity rules: %s", err)
async def update_hook(_, is_updated):
if is_updated:
await update_php_immunity_files()
if ProactiveDefence.PHP_IMMUNITY:
await apply_php_immunity_rules()
async def update_hook_immunity_v2(_, is_updated):
"""When we are done with downloading
/var/imunify360/files/php-immunity/v2/* files
then we need to copy the files as is (no gunzip or byte-compiling)
to /usr/share/i360-php-opts/
in a safe way using atomic_rewrite()
as far these files are opened by i360.so using mmap()
plus ensure that the files have correct permissions for cagefs
(/usr/share/i360-php-opts/ directory files
are visible for cagefs due to imunify360-php-i360 %post scriptlet)
"""
if is_updated:
if os.path.exists(I360_STORAGE_REPLACEHDB_BIN):
await check_run(
[I360_STORAGE_REPLACEHDB_BIN],
preexec_fn=lambda: os.umask(_RULES_UMASK),
)
return
index = files.Index(files.PHP_IMMUNITY_V2)
for wb_db_item in index.items():
local_path = Path(index.localfilepath(wb_db_item["url"]))
# As for tough requirements on Proactive defense performance
# overhead, we do not expect that W/B hash db file
# to be greater than 10 MiB
atomic_rewrite(
PHP_IMMUNITY_FILESDIR / local_path.name,
local_path.read_bytes(),
backup=False,
permissions=0o644,
)
async def recreate_signatures_on_update(_, is_updated):
if is_updated:
# recreate signatures from new rules
# use *0o022* umask to ensure that rules will be recreated with
# required permissions
await check_run(
[I360_STORAGE_NEW_BIN], preexec_fn=lambda: os.umask(_RULES_UMASK)
)