Skip to content

Instantly share code, notes, and snippets.

@moreati
Last active July 27, 2023 15:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moreati/e866b6827c754b24c899965a16ad0b41 to your computer and use it in GitHub Desktop.
Save moreati/e866b6827c754b24c899965a16ad0b41 to your computer and use it in GitHub Desktop.
ansible-playbook wrapped with audit hooks for file path operations
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import collections
import os
import re
import sys
EVENTS_OF_INTEREST = frozenset({
'glob.glob',
'open',
'os.listdir',
'os.listxattr',
'os.scandir',
'os.stat',
'pathlib.Path.glob',
'pathlib.Path.rglob',
})
events = collections.Counter()
paths = collections.Counter()
original_fstat = os.fstat
original_lstat = os.lstat
original_stat = os.stat
def fstat(fd):
sys.audit('os.fstat', fd)
return original_fstat(fd)
def lstat(path, *, dir_fd=None):
sys.audit('os.lstat', path, dir_fd)
return original_lstat(path, dir_fd=dir_fd)
def stat(path, *, dir_fd=None, follow_symlinks=True):
sys.audit('os.stat', path, dir_fd, follow_symlinks)
return original_stat(path, dir_fd=dir_fd, follow_symlinks=follow_symlinks)
os.fstat = fstat
os.lstat = lstat
os.stat = stat
def audit(event, args):
if event not in EVENTS_OF_INTEREST:
return
events[event] += 1
path = args[0]
if isinstance(path, bytes):
path = path.decode(sys.getfilesystemencoding())
paths[path] += 1
sys.addaudithook(audit)
from ansible.cli.playbook import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
try:
rc = main()
except SystemExit as exc:
rc = exc.code
for event, count in events.most_common(10):
print(count, event)
print()
for path, count in paths.most_common(10):
print(count, path)
sys.exit(rc)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment