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 22require_once dirname(__FILE__).'/include/config.inc.php'; 23require_once dirname(__FILE__).'/include/forms.inc.php'; 24require_once dirname(__FILE__).'/include/discovery.inc.php'; 25 26$page['title'] = _('Configuration of discovery rules'); 27$page['file'] = 'discoveryconf.php'; 28$page['type'] = detect_page_type(); 29 30require_once dirname(__FILE__).'/include/page_header.php'; 31 32// VAR TYPE OPTIONAL FLAGS VALIDATION EXCEPTION 33$fields = [ 34 'druleid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, 'isset({form}) && {form} == "update"'], 35 'name' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY, 'isset({add}) || isset({update})'], 36 'proxy_hostid' => [T_ZBX_INT, O_OPT, null, DB_ID, 'isset({add}) || isset({update})'], 37 'iprange' => [T_ZBX_STR, O_OPT, P_CRLF, null, 'isset({add}) || isset({update})'], 38 'delay' => [T_ZBX_INT, O_OPT, null, BETWEEN(1, SEC_PER_WEEK), 'isset({add}) || isset({update})'], 39 'status' => [T_ZBX_INT, O_OPT, null, IN('0,1'), null], 40 'uniqueness_criteria' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})', _('Device uniqueness criteria')], 41 'g_druleid' => [T_ZBX_INT, O_OPT, null, DB_ID, null], 42 'dchecks' => [null, O_OPT, null, null, null], 43 // actions 44 'action' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, 45 IN('"drule.massdelete","drule.massdisable","drule.massenable"'), 46 null 47 ], 48 'add' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 49 'update' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 50 'delete' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 51 'cancel' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 52 'form' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 53 'form_refresh' => [T_ZBX_INT, O_OPT, null, null, null], 54 'output' => [T_ZBX_STR, O_OPT, P_ACT, null, null], 55 'ajaxaction' => [T_ZBX_STR, O_OPT, P_ACT, null, null], 56 'ajaxdata' => [T_ZBX_STR, O_OPT, P_ACT, null, null], 57 // sort and sortorder 58 'sort' => [T_ZBX_STR, O_OPT, P_SYS, IN('"name"'), null], 59 'sortorder' => [T_ZBX_STR, O_OPT, P_SYS, IN('"'.ZBX_SORT_DOWN.'","'.ZBX_SORT_UP.'"'), null] 60]; 61check_fields($fields); 62 63$_REQUEST['status'] = isset($_REQUEST['status']) ? DRULE_STATUS_ACTIVE : DRULE_STATUS_DISABLED; 64$_REQUEST['dchecks'] = getRequest('dchecks', []); 65 66/* 67 * Permissions 68 */ 69if (isset($_REQUEST['druleid'])) { 70 $dbDRule = API::DRule()->get([ 71 'druleids' => getRequest('druleid'), 72 'output' => ['name', 'proxy_hostid', 'iprange', 'delay', 'status'], 73 'selectDChecks' => [ 74 'type', 'key_', 'snmp_community', 'ports', 'snmpv3_securityname', 'snmpv3_securitylevel', 75 'snmpv3_authpassphrase', 'snmpv3_privpassphrase', 'uniq', 'snmpv3_authprotocol', 'snmpv3_privprotocol', 76 'snmpv3_contextname' 77 ], 78 'editable' => true 79 ]); 80 if (empty($dbDRule)) { 81 access_deny(); 82 } 83} 84 85// ajax 86if (isset($_REQUEST['output']) && $_REQUEST['output'] == 'ajax') { 87 $ajaxResponse = new CAjaxResponse; 88 89 if (isset($_REQUEST['ajaxaction']) && $_REQUEST['ajaxaction'] == 'validate') { 90 $ajaxData = getRequest('ajaxdata', []); 91 $item_key_parser = new CItemKey(); 92 93 foreach ($ajaxData as $check) { 94 switch ($check['field']) { 95 case 'port': 96 if (!validate_port_list($check['value'])) { 97 $ajaxResponse->error(_('Incorrect port range.')); 98 } 99 break; 100 case 'itemKey': 101 if ($item_key_parser->parse($check['value']) != CParser::PARSE_SUCCESS) { 102 $ajaxResponse->error( 103 _s('Invalid key "%1$s": %2$s.', $check['value'], $item_key_parser->getError()) 104 ); 105 } 106 break; 107 } 108 } 109 } 110 111 $ajaxResponse->send(); 112 113 require_once dirname(__FILE__).'/include/page_footer.php'; 114 exit; 115} 116 117/* 118 * Action 119 */ 120if (hasRequest('add') || hasRequest('update')) { 121 $dChecks = getRequest('dchecks', []); 122 $uniq = getRequest('uniqueness_criteria', 0); 123 124 foreach ($dChecks as $dcnum => $check) { 125 if (substr($check['dcheckid'], 0, 3) === 'new') { 126 unset($dChecks[$dcnum]['dcheckid']); 127 } 128 129 $dChecks[$dcnum]['uniq'] = ($uniq == $dcnum) ? 1 : 0; 130 } 131 132 $discoveryRule = [ 133 'name' => getRequest('name'), 134 'proxy_hostid' => getRequest('proxy_hostid'), 135 'iprange' => getRequest('iprange'), 136 'delay' => getRequest('delay'), 137 'status' => getRequest('status'), 138 'dchecks' => $dChecks 139 ]; 140 141 DBStart(); 142 143 if (hasRequest('update')) { 144 $discoveryRule['druleid'] = getRequest('druleid'); 145 $result = API::DRule()->update($discoveryRule); 146 147 $messageSuccess = _('Discovery rule updated'); 148 $messageFailed = _('Cannot update discovery rule'); 149 $auditAction = AUDIT_ACTION_UPDATE; 150 } 151 else { 152 $result = API::DRule()->create($discoveryRule); 153 154 $messageSuccess = _('Discovery rule created'); 155 $messageFailed = _('Cannot create discovery rule'); 156 $auditAction = AUDIT_ACTION_ADD; 157 } 158 159 if ($result) { 160 $druleid = reset($result['druleids']); 161 add_audit($auditAction, AUDIT_RESOURCE_DISCOVERY_RULE, '['.$druleid.'] '.$discoveryRule['name']); 162 unset($_REQUEST['form']); 163 } 164 165 $result = DBend($result); 166 167 if ($result) { 168 uncheckTableRows(); 169 } 170 show_messages($result, $messageSuccess, $messageFailed); 171} 172elseif (isset($_REQUEST['delete']) && isset($_REQUEST['druleid'])) { 173 $result = API::DRule()->delete([$_REQUEST['druleid']]); 174 175 if ($result) { 176 unset($_REQUEST['form'], $_REQUEST['druleid']); 177 uncheckTableRows(); 178 } 179 show_messages($result, _('Discovery rule deleted'), _('Cannot delete discovery rule')); 180} 181elseif (hasRequest('action') && str_in_array(getRequest('action'), ['drule.massenable', 'drule.massdisable']) && hasRequest('g_druleid')) { 182 $result = true; 183 $enable = (getRequest('action') == 'drule.massenable'); 184 $status = $enable ? DRULE_STATUS_ACTIVE : DRULE_STATUS_DISABLED; 185 $auditAction = $enable ? AUDIT_ACTION_ENABLE : AUDIT_ACTION_DISABLE; 186 $updated = 0; 187 188 DBStart(); 189 190 foreach (getRequest('g_druleid') as $druleId) { 191 $result &= DBexecute('UPDATE drules SET status='.zbx_dbstr($status).' WHERE druleid='.zbx_dbstr($druleId)); 192 193 if ($result) { 194 $druleData = get_discovery_rule_by_druleid($druleId); 195 add_audit($auditAction, AUDIT_RESOURCE_DISCOVERY_RULE, '['.$druleId.'] '.$druleData['name']); 196 } 197 198 $updated++; 199 } 200 201 $messageSuccess = $enable 202 ? _n('Discovery rule enabled', 'Discovery rules enabled', $updated) 203 : _n('Discovery rule disabled', 'Discovery rules disabled', $updated); 204 $messageFailed = $enable 205 ? _n('Cannot enable discovery rule', 'Cannot enable discovery rules', $updated) 206 : _n('Cannot disable discovery rule', 'Cannot disable discovery rules', $updated); 207 208 $result = DBend($result); 209 210 if ($result) { 211 uncheckTableRows(); 212 } 213 show_messages($result, $messageSuccess, $messageFailed); 214} 215elseif (hasRequest('action') && getRequest('action') == 'drule.massdelete' && hasRequest('g_druleid')) { 216 $result = API::DRule()->delete(getRequest('g_druleid')); 217 218 if ($result) { 219 uncheckTableRows(); 220 } 221 show_messages($result, _('Discovery rules deleted'), _('Cannot delete discovery rules')); 222} 223 224/* 225 * Display 226 */ 227if (isset($_REQUEST['form'])) { 228 $data = [ 229 'druleid' => getRequest('druleid'), 230 'drule' => [], 231 'form' => getRequest('form'), 232 'form_refresh' => getRequest('form_refresh', 0) 233 ]; 234 235 // get drule 236 if (isset($data['druleid']) && !isset($_REQUEST['form_refresh'])) { 237 $data['drule'] = reset($dbDRule); 238 $data['drule']['uniqueness_criteria'] = -1; 239 240 if (!empty($data['drule']['dchecks'])) { 241 foreach ($data['drule']['dchecks'] as $id => $dcheck) { 242 if ($dcheck['uniq']) { 243 $data['drule']['uniqueness_criteria'] = $dcheck['dcheckid']; 244 } 245 } 246 } 247 } 248 else { 249 $data['drule']['proxy_hostid'] = getRequest('proxy_hostid', 0); 250 $data['drule']['name'] = getRequest('name', ''); 251 $data['drule']['iprange'] = getRequest('iprange', '192.168.0.1-254'); 252 $data['drule']['delay'] = getRequest('delay', SEC_PER_HOUR); 253 $data['drule']['status'] = getRequest('status', DRULE_STATUS_ACTIVE); 254 $data['drule']['dchecks'] = getRequest('dchecks', []); 255 $data['drule']['nextcheck'] = getRequest('nextcheck', 0); 256 $data['drule']['uniqueness_criteria'] = getRequest('uniqueness_criteria', -1); 257 } 258 259 if (!empty($data['drule']['dchecks'])) { 260 foreach ($data['drule']['dchecks'] as $id => $dcheck) { 261 $data['drule']['dchecks'][$id]['name'] = discovery_check2str( 262 $dcheck['type'], 263 isset($dcheck['key_']) ? $dcheck['key_'] : '', 264 isset($dcheck['ports']) ? $dcheck['ports'] : '' 265 ); 266 } 267 268 order_result($data['drule']['dchecks'], 'name'); 269 } 270 271 // get proxies 272 $data['proxies'] = API::Proxy()->get([ 273 'output' => API_OUTPUT_EXTEND 274 ]); 275 order_result($data['proxies'], 'host'); 276 277 // render view 278 $discoveryView = new CView('configuration.discovery.edit', $data); 279 $discoveryView->render(); 280 $discoveryView->show(); 281} 282else { 283 $sortField = getRequest('sort', CProfile::get('web.'.$page['file'].'.sort', 'name')); 284 $sortOrder = getRequest('sortorder', CProfile::get('web.'.$page['file'].'.sortorder', ZBX_SORT_UP)); 285 286 CProfile::update('web.'.$page['file'].'.sort', $sortField, PROFILE_TYPE_STR); 287 CProfile::update('web.'.$page['file'].'.sortorder', $sortOrder, PROFILE_TYPE_STR); 288 289 $config = select_config(); 290 291 $data = [ 292 'sort' => $sortField, 293 'sortorder' => $sortOrder 294 ]; 295 296 // get drules 297 $data['drules'] = API::DRule()->get([ 298 'output' => ['proxy_hostid', 'name', 'status', 'iprange', 'delay'], 299 'selectDChecks' => ['type'], 300 'editable' => true, 301 'sortfield' => $sortField, 302 'limit' => $config['search_limit'] + 1 303 ]); 304 305 if ($data['drules']) { 306 foreach ($data['drules'] as $key => $drule) { 307 // checks 308 $checks = []; 309 310 foreach ($drule['dchecks'] as $check) { 311 $checks[$check['type']] = discovery_check_type2str($check['type']); 312 } 313 314 order_result($checks); 315 316 $data['drules'][$key]['checks'] = $checks; 317 318 // description 319 $data['drules'][$key]['description'] = []; 320 321 if ($drule['proxy_hostid']) { 322 $proxy = get_host_by_hostid($drule['proxy_hostid']); 323 324 array_push($data['drules'][$key]['description'], $proxy['host'].NAME_DELIMITER); 325 } 326 } 327 328 order_result($data['drules'], $sortField, $sortOrder); 329 } 330 331 // get paging 332 $data['paging'] = getPagingLine($data['drules'], $sortOrder, new CUrl('discoveryconf.php')); 333 334 // render view 335 $discoveryView = new CView('configuration.discovery.list', $data); 336 $discoveryView->render(); 337 $discoveryView->show(); 338} 339 340require_once dirname(__FILE__).'/include/page_footer.php'; 341