ȼhe=g d Z ddlZddlZddlZddlmZ ddlmZ ddlm Z ej
e ZdZ
deded efd
Z edd Zdd
edz d efdZdZefd
ed eee edz f fdZ G d de ZdS )u
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Copyright © 2019 Cloud Linux Software Inc.
This software is also available under ImunifyAV commercial license,
see
DEF-43111: AV-mode watcher that restarts aibolit-resident when the
malware-stack kill-switch (force_aibolit_stack) flips.
Polls FLAGS_PLAIN_PATH (one-flag-name-per-line plain text written by
defence360agent.plugins.feature_flags.FeatureFlagsSync) on a short
interval; on a False<->True transition, scans /etc/systemd/system/
aibolit-resident.service.d/ for drop-in overrides (logs a WARNING if
present) and calls imav.malwarelib.subsys.aibolit.restart_on_sigs_or_config_update.
In IM360 mode the Go resident-agent already owns this transition (see
src/resident-agent/plugins/feature_flags/plugin.go), so this watcher is
Scope.AV only to avoid double-restarting.
N)
MessageSource)FLAGS_PLAIN_PATH)Scopeforce_aibolit_stacknamedefaultreturnc t j | }|s|S t | S # t $ r" t
d| || |cY S w xY w)u Read an int env var tolerantly. A non-numeric value (empty string,
typo, etc.) must NOT raise at import time — the watcher lives in the
AV agent entry point and a bad env var would otherwise kill the agent.
zBaibolit-resident FF watcher: %s=%r is not an int, using default %d)osenvirongetint
ValueErrorloggerwarning)r r raws ]/opt/imunify360/venv/lib/python3.11/site-packages/imav/plugins/aibolit_resident_ff_watcher.py_env_intr 1 s~
*..
C
3xx
s 4 )A A !I360_FORCE_AIBOLIT_STACK_POLL_SEC pathc | t } t | d 5 }|D ].}| d t k r ddd dS / ddd n# 1 swxY w Y n# t t
f$ r Y nw xY wdS )u Return True iff force_aibolit_stack appears in the plain-text sidecar.
Reads FLAGS_PLAIN_PATH directly (one bare flag name per line, sorted,
written atomically by both FeatureFlagsSync._write_flags and the Go
resident-agent). The aibolit-resident systemd unit's ExecStart= shell
greps the same file, so reading it here keeps the watcher's transition
detector aligned with the unit-file decision.
Bypasses any caching deliberately:
- Avoids the mtime cache in defence360agent.internals.feature_flags.is_enabled
(whole-second resolution would race with an immediately-following
write and silently mask transitions inside the same wall-clock second).
- Avoids the JSON file's value-interpretation surface (truthy/falsy
across bool/int/string variants); the plain file already represents
the enabled-set semantic, so exact-line match is the right comparison.
`path` defaults to the module-level FLAGS_PLAIN_PATH resolved at call
time (NOT bound at function-definition time) so unit tests can override
that constant via monkeypatch and have it take effect here.
Returns False when the file is missing, unreadable, empty, or the flag
name is not present — matching the agent's default-off semantics.
Nzutf-8)encoding
TF)r openrstrip_FORCE_AIBOLIT_STACK_FF_NAMEOSErrorUnicodeDecodeError)r flines r "_read_force_aibolit_stack_uncachedr" I s 0 |
$
)
)
) Q
;;t$$(DDD D
'(
5s@ A' $A A'
AA' AA' "A#A' 'A;:A;z./etc/systemd/system/aibolit-resident.service.dc t t j | }n*# t $ r g dfcY S t $ r}g |fcY d}~S d}~ww xY wt d |D }|dfS )u Scan `path` for .conf drop-in files (blocking syscall).
Returns ``(sorted_conf_names, None)`` on success, where the list is empty
if the directory exists but contains no .conf overrides. Returns
``([], None)`` when the directory is absent (clean state — no warning).
Returns ``([], err)`` for unexpected OSErrors so the async caller can log
with ``exc_info=err``.
Lives at module scope (not a method) so the async caller can pass it to
``loop.run_in_executor`` without partially binding ``self``.
Nc 3 X K | ]%}|j d |j V &dS )z.confN)r endswith).0es r z4_scan_aibolit_resident_dropin_dir..