OwlCyberSecurity - MANAGER
Edit File: accounting.py
## # Copyright (c) 2006-2017 Apple Inc. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ## """ Extended account-specific logging. Allows different sub-systems to log data on a per-principal basis. """ __all__ = [ "accountingEnabled", "emitAccounting", ] import datetime import os from twext.python.log import Logger from twistedcaldav.config import config log = Logger() def accountingEnabled(category, record): """ Determine if accounting is enabled for the given category and record. """ return ( accountingEnabledForCategory(category) and accountingEnabledForRecord(record) ) def accountingEnabledForCategory(category): """ Determine if accounting is enabled for the given category. """ AccountingCategories = getattr(config, "AccountingCategories", None) if AccountingCategories is None: return False return AccountingCategories.get(category, False) def accountingEnabledForRecord(record): """ Determine if accounting is enabled for the given record. """ enabledRecordGUIDs = config.AccountingPrincipals if "*" in enabledRecordGUIDs: return True return record.uid in enabledRecordGUIDs def emitAccounting(category, record, data, tag=None, filename=None): """ Write the supplied data to the appropriate location for the given category and record. @param record: the record for whom a log entry is to be created. @type record: L{DirectoryRecord} @param category: accounting category @type category: C{tuple} @param data: data to write. @type data: C{str} """ if isinstance(record, str): principalLogPath = record elif accountingEnabled(category, record): ruid = record.uid.encode("utf-8") principalLogPath = os.path.join( ruid[0:2], ruid[2:4], ruid ) else: return None try: # # Obtain the accounting log file name # logRoot = config.AccountingLogRoot logDirectory = category if principalLogPath: logDirectory = os.path.join( logDirectory, principalLogPath, ) logFilename = os.path.join( logDirectory, datetime.datetime.now().isoformat() if filename is None else filename ) if not os.path.isdir(os.path.join(logRoot, logDirectory)): os.makedirs(os.path.join(logRoot, logDirectory)) if filename is None: logFilename = "%s-01" % (logFilename,) if tag: logFilename += " (%s)" % (tag,) logFilename += ".txt" else: if filename is None: index = 1 while True: path = "%s-%02d" % (logFilename, index) if tag: path += " (%s)" % (tag,) path += ".txt" if not os.path.isfile(os.path.join(logRoot, path)): logFilename = path break if index == 1000: log.error("Too many {cat} accounting files for {rec}", cat=category, rec=record) return None index += 1 # # Now write out the data to the log file # with open(os.path.join(logRoot, logFilename), "a") as logFile: logFile.write(data) return logFilename except OSError, e: # No failures in accounting should propagate out log.error("Failed to write accounting data due to: {ex}", ex=str(e)) return None