You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
8.5 KiB
247 lines
8.5 KiB
1 year ago
|
<?php
|
||
|
/*
|
||
|
** Zabbix
|
||
|
** Copyright (C) 2001-2023 Zabbix SIA
|
||
|
**
|
||
|
** This program is free software; you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation; either version 2 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program; if not, write to the Free Software
|
||
|
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
**/
|
||
|
|
||
|
|
||
|
class CAuditOld {
|
||
|
private const AUDITLOG_ENABLE = 1;
|
||
|
|
||
|
/**
|
||
|
* Supported resources list, every record contains:
|
||
|
* resource id field name
|
||
|
* resource name field name
|
||
|
* resource table name
|
||
|
* resource API name
|
||
|
*/
|
||
|
private static $supported_type = [
|
||
|
CAudit::RESOURCE_ACTION => ['actionid', 'name', 'actions', 'action'],
|
||
|
CAudit::RESOURCE_AUTHENTICATION => ['configid', null, 'config', 'authentication'],
|
||
|
CAudit::RESOURCE_AUTH_TOKEN => ['tokenid', 'name', 'token', 'token'],
|
||
|
CAudit::RESOURCE_AUTOREGISTRATION => ['configid', null, 'config', 'autoregistration'],
|
||
|
CAudit::RESOURCE_CORRELATION => ['correlationid', 'name', 'correlation', 'correlation'],
|
||
|
CAudit::RESOURCE_DASHBOARD => ['dashboardid', 'name', 'dashboard', 'dashboard'],
|
||
|
CAudit::RESOURCE_DISCOVERY_RULE => ['druleid', 'name', 'drules', 'drule'],
|
||
|
CAudit::RESOURCE_GRAPH => ['graphid', 'name', 'graphs', 'graph'],
|
||
|
CAudit::RESOURCE_GRAPH_PROTOTYPE => ['graphid', 'name', 'graphs', 'graphprototype'],
|
||
|
CAudit::RESOURCE_HOST => ['hostid', 'name', 'hosts', 'host'],
|
||
|
CAudit::RESOURCE_HOST_GROUP => ['groupid', 'name', 'groups', 'hostgroup'],
|
||
|
CAudit::RESOURCE_HOST_PROTOTYPE => ['hostid', 'host', 'hosts', 'hostprototype'],
|
||
|
CAudit::RESOURCE_HOUSEKEEPING => ['configid', null, 'config', 'housekeeping'],
|
||
|
CAudit::RESOURCE_ICON_MAP => ['iconmapid', 'name', 'icon_map', 'iconmap'],
|
||
|
CAudit::RESOURCE_IMAGE => ['imageid', 'name', 'images', 'image'],
|
||
|
CAudit::RESOURCE_IT_SERVICE => ['serviceid', 'name', 'services', 'service'],
|
||
|
CAudit::RESOURCE_ITEM => ['itemid', 'name', 'items', 'item'],
|
||
|
CAudit::RESOURCE_ITEM_PROTOTYPE => ['itemid', 'name', 'items', 'itemprototype'],
|
||
|
CAudit::RESOURCE_MACRO => ['globalmacroid', 'macro', 'globalmacro', 'usermacro'],
|
||
|
CAudit::RESOURCE_MAINTENANCE => ['maintenanceid', 'name', 'maintenances', 'maintenance'],
|
||
|
CAudit::RESOURCE_MAP => ['sysmapid', 'name', 'sysmaps', 'map'],
|
||
|
CAudit::RESOURCE_MEDIA_TYPE => ['mediatypeid', 'name', 'media_type', 'mediatype'],
|
||
|
CAudit::RESOURCE_MODULE => ['moduleid', 'id', 'module', 'module'],
|
||
|
CAudit::RESOURCE_PROXY => ['proxyid', 'name', 'proxy', 'proxy'],
|
||
|
CAudit::RESOURCE_SCENARIO => ['httptestid', 'name', 'httptest', 'httptest'],
|
||
|
CAudit::RESOURCE_SCHEDULED_REPORT => ['reportid', 'name', 'report', 'report'],
|
||
|
CAudit::RESOURCE_SCRIPT => ['scriptid', 'name', 'scripts', 'script'],
|
||
|
CAudit::RESOURCE_SETTINGS => ['configid', null, 'config', 'settings'],
|
||
|
CAudit::RESOURCE_TEMPLATE => ['templateid', 'name', 'hosts', 'template'],
|
||
|
CAudit::RESOURCE_TRIGGER => ['triggerid', 'description', 'triggers', 'trigger'],
|
||
|
CAudit::RESOURCE_TRIGGER_PROTOTYPE => ['triggerid', 'description', 'triggers', 'triggerprototype'],
|
||
|
CAudit::RESOURCE_USER => ['userid', 'username', 'users', 'user'],
|
||
|
CAudit::RESOURCE_USER_GROUP => ['usrgrpid', 'name', 'usrgrp', 'usergroup'],
|
||
|
CAudit::RESOURCE_USER_ROLE => ['roleid', 'name', 'role', 'role'],
|
||
|
CAudit::RESOURCE_VALUE_MAP => ['valuemapid', 'name', 'valuemaps', 'valuemap'],
|
||
|
CAudit::RESOURCE_TEMPLATE_DASHBOARD => ['dashboardid', 'name', 'dashboard', 'templatedashboard']
|
||
|
];
|
||
|
|
||
|
private static $masked_fields = [
|
||
|
'config' => [
|
||
|
'fields' => ['tls_psk_identity' => true, 'tls_psk' => true]
|
||
|
],
|
||
|
'globalmacro' => [
|
||
|
'fields' => ['value' => true],
|
||
|
'conditions' => ['type' => ZBX_MACRO_TYPE_SECRET]
|
||
|
],
|
||
|
'hosts' => [
|
||
|
'fields' => ['tls_psk_identity' => true, 'tls_psk' => true]
|
||
|
],
|
||
|
'media_type' => [
|
||
|
'fields' => ['passwd' => true]
|
||
|
],
|
||
|
'token' => [
|
||
|
'fields' => ['token' => true]
|
||
|
],
|
||
|
'users' => [
|
||
|
'fields' => ['passwd' => true]
|
||
|
]
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* Add simple audit record.
|
||
|
*
|
||
|
* @param string $userid
|
||
|
* @param string $ip
|
||
|
* @param int $action AUDIT_ACTION_*
|
||
|
* @param int $resourcetype AUDIT_RESOURCE_*
|
||
|
* @param string $note
|
||
|
*/
|
||
|
// static public function addDetails($userid, $ip, $action, $resourcetype, $note = '') {
|
||
|
// DB::insert('auditlog', [[
|
||
|
// 'userid' => $userid,
|
||
|
// 'clock' => time(),
|
||
|
// 'ip' => substr($ip, 0, 39),
|
||
|
// 'action' => $action,
|
||
|
// 'resourcetype' => $resourcetype,
|
||
|
// 'note' => $note
|
||
|
// ]]);
|
||
|
// }
|
||
|
|
||
|
private static function getRecordSetId(): string {
|
||
|
static $recordsetid = null;
|
||
|
|
||
|
if ($recordsetid === null) {
|
||
|
$recordsetid = CCuid::generate();
|
||
|
}
|
||
|
|
||
|
return $recordsetid;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add audit records.
|
||
|
*
|
||
|
* @param string $userid
|
||
|
* @param string $ip
|
||
|
* @param string $username
|
||
|
* @param int $action CAudit::ACTION_*
|
||
|
* @param int $resourcetype CAudit::RESOURCE_*
|
||
|
* @param array $objects
|
||
|
* @param array $objects_old
|
||
|
*/
|
||
|
public static function addBulk(string $userid, string $ip, string $username, int $action, int $resourcetype,
|
||
|
array $objects, array $objects_old = null) {
|
||
|
if (!array_key_exists($resourcetype, self::$supported_type)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (CSettingsHelper::get(CSettingsHelper::AUDITLOG_ENABLED) != self::AUDITLOG_ENABLE
|
||
|
&& ($resourcetype != CAudit::RESOURCE_SETTINGS
|
||
|
|| !array_key_exists(CSettingsHelper::AUDITLOG_ENABLED, current($objects)))) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$recordsetid = self::getRecordSetId();
|
||
|
|
||
|
[$field_name_resourceid, $field_name_resourcename, $table_name, $api_name] = self::$supported_type[$resourcetype];
|
||
|
|
||
|
$clock = time();
|
||
|
$ip = substr($ip, 0, 39);
|
||
|
|
||
|
$auditlog = [];
|
||
|
|
||
|
foreach ($objects as $object) {
|
||
|
$resourceid = $object[$field_name_resourceid];
|
||
|
$diff = '';
|
||
|
|
||
|
if ($action == CAudit::ACTION_UPDATE) {
|
||
|
$object_old = $objects_old[$resourceid];
|
||
|
|
||
|
/**
|
||
|
* Convert two dimension array to one dimension array,
|
||
|
* because array_diff and array_intersect work only with one dimension array.
|
||
|
*/
|
||
|
$object_old = array_filter($object_old, function ($val) {
|
||
|
return !is_array($val);
|
||
|
});
|
||
|
$object = array_filter($object, function ($val) {
|
||
|
return !is_array($val);
|
||
|
});
|
||
|
|
||
|
$object_diff = array_diff_assoc(array_intersect_key($object_old, $object), $object);
|
||
|
|
||
|
if (!$object_diff) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (array_key_exists($table_name, self::$masked_fields)) {
|
||
|
$table_masked_fields = self::$masked_fields[$table_name]['fields'];
|
||
|
$mask_object_old = true;
|
||
|
$mask_object = true;
|
||
|
|
||
|
if (array_key_exists('conditions', self::$masked_fields[$table_name])) {
|
||
|
foreach (self::$masked_fields[$table_name]['conditions'] as $field_name => $value) {
|
||
|
if ($mask_object_old) {
|
||
|
$mask_object_old = ($object_old[$field_name] == $value);
|
||
|
}
|
||
|
if ($mask_object) {
|
||
|
$mask_object = array_key_exists($field_name, $object)
|
||
|
? ($object[$field_name] == $value)
|
||
|
: ($object_old[$field_name] == $value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
$table_masked_fields = [];
|
||
|
$mask_object_old = false;
|
||
|
$mask_object = false;
|
||
|
}
|
||
|
|
||
|
$details = [];
|
||
|
|
||
|
foreach (array_keys($object_diff) as $field_name) {
|
||
|
if (array_key_exists($field_name, $table_masked_fields)) {
|
||
|
if ($mask_object_old) {
|
||
|
$object_old[$field_name] = ZBX_SECRET_MASK;
|
||
|
}
|
||
|
if ($mask_object) {
|
||
|
$object[$field_name] = ZBX_SECRET_MASK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$details[$api_name.'.'.$field_name] = ['update', $object[$field_name], $object_old[$field_name]];
|
||
|
}
|
||
|
|
||
|
$diff = json_encode($details);
|
||
|
|
||
|
$resourcename = ($field_name_resourcename !== null) ? $object_old[$field_name_resourcename] : '';
|
||
|
}
|
||
|
else {
|
||
|
$resourcename = ($field_name_resourcename !== null) ? $object[$field_name_resourcename] : '';
|
||
|
}
|
||
|
|
||
|
if (mb_strlen($resourcename) > 255) {
|
||
|
$resourcename = mb_substr($resourcename, 0, 252).'...';
|
||
|
}
|
||
|
|
||
|
$auditlog[] = [
|
||
|
'userid' => $userid,
|
||
|
'username' => $username,
|
||
|
'clock' => $clock,
|
||
|
'ip' => $ip,
|
||
|
'action' => $action,
|
||
|
'resourcetype' => $resourcetype,
|
||
|
'resourceid' => $resourceid,
|
||
|
'resourcename' => $resourcename,
|
||
|
'recordsetid' => $recordsetid,
|
||
|
'details' => $diff
|
||
|
];
|
||
|
}
|
||
|
|
||
|
DB::insertBatch('auditlog', $auditlog);
|
||
|
}
|
||
|
}
|