diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php index aeed05e8b4..8003e22667 100644 --- a/application/applicationextension.inc.php +++ b/application/applicationextension.inc.php @@ -1316,6 +1316,11 @@ interface iRestServiceProvider public function ExecOperation($sVersion, $sVerb, $aParams); } +interface iRestInputSanitizer +{ + public function SanitizeJsonInput(string $sJsonInput): string; +} + /** * Minimal REST response structure. Derive this structure to add response data and error codes. * @@ -1405,6 +1410,14 @@ class RestResult * @api */ public $message; + + /** + * Sanitize the content of this result to hide sensitive information + */ + public function SanitizeContent() + { + // The default implementation does nothing + } } /** diff --git a/core/restservices.class.inc.php b/core/restservices.class.inc.php index dbcc29e6ef..1808ee8e32 100644 --- a/core/restservices.class.inc.php +++ b/core/restservices.class.inc.php @@ -122,6 +122,18 @@ class ObjectResult { $this->fields[$sAttCode] = $this->MakeResultValue($oObject, $sAttCode, $bExtendedOutput); } + + public function SanitizeContent() + { + foreach($this->fields as $sAttCode => $value) + { + $oAttDef = MetaModel::GetAttributeDef($this->class, $sAttCode); + if ($oAttDef instanceof AttributeEncryptedString) + { + $this->fields[$sAttCode] = '******'; + } + } + } } @@ -181,6 +193,16 @@ class RestResultWithObjects extends RestResult $sObjKey = get_class($oObject).'::'.$oObject->GetKey(); $this->objects[$sObjKey] = $oObjRes; } + + public function SanitizeContent() + { + parent::SanitizeContent(); + + foreach($this->objects as $sObjKey => $oObjRes) + { + $oObjRes->SanitizeContent(); + } + } } class RestResultWithRelations extends RestResultWithObjects @@ -247,7 +269,7 @@ class RestDelete * * @package Core */ -class CoreServices implements iRestServiceProvider +class CoreServices implements iRestServiceProvider, iRestInputSanitizer { /** * Enumerate services delivered by this class @@ -663,6 +685,12 @@ class CoreServices implements iRestServiceProvider } return $oResult; } + + public function SanitizeJsonInput(string $sJsonInput): string + { + //TODO + return 'TODO: sanitized input'; + } /** * Helper for object deletion diff --git a/webservices/rest.php b/webservices/rest.php index d68c95e84b..3fb15093f6 100644 --- a/webservices/rest.php +++ b/webservices/rest.php @@ -209,6 +209,13 @@ try /** @var iRestServiceProvider $oRS */ $oRS = $aOpToRestService[$sOperation]['service_provider']; $sProvider = get_class($oRS); + + if ($oRS instanceof iRestInputSanitizer) { + $sSanitizedJsonInput = $oRS->SanitizeJsonInput($sJsonString); + } + else { + $sSanitizedJsonInput = $sJsonString; + } CMDBObject::SetTrackOrigin('webservice-rest'); $oResult = $oRS->ExecOperation($sVersion, $sOperation, $aJsonData); @@ -267,7 +274,7 @@ if (MetaModel::GetConfig()->Get('log_rest_service')) $oLog->SetTrim('userinfo', UserRights::GetUser()); $oLog->Set('version', $sVersion); $oLog->Set('operation', $sOperation); - $oLog->SetTrim('json_input', $sJsonString); + $oLog->SetTrim('json_input', $sSanitizedJsonInput); $oLog->Set('provider', $sProvider); $sMessage = $oResult->message; @@ -277,7 +284,8 @@ if (MetaModel::GetConfig()->Get('log_rest_service')) } $oLog->SetTrim('message', $sMessage); $oLog->Set('code', $oResult->code); - $oLog->SetTrim('json_output', $sResponse); + $oResult->SanitizeContent(); + $oLog->SetTrim('json_output', json_encode($oResult)); $oLog->DBInsertNoReload(); $oKPI->ComputeAndReport('Log inserted');