From a50b8dbc4e3751eddcd2d6570e54e6347f96dcc1 Mon Sep 17 00:00:00 2001 From: Sujith H Date: Tue, 21 Mar 2017 17:14:14 +0530 Subject: [PATCH] Separate audit logs from server logs. This change will help users to separate logs for each apps based on conditional logging. Changed usage of log.condition to log.conditions. Signed-off-by: Sujith H --- config/config.sample.php | 20 +++++++++--- lib/private/Log.php | 59 ++++++++++++++++++++++-------------- lib/private/Log/Owncloud.php | 12 ++++++-- tests/lib/LoggerTest.php | 18 +++++++++++ 4 files changed, 80 insertions(+), 29 deletions(-) diff --git a/config/config.sample.php b/config/config.sample.php index 2843eb0937f3..4f05c2bfe88f 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -602,13 +602,25 @@ * this condition is met * - ``apps``: if the log message is invoked by one of the specified apps, * this condition is met + * - ``logfile``: the log message invoked by the specified apps get redirected to + * this logfile, this condition is met + * Note: Not applicapable when using syslog. * * Defaults to an empty array. */ -'log.condition' => [ - 'shared_secret' => '57b58edb6637fe3059b3595cf9c41b9', - 'users' => ['sample-user'], - 'apps' => ['files'], +'log.conditions' => [ + [ + 'shared_secret' => '57b58edb6637fe3059b3595cf9c41b9', + 'users' => ['user1'], + 'apps' => ['files_texteditor'], + 'logfile' => '/tmp/test.log' + ], + [ + 'shared_secret' => '57b58edb6637fe3059b3595cf9c41b9', + 'users' => ['user1'], + 'apps' => ['gallery'], + 'logfile' => '/tmp/gallery.log' + ], ], /** diff --git a/lib/private/Log.php b/lib/private/Log.php index 068a9064f415..2c4b15fe5e47 100644 --- a/lib/private/Log.php +++ b/lib/private/Log.php @@ -230,7 +230,11 @@ public function debug($message, array $context = []) { */ public function log($level, $message, array $context = []) { $minLevel = min($this->config->getValue('loglevel', Util::WARN), Util::FATAL); - $logCondition = $this->config->getValue('log.condition', []); + $logConditions = $this->config->getValue('log.conditions', []); + if (empty($logConditions)) { + $logConditions[] = $this->config->getValue('log.condition', []); + } + $logConditionFile = null; array_walk($context, [$this->normalizer, 'format']); @@ -241,10 +245,17 @@ public function log($level, $message, array $context = []) { * check log condition based on the context of each log message * once this is met -> change the required log level to debug */ - if(!empty($logCondition) - && isset($logCondition['apps']) - && in_array($app, $logCondition['apps'], true)) { - $minLevel = Util::DEBUG; + if(!empty($logConditions)) { + foreach ($logConditions as $logCondition) { + if(!empty($logCondition['apps']) + && in_array($app, $logCondition['apps'], true)) { + $minLevel = Util::DEBUG; + if (!empty($logCondition['logfile'])) { + $logConditionFile = $logCondition['logfile']; + break; + } + } + } } } else { @@ -266,25 +277,29 @@ public function log($level, $message, array $context = []) { if($this->logConditionSatisfied === null) { // default to false to just process this once per request $this->logConditionSatisfied = false; - if(!empty($logCondition)) { - - // check for secret token in the request - if(isset($logCondition['shared_secret'])) { - $request = \OC::$server->getRequest(); - - // if token is found in the request change set the log condition to satisfied - if($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret'))) { - $this->logConditionSatisfied = true; + if(!empty($logConditions)) { + foreach ($logConditions as $logCondition) { + + // check for secret token in the request + if (!empty($logCondition['shared_secret'])) { + $request = \OC::$server->getRequest(); + + // if token is found in the request change set the log condition to satisfied + if ($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret'))) { + $this->logConditionSatisfied = true; + break; + } } - } - // check for user - if(isset($logCondition['users'])) { - $user = \OC::$server->getUserSession()->getUser(); + // check for user + if (!empty($logCondition['users'])) { + $user = \OC::$server->getUserSession()->getUser(); - // if the user matches set the log condition to satisfied - if($user !== null && in_array($user->getUID(), $logCondition['users'], true)) { - $this->logConditionSatisfied = true; + // if the user matches set the log condition to satisfied + if ($user !== null && in_array($user->getUID(), $logCondition['users'], true)) { + $this->logConditionSatisfied = true; + break; + } } } } @@ -297,7 +312,7 @@ public function log($level, $message, array $context = []) { if ($level >= $minLevel) { $logger = $this->logger; - call_user_func([$logger, 'write'], $app, $message, $level); + call_user_func([$logger, 'write'], $app, $message, $level, $logConditionFile); } } diff --git a/lib/private/Log/Owncloud.php b/lib/private/Log/Owncloud.php index c0342dcfb322..efe48c57cb61 100644 --- a/lib/private/Log/Owncloud.php +++ b/lib/private/Log/Owncloud.php @@ -67,8 +67,9 @@ public static function init() { * @param string $app * @param string $message * @param int $level + * @param string conditionalLogFile */ - public static function write($app, $message, $level) { + public static function write($app, $message, $level, $conditionalLogFile = null) { $config = \OC::$server->getSystemConfig(); // default to ISO8601 @@ -110,8 +111,13 @@ public static function write($app, $message, $level) { 'user' ); $entry = json_encode($entry); - $handle = @fopen(self::$logFile, 'a'); - @chmod(self::$logFile, 0640); + if (!is_null($conditionalLogFile)) { + $handle = @fopen($conditionalLogFile, 'a'); + @chmod($conditionalLogFile, 0640); + } else { + $handle = @fopen(self::$logFile, 'a'); + @chmod(self::$logFile, 0640); + } if ($handle) { fwrite($handle, $entry."\n"); fclose($handle); diff --git a/tests/lib/LoggerTest.php b/tests/lib/LoggerTest.php index d73de1c193e4..59f172e0c83a 100644 --- a/tests/lib/LoggerTest.php +++ b/tests/lib/LoggerTest.php @@ -59,6 +59,24 @@ public function testAppCondition() { $this->assertEquals($expected, $this->getLogs()); } + public function testAppLogCondition() { + $this->config->expects($this->any()) + ->method('getValue') + ->will(($this->returnValueMap([ + ['loglevel', Util::WARN, Util::WARN], + ['log.conditions', [], [['apps' => ['files'], 'logfile' => '/tmp/test.log']]] + ]))); + $logger = $this->logger; + + $logger->info('Don\'t display info messages'); + $logger->info('Show info messages of files app', ['app' => 'files']); + + $expected = [ + '1 Show info messages of files app', + ]; + $this->assertEquals($expected, $this->getLogs()); + } + private function getLogs() { return self::$logs; }