...

Text file src/edge-infra.dev/cmd/sds/fim/mount-monitor.py

Documentation: edge-infra.dev/cmd/sds/fim

     1import select
     2import re
     3import difflib
     4import subprocess
     5import datetime
     6
     7config_path = '/samhain/config/samhainrc'
     8mount_dir = '/ien_fs/proc/self/mounts'
     9inotify_processes = {}
    10
    11def get_monitored_dirs(path):
    12    with open(path) as f:
    13        lines = f.readlines()
    14
    15    regex = re.compile(r'dir.*=.*99(/ien_fs/.*)')
    16    paths = []
    17    for line in lines:
    18        m = regex.search(line)
    19        if m:
    20            paths.append(m.group(1))
    21
    22    return paths
    23
    24def process_mounts(old_mounts, new_mounts, monitored_paths):
    25    actions = {'+':'addition', '-':'deletion'}
    26    output = [m for m in difflib.ndiff(old_mounts, new_mounts) if m[0] != ' ']
    27
    28    for mount in output:
    29        s = mount.split()
    30
    31        action = actions.get(s[0], '') if old_mounts else 'existence'
    32        # Very rare case where this can fail. Only randomly saw this, but it crashed the program.
    33        try: 
    34            path = s[2]
    35            mount_type = s[3]
    36        except IndexError:
    37            path = "Unknown"
    38            mount_type = "Unknown"
    39
    40
    41        result = [p for p in monitored_paths if path.startswith(p)]
    42        if result:
    43            time_format = '%Y-%m-%dT%H:%M:%S%z'
    44            date = datetime.datetime.now().astimezone().replace(microsecond=0).strftime(time_format)
    45            msg =  f'CRIT   :  [{date}] msg=<Unusual mount activity detected>, path={path}, action={action},mount_type={mount_type}'
    46            print(msg)
    47
    48            if action == 'addition':
    49                # https://stackoverflow.com/a/13143013/17126721
    50                # Brilliant fix to orphaned shell command
    51                mask = 'modify,move,delete,create'
    52                cmd = f"exec inotifywait -m {path} -r -q -e {mask} --timefmt '{time_format}' --format 'CRIT   :  [%T] msg=<Unusual mount activity detected>, path=%w%f, inotify_event=%:e'"
    53                # No problem with using shell=True here IMO. 
    54                # We don't do anything special with it, and the path will be absolute
    55                inotify_processes[path] = subprocess.Popen(cmd, shell=True)
    56            elif action == 'deletion' and path in inotify_processes:
    57                inotify_processes[path].terminate()
    58                inotify_processes.pop(path)
    59
    60# Grab list of monitored dirs from the samhain config file
    61paths = get_monitored_dirs(config_path)
    62
    63# Initial run through before loop
    64# If a suspicious mount exists at this point, we do not need to set up our own watches for this one as Samhain will cover these
    65f = open(mount_dir)
    66mounts = f.readlines()
    67process_mounts([], mounts, paths)
    68
    69
    70
    71# Loop forever without constantly polling the file
    72while True:
    73    r,w,x = select.select([],[],[f])
    74    f.seek(0)
    75
    76    new_mounts = f.readlines()
    77    process_mounts(mounts, new_mounts, paths)
    78    # We maintain the list of last known mounts to diff on
    79    mounts = new_mounts

View as plain text