Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Petry <vincent@nextcloud.com>2022-08-05 15:09:55 +0300
committerGitHub <noreply@github.com>2022-08-05 15:09:55 +0300
commitcbd5cef2cccded7806067cb22549a1d50d35cd59 (patch)
treeed58169e35606e49a72e211e3b997c31337f4f51
parent5f40bd106ed81d681167e747f0d62dede8bf3672 (diff)
parent6941c91531b78a6898abe85ab74225b892bf8b06 (diff)
Merge pull request #33398 from nextcloud/enh/noid/sensitive-methods-apps
allow apps to specify methods carrying sensitive parameters
-rw-r--r--lib/private/AppFramework/Bootstrap/RegistrationContext.php23
-rw-r--r--lib/private/Log.php39
-rw-r--r--lib/private/Log/ExceptionSerializer.php13
-rw-r--r--lib/public/AppFramework/Bootstrap/IRegistrationContext.php11
-rw-r--r--tests/lib/Log/ExceptionSerializerTest.php16
5 files changed, 92 insertions, 10 deletions
diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
index 8f6aff228e1..c98f968c999 100644
--- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php
+++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
@@ -121,6 +121,9 @@ class RegistrationContext {
/** @var ServiceRegistration<ICalendarProvider>[] */
private $calendarProviders = [];
+ /** @var ParameterRegistration[] */
+ private $sensitiveMethods = [];
+
/** @var LoggerInterface */
private $logger;
@@ -304,6 +307,14 @@ class RegistrationContext {
$migratorClass
);
}
+
+ public function registerSensitiveMethods(string $class, array $methods): void {
+ $this->context->registerSensitiveMethods(
+ $this->appId,
+ $class,
+ $methods
+ );
+ }
};
}
@@ -430,6 +441,11 @@ class RegistrationContext {
$this->userMigrators[] = new ServiceRegistration($appId, $migratorClass);
}
+ public function registerSensitiveMethods(string $appId, string $class, array $methods): void {
+ $methods = array_filter($methods, 'is_string');
+ $this->sensitiveMethods[] = new ParameterRegistration($appId, $class, $methods);
+ }
+
/**
* @param App[] $apps
*/
@@ -712,4 +728,11 @@ class RegistrationContext {
public function getUserMigrators(): array {
return $this->userMigrators;
}
+
+ /**
+ * @return ParameterRegistration[]
+ */
+ public function getSensitiveMethods(): array {
+ return $this->sensitiveMethods;
+ }
}
diff --git a/lib/private/Log.php b/lib/private/Log.php
index 95e0a833b66..4ab647bc6c1 100644
--- a/lib/private/Log.php
+++ b/lib/private/Log.php
@@ -36,8 +36,11 @@ declare(strict_types=1);
*/
namespace OC;
+use Exception;
use Nextcloud\LogNormalizer\Normalizer;
+use OC\AppFramework\Bootstrap\Coordinator;
use OCP\Log\IDataLogger;
+use Throwable;
use function array_merge;
use OC\Log\ExceptionSerializer;
use OCP\ILogger;
@@ -228,7 +231,7 @@ class Log implements ILogger, IDataLogger {
$this->crashReporters->delegateBreadcrumb($entry['message'], 'log', $context);
}
}
- } catch (\Throwable $e) {
+ } catch (Throwable $e) {
// make sure we dont hard crash if logging fails
}
}
@@ -300,19 +303,19 @@ class Log implements ILogger, IDataLogger {
/**
* Logs an exception very detailed
*
- * @param \Exception|\Throwable $exception
+ * @param Exception|Throwable $exception
* @param array $context
* @return void
* @since 8.2.0
*/
- public function logException(\Throwable $exception, array $context = []) {
+ public function logException(Throwable $exception, array $context = []) {
$app = $context['app'] ?? 'no app in context';
$level = $context['level'] ?? ILogger::ERROR;
// if an error is raised before the autoloader is properly setup, we can't serialize exceptions
try {
- $serializer = new ExceptionSerializer($this->config);
- } catch (\Throwable $e) {
+ $serializer = $this->getSerializer();
+ } catch (Throwable $e) {
$this->error("Failed to load ExceptionSerializer serializer while trying to log " . $exception->getMessage());
return;
}
@@ -338,7 +341,7 @@ class Log implements ILogger, IDataLogger {
if (!is_null($this->crashReporters)) {
$this->crashReporters->delegateReport($exception, $context);
}
- } catch (\Throwable $e) {
+ } catch (Throwable $e) {
// make sure we dont hard crash if logging fails
}
}
@@ -361,7 +364,7 @@ class Log implements ILogger, IDataLogger {
}
$context['level'] = $level;
- } catch (\Throwable $e) {
+ } catch (Throwable $e) {
// make sure we dont hard crash if logging fails
}
}
@@ -401,4 +404,26 @@ class Log implements ILogger, IDataLogger {
}
return array_merge(array_diff_key($context, $usedContextKeys), [$messageKey => strtr($message, $replace)]);
}
+
+ /**
+ * @throws Throwable
+ */
+ protected function getSerializer(): ExceptionSerializer {
+ $serializer = new ExceptionSerializer($this->config);
+ try {
+ /** @var Coordinator $coordinator */
+ $coordinator = \OCP\Server::get(Coordinator::class);
+ foreach ($coordinator->getRegistrationContext()->getSensitiveMethods() as $registration) {
+ $serializer->enlistSensitiveMethods($registration->getName(), $registration->getValue());
+ }
+ // For not every app might be initialized at this time, we cannot assume that the return value
+ // of getSensitiveMethods() is complete. Running delegates in Coordinator::registerApps() is
+ // not possible due to dependencies on the one hand. On the other it would work only with
+ // adding public methods to the PsrLoggerAdapter and this class.
+ // Thus, serializer cannot be a property.
+ } catch (Throwable $t) {
+ // ignore app-defined sensitive methods in this case - they weren't loaded anyway
+ }
+ return $serializer;
+ }
}
diff --git a/lib/private/Log/ExceptionSerializer.php b/lib/private/Log/ExceptionSerializer.php
index 3c3ff95f8e1..aaf6a39235e 100644
--- a/lib/private/Log/ExceptionSerializer.php
+++ b/lib/private/Log/ExceptionSerializer.php
@@ -109,7 +109,7 @@ class ExceptionSerializer {
$this->systemConfig = $systemConfig;
}
- public const methodsWithSensitiveParametersByClass = [
+ protected array $methodsWithSensitiveParametersByClass = [
SetupController::class => [
'run',
'display',
@@ -190,8 +190,8 @@ class ExceptionSerializer {
$sensitiveValues = [];
$trace = array_map(function (array $traceLine) use (&$sensitiveValues) {
$className = $traceLine['class'] ?? '';
- if ($className && isset(self::methodsWithSensitiveParametersByClass[$className])
- && in_array($traceLine['function'], self::methodsWithSensitiveParametersByClass[$className], true)) {
+ if ($className && isset($this->methodsWithSensitiveParametersByClass[$className])
+ && in_array($traceLine['function'], $this->methodsWithSensitiveParametersByClass[$className], true)) {
return $this->editTrace($sensitiveValues, $traceLine);
}
foreach (self::methodsWithSensitiveParameters as $sensitiveMethod) {
@@ -289,4 +289,11 @@ class ExceptionSerializer {
return $data;
}
+
+ public function enlistSensitiveMethods(string $class, array $methods): void {
+ if (!isset($this->methodsWithSensitiveParametersByClass[$class])) {
+ $this->methodsWithSensitiveParametersByClass[$class] = [];
+ }
+ $this->methodsWithSensitiveParametersByClass[$class] = array_merge($this->methodsWithSensitiveParametersByClass[$class], $methods);
+ }
}
diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
index a5d675f14c7..6b10d7bfc0f 100644
--- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
+++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
@@ -306,4 +306,15 @@ interface IRegistrationContext {
* @since 24.0.0
*/
public function registerUserMigrator(string $migratorClass): void;
+
+ /**
+ * Announce methods of classes that may contain sensitive values, which
+ * should be obfuscated before being logged.
+ *
+ * @param string $class
+ * @param string[] $methods
+ * @return void
+ * @since 25.0.0
+ */
+ public function registerSensitiveMethods(string $class, array $methods): void;
}
diff --git a/tests/lib/Log/ExceptionSerializerTest.php b/tests/lib/Log/ExceptionSerializerTest.php
index 70ac80d13e3..209214a6832 100644
--- a/tests/lib/Log/ExceptionSerializerTest.php
+++ b/tests/lib/Log/ExceptionSerializerTest.php
@@ -48,6 +48,10 @@ class ExceptionSerializerTest extends TestCase {
throw new \Exception('my exception');
}
+ private function customMagicAuthThing(string $login, string $parole): void {
+ throw new \Exception('expected custom auth exception');
+ }
+
/**
* this test ensures that the serializer does not overwrite referenced
* variables. It is crafted after a scenario we experienced: the DAV server
@@ -65,4 +69,16 @@ class ExceptionSerializerTest extends TestCase {
$this->assertSame(ExceptionSerializer::SENSITIVE_VALUE_PLACEHOLDER, $serializedData['Trace'][0]['args'][0]);
}
}
+
+ public function testSerializerWithRegisteredMethods() {
+ $this->serializer->enlistSensitiveMethods(self::class, ['customMagicAuthThing']);
+ try {
+ $this->customMagicAuthThing('u57474', 'Secret');
+ } catch (\Exception $e) {
+ $serializedData = $this->serializer->serializeException($e);
+ $this->assertSame('customMagicAuthThing', $serializedData['Trace'][0]['function']);
+ $this->assertSame(ExceptionSerializer::SENSITIVE_VALUE_PLACEHOLDER, $serializedData['Trace'][0]['args'][0]);
+ $this->assertFalse(isset($serializedData['Trace'][0]['args'][1]));
+ }
+ }
}