# Copyright (C) 2015 Custodia Project Contributors - see LICENSE file import sys import time import traceback try: from StringIO import StringIO except ImportError: from io import StringIO DEBUG = False def stacktrace(): _, _, tb = sys.exc_info() if tb is None: return None try: f = StringIO() traceback.print_tb(tb, None, file=f) return f.getvalue() finally: del tb def get_time(): t = time.gmtime(time.time()) return '%04d/%02d/%02d %02d:%02d:%02d' % ( t[0], t[1], t[2], t[3], t[4], t[5]) def error(msg, head=None): if head is not None: head = get_time() sys.stderr.write('[%s] %s\n' % (head, msg)) def debug(msg): if DEBUG: error(msg, 'DEBUG') trace = stacktrace() if trace is not None: sys.stderr.write(trace + '\n') AUDIT_NONE = 0 AUDIT_GET_ALLOWED = 1 AUDIT_GET_DENIED = 2 AUDIT_SET_ALLOWED = 3 AUDIT_SET_DENIED = 4 AUDIT_DEL_ALLOWED = 5 AUDIT_DEL_DENIED = 6 AUDIT_LAST = 7 AUDIT_SVC_NONE = 8 AUDIT_SVC_AUTH_PASS = 9 AUDIT_SVC_AUTH_FAIL = 10 AUDIT_SVC_AUTHZ_PASS = 11 AUDIT_SVC_AUTHZ_FAIL = 12 AUDIT_SVC_LAST = 13 AUDIT_MESSAGES = [ "AUDIT FAILURE", "ALLOWED: '{client:s}' requested key '{key:s}'", # AUDIT_GET_ALLOWED "DENIED: '{client:s}' requested key '{key:s}'", # AUDIT_GET_DENIED "ALLOWED: '{client:s}' stored key '{key:s}'", # AUDIT_SET_ALLOWED "DENIED: '{client:s}' stored key '{key:s}'", # AUDIT_SET_DENIED "ALLOWED: '{client:s}' deleted key '{key:s}'", # AUDIT_DEL_ALLOWED "DENIED: '{client:s}' deleted key '{key:s}'", # AUDIT_DEL_DENIED "AUDIT FAILURE 7", "AUDIT FAILURE 8", "PASS({tag:s}): '{cli:s}' authenticated as '{name:s}'", # SVC_AUTH_PASS "FAIL({tag:s}): '{cli:s}' authenticated as '{name:s}'", # SVC_AUTH_FAIL "PASS({tag:s}): '{cli:s}' authorized for '{name:s}'", # SVC_AUTHZ_PASS "FAIL({tag:s}): '{cli:s}' authorized for '{name:s}'", # SVC_AUTHZ_FAIL "AUDIT FAILURE 13", ] class AuditLog(object): def __init__(self, config): if config is None: config = {} self.logfile = config.get('auditlog', 'custodia.audit.log') def _log(self, message): with open(self.logfile, 'a+') as f: f.write('%s: %s\n' % (get_time(), message)) f.flush() def key_access(self, action, client, keyname): if action <= AUDIT_NONE or action >= AUDIT_LAST: action = AUDIT_NONE self._log(AUDIT_MESSAGES[action].format(client=client, key=keyname)) def svc_access(self, action, client, tag, name): if action <= AUDIT_SVC_NONE or action >= AUDIT_SVC_LAST: action = AUDIT_NONE self._log(AUDIT_MESSAGES[action].format(cli=str(client), tag=tag, name=name))