1<?php 2/* 3** Zabbix 4** Copyright (C) 2001-2021 Zabbix SIA 5** 6** This program is free software; you can redistribute it and/or modify 7** it under the terms of the GNU General Public License as published by 8** the Free Software Foundation; either version 2 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU General Public License for more details. 15** 16** You should have received a copy of the GNU General Public License 17** along with this program; if not, write to the Free Software 18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19**/ 20 21 22class CAudit { 23 24 /** 25 * Add simple audit record. 26 * 27 * @param string $userid 28 * @param string $ip 29 * @param int $action AUDIT_ACTION_* 30 * @param int $resourcetype AUDIT_RESOURCE_* 31 * @param string $details 32 */ 33 static public function addDetails($userid, $ip, $action, $resourcetype, $details = '') { 34 DB::insert('auditlog', [[ 35 'userid' => $userid, 36 'clock' => time(), 37 'ip' => substr($ip, 0, 39), 38 'action' => $action, 39 'resourcetype' => $resourcetype, 40 'details' => $details 41 ]]); 42 } 43 44 /** 45 * Add audit records. 46 * 47 * @param string $userid 48 * @param string $ip 49 * @param int $action AUDIT_ACTION_* 50 * @param int $resourcetype AUDIT_RESOURCE_* 51 * @param array $objects 52 * @param array $objects_old 53 */ 54 static public function addBulk($userid, $ip, $action, $resourcetype, array $objects, array $objects_old = null) { 55 $masked_fields = [ 56 'users' => ['passwd' => true] 57 ]; 58 59 switch ($resourcetype) { 60 case AUDIT_RESOURCE_ACTION: 61 $field_name_resourceid = 'actionid'; 62 $field_name_resourcename = 'name'; 63 $table_name = 'actions'; 64 break; 65 66 case AUDIT_RESOURCE_APPLICATION: 67 $field_name_resourceid = 'applicationid'; 68 $field_name_resourcename = 'name'; 69 $table_name = 'applications'; 70 break; 71 72 case AUDIT_RESOURCE_CORRELATION: 73 $field_name_resourceid = 'correlationid'; 74 $field_name_resourcename = 'name'; 75 $table_name = 'correlation'; 76 break; 77 78 case AUDIT_RESOURCE_DASHBOARD: 79 $field_name_resourceid = 'dashboardid'; 80 $field_name_resourcename = 'name'; 81 $table_name = 'dashboard'; 82 break; 83 84 case AUDIT_RESOURCE_DISCOVERY_RULE: 85 $field_name_resourceid = 'druleid'; 86 $field_name_resourcename = 'name'; 87 $table_name = 'drules'; 88 break; 89 90 case AUDIT_RESOURCE_GRAPH: 91 case AUDIT_RESOURCE_GRAPH_PROTOTYPE: 92 $field_name_resourceid = 'graphid'; 93 $field_name_resourcename = 'name'; 94 $table_name = 'graphs'; 95 break; 96 97 case AUDIT_RESOURCE_HOST_PROTOTYPE: 98 $field_name_resourceid = 'hostid'; 99 $field_name_resourcename = 'host'; 100 $table_name = 'hosts'; 101 break; 102 103 case AUDIT_RESOURCE_HOST_GROUP: 104 $field_name_resourceid = 'groupid'; 105 $field_name_resourcename = 'name'; 106 $table_name = 'groups'; 107 break; 108 109 case AUDIT_RESOURCE_ICON_MAP: 110 $field_name_resourceid = 'iconmapid'; 111 $field_name_resourcename = 'name'; 112 $table_name = 'icon_map'; 113 break; 114 115 case AUDIT_RESOURCE_ITEM: 116 case AUDIT_RESOURCE_ITEM_PROTOTYPE: 117 $field_name_resourceid = 'itemid'; 118 $field_name_resourcename = 'name'; 119 $table_name = 'items'; 120 break; 121 122 case AUDIT_RESOURCE_MACRO: 123 $field_name_resourceid = 'globalmacroid'; 124 $field_name_resourcename = 'macro'; 125 $table_name = 'globalmacro'; 126 break; 127 128 case AUDIT_RESOURCE_MAINTENANCE: 129 $field_name_resourceid = 'maintenanceid'; 130 $field_name_resourcename = 'name'; 131 $table_name = 'maintenances'; 132 break; 133 134 case AUDIT_RESOURCE_PROXY: 135 $field_name_resourceid = 'proxyid'; 136 $field_name_resourcename = 'host'; 137 $table_name = 'hosts'; 138 break; 139 140 case AUDIT_RESOURCE_SCENARIO: 141 $field_name_resourceid = 'httptestid'; 142 $field_name_resourcename = 'name'; 143 $table_name = 'httptest'; 144 break; 145 146 case AUDIT_RESOURCE_SCRIPT: 147 $field_name_resourceid = 'scriptid'; 148 $field_name_resourcename = 'name'; 149 $table_name = 'scripts'; 150 break; 151 152 case AUDIT_RESOURCE_TRIGGER: 153 case AUDIT_RESOURCE_TRIGGER_PROTOTYPE: 154 $field_name_resourceid = 'triggerid'; 155 $field_name_resourcename = 'description'; 156 $table_name = 'triggers'; 157 break; 158 159 case AUDIT_RESOURCE_USER: 160 $field_name_resourceid = 'userid'; 161 $field_name_resourcename = 'alias'; 162 $table_name = 'users'; 163 break; 164 165 case AUDIT_RESOURCE_USER_GROUP: 166 $field_name_resourceid = 'usrgrpid'; 167 $field_name_resourcename = 'name'; 168 $table_name = 'usrgrp'; 169 break; 170 171 case AUDIT_RESOURCE_VALUE_MAP: 172 $field_name_resourceid = 'valuemapid'; 173 $field_name_resourcename = 'name'; 174 $table_name = 'valuemaps'; 175 break; 176 177 case AUDIT_RESOURCE_HOST: 178 $field_name_resourceid = 'hostid'; 179 $field_name_resourcename = 'host'; 180 $table_name = 'hosts'; 181 break; 182 183 case AUDIT_RESOURCE_TEMPLATE: 184 $field_name_resourceid = 'templateid'; 185 $field_name_resourcename = 'host'; 186 $table_name = 'hosts'; 187 break; 188 189 default: 190 return; 191 } 192 193 $clock = time(); 194 $ip = substr($ip, 0, 39); 195 196 $auditlog = []; 197 $objects_diff = []; 198 199 foreach ($objects as $object) { 200 $resourceid = $object[$field_name_resourceid]; 201 202 if ($action == AUDIT_ACTION_UPDATE) { 203 $object_old = $objects_old[$resourceid]; 204 205 /** 206 * Convert two dimension array to one dimension array, 207 * because array_diff and array_intersect work only with one dimension array. 208 */ 209 $object_old = array_filter($object_old, function ($val) { 210 return !is_array($val); 211 }); 212 $object = array_filter($object, function ($val) { 213 return !is_array($val); 214 }); 215 216 $object_diff = array_diff_assoc(array_intersect_key($object_old, $object), $object); 217 218 if (!$object_diff) { 219 continue; 220 } 221 222 foreach ($object_diff as $field_name => &$values) { 223 if (array_key_exists($table_name, $masked_fields) 224 && array_key_exists($field_name, $masked_fields[$table_name])) { 225 $object_old[$field_name] = '********'; 226 $object[$field_name] = '********'; 227 } 228 229 $values = [ 230 'old' => $object_old[$field_name], 231 'new' => $object[$field_name] 232 ]; 233 234 } 235 unset($values); 236 237 $objects_diff[] = $object_diff; 238 239 $resourcename = $object_old[$field_name_resourcename]; 240 } 241 else { 242 $resourcename = $object[$field_name_resourcename]; 243 } 244 245 if (mb_strlen($resourcename) > 255) { 246 $resourcename = mb_substr($resourcename, 0, 252).'...'; 247 } 248 249 $auditlog[] = [ 250 'userid' => $userid, 251 'clock' => $clock, 252 'ip' => $ip, 253 'action' => $action, 254 'resourcetype' => $resourcetype, 255 'resourceid' => $resourceid, 256 'resourcename' => $resourcename 257 ]; 258 } 259 260 if ($auditlog) { 261 $auditids = DB::insertBatch('auditlog', $auditlog); 262 263 if ($action == AUDIT_ACTION_UPDATE) { 264 $auditlog_details = []; 265 266 foreach ($objects_diff as $index => $object_diff) { 267 foreach ($object_diff as $field_name => $values) { 268 $auditlog_details[] = [ 269 'auditid' => $auditids[$index], 270 'table_name' => $table_name, 271 'field_name' => $field_name, 272 'oldvalue' => $values['old'], 273 'newvalue' => $values['new'] 274 ]; 275 } 276 } 277 278 DB::insertBatch('auditlog_details', $auditlog_details); 279 } 280 } 281 } 282} 283