chg: [internal] ECS: Add specific log for emails

pull/9465/head
Jakub Onderka 2023-12-27 21:42:00 +01:00
parent fe6e075b84
commit 2b159eb025
4 changed files with 82 additions and 11 deletions

View File

@ -555,14 +555,18 @@ class SendEmail
}
try {
return [
'contents' => $email->send(),
'encrypted' => $encrypted,
'subject' => $subject,
];
$content = $email->send();
} catch (Exception $e) {
throw new SendEmailException('The message could not be sent.', 0, $e);
}
return [
'to' => $user['User']['email'],
'message_id' => $email->messageId(),
'contents' => $content,
'encrypted' => $encrypted,
'subject' => $subject,
];
}
/**

View File

@ -1211,11 +1211,17 @@ class Log extends AppModel
return $this->elasticSearchClient;
}
/**
* @param $data
* @param $options
* @return array|bool|mixed
*/
public function saveOrFailSilently($data, $options = null)
{
try {
return $this->save($data, $options);
} catch (Exception $e) {
$this->logException('Could not save log to database', $e);
return false;
}
}

View File

@ -890,7 +890,11 @@ class User extends AppModel
$logTitle = $result['encrypted'] ? 'Encrypted email' : 'Email';
// Intentional two spaces to pass test :)
$logTitle .= $replyToLog . ' to ' . $user['User']['email'] . ' sent, titled "' . $result['subject'] . '".';
$logTitle .= $replyToLog . ' to ' . $result['to'] . ' sent, titled "' . $result['subject'] . '".';
if (Configure::read('Security.ecs_log')) {
EcsLog::writeEmailLog($logTitle, $result, $replyToUser ? $replyToUser['User']['email'] : null);
}
$log->create();
$log->saveOrFailSilently(array(

View File

@ -7,6 +7,8 @@ App::uses('JsonTool', 'Tools');
*/
class EcsLog implements CakeLogInterface
{
const ECS_VERSION = '8.11';
const SOCKET_PATH = '/run/vector';
/** @var false|resource */
@ -24,9 +26,9 @@ class EcsLog implements CakeLogInterface
public function write($type, $message)
{
$message = [
'@timestamp' => date('Y-m-d\TH:i:s.uP'),
'@timestamp' => self::timestamp(),
'ecs' => [
'version' => '8.11',
'version' => self::ECS_VERSION,
],
'event' => [
'kind' => 'event',
@ -52,10 +54,14 @@ class EcsLog implements CakeLogInterface
*/
public static function writeApplicationLog($type, $action, $message)
{
if ($action === 'email') {
return; // do not log email actions as it is logged with more details by `writeEmailLog` function
}
$message = [
'@timestamp' => date('Y-m-d\TH:i:s.uP'),
'@timestamp' => self::timestamp(),
'ecs' => [
'version' => '8.11',
'version' => self::ECS_VERSION,
],
'event' => [
'kind' => 'event',
@ -81,6 +87,47 @@ class EcsLog implements CakeLogInterface
static::writeMessage($message);
}
/**
* Include more meta information about email than would provide default `writeApplicationLog` log
* @param string $logTitle
* @param array $emailResult
* @param string|null $replyTo
* @return void
* @throws JsonException
*/
public static function writeEmailLog($logTitle, array $emailResult, $replyTo = null)
{
$message = [
'@timestamp' => self::timestamp(),
'ecs' => [
'version' => self::ECS_VERSION,
],
'event' => [
'kind' => 'event',
'provider' => 'misp',
'module' => 'application',
'dataset' => 'application.logs',
'category' => 'email',
'action' => 'email',
'type' => 'info',
],
'email' => [
'message_id' => $emailResult['message_id'],
'subject' => $emailResult['subject'],
'to' => [
'address' => $emailResult['to'],
],
],
'message' => $logTitle,
];
if ($replyTo) {
$message['email']['reply_to'] = ['address' => $replyTo];
}
static::writeMessage($message);
}
/**
* @return string|null
*/
@ -185,6 +232,14 @@ class EcsLog implements CakeLogInterface
return null;
}
/**
* @return string
*/
public static function timestamp()
{
return date('Y-m-d\TH:i:s.uP');
}
/**
* @param array $message
* @return void
@ -204,7 +259,9 @@ class EcsLog implements CakeLogInterface
// In case of failure, try reconnect and send log again
if ($bytesWritten === false) {
static::connect();
fwrite(static::$socket, $data);
if (static::$socket) {
fwrite(static::$socket, $data);
}
}
}
}