function process_syslog($entry, $update) { global $config; global $rules; global $device_rules; global $maint; foreach ($config['syslog']['filter'] as $bi) { if (strpos($entry['msg'], $bi) !== FALSE) { //echo('D-'.$bi); return FALSE; } } $entry['msg_orig'] = $entry['msg']; // Initial rewrites $entry['host'] = strtolower(trim($entry['host'])); // Rewrite priority and level from strings to numbers $entry['priority'] = priority_string_to_numeric($entry['priority']); $entry['level'] = priority_string_to_numeric($entry['level']); $entry['device_id'] = get_cache($entry['host'], 'device_id'); //print_vars($entry); //print_vars($GLOBALS['dev_cache']); if ($entry['device_id']) { $os = get_cache($entry['host'], 'os'); $os_group = get_cache($entry['host'], 'os_group'); if (in_array($os, array('ios', 'iosxe', 'catos', 'asa'))) { $matches = array(); # if (preg_match('#%(?P<program>.*):( ?)(?P<msg>.*)#', $entry['msg'], $matches)) { # $entry['msg'] = $matches['msg']; # $entry['program'] = $matches['program']; # } # unset($matches); //NOTE. Please include examples for syslog entries, to know why need some preg_replace() if (strstr($entry['msg'], '%')) { //10.0.0.210||23||4||4||26644:||2013-11-08 07:19:24|| 033884: Nov 8 07:19:23.993: %FW-4-TCP_OoO_SEG: Dropping TCP Segment: seq:-1169729434 1500 bytes is out-of-order; expected seq:3124765814. Reason: TCP reassembly queue overflow - session 10.10.32.37:56316 to 93.186.239.142:80 on zone-pair Local->Internet class All_Inspection||26644 //hostname||17||5||5||192462650:||2014-06-17 11:16:01|| %SSH-5-SSH2_SESSION: SSH2 Session request from 10.95.0.42 (tty = 0) using crypto cipher 'aes256-cbc', hmac 'hmac-sha1' Succeeded||192462650 if (strpos($entry['msg'], ': %')) { list(, $entry['msg']) = explode(': %', $entry['msg'], 2); $entry['msg'] = "%" . $entry['msg']; } $entry['msg'] = preg_replace("/^%(.+?):\\ /", "\\1||", $entry['msg']); } else { $entry['msg'] = preg_replace("/^.*[0-9]:/", "", $entry['msg']); $entry['msg'] = preg_replace("/^[0-9][0-9]\\ [A-Z]{3}:/", "", $entry['msg']); $entry['msg'] = preg_replace("/^(.+?):\\ /", "\\1||", $entry['msg']); } //$entry['msg'] = preg_replace("/^.+\.[0-9]{3}:/", "", $entry['msg']); /// FIXME. Show which entries this should replace. It's broke all entries with 'IP:PORT'. $entry['msg'] = preg_replace("/^.+-Traceback=/", "Traceback||", $entry['msg']); list($entry['program'], $entry['msg']) = explode("||", $entry['msg'], 2); $entry['msg'] = preg_replace("/^[0-9]+:/", "", $entry['msg']); if (!$entry['program']) { $entry['msg'] = preg_replace("/^([0-9A-Z\\-]+?):\\ /", "\\1||", $entry['msg']); list($entry['program'], $entry['msg']) = explode("||", $entry['msg'], 2); } if (!$entry['msg']) { $entry['msg'] = $entry['program']; unset($entry['program']); } } else { if ($os == 'iosxr') { //1.1.1.1||23||5||5||920:||2014-11-26 17:29:48||RP/0/RSP0/CPU0:Nov 26 16:29:48.161 : bgp[1046]: %ROUTING-BGP-5-ADJCHANGE : neighbor 1.1.1.2 Up (VRF: default) (AS: 11111) ||920 //1.1.1.2||23||6||6||253:||2014-11-26 17:30:21||RP/0/RSP0/CPU0:Nov 26 16:30:21.710 : SSHD_[65755]: %SECURITY-SSHD-6-INFO_GENERAL : Client closes socket connection ||253 //1.1.1.3||local0||err||err||83||2015-01-14 07:29:45||oly-er-01 LC/0/0/CPU0:Jan 14 07:29:45.556 CET: pfilter_ea[301]: %L2-PFILTER_EA-3-ERR_IM_CAPS : uidb set acl failed on interface Bundle-Ether1.1501.ip43696. (null) ||94795 list(, $entry['msg']) = explode(': %', $entry['msg'], 2); list($entry['program'], $entry['msg']) = explode(' : ', $entry['msg'], 2); } else { if ($os == 'linux' && get_cache($entry['host'], 'version') == 'Point') { // Cisco WAP200 and similar $matches = array(); if (preg_match('#Log: \\[(?P<program>.*)\\] - (?P<msg>.*)#', $entry['msg'], $matches)) { $entry['msg'] = $matches['msg']; $entry['program'] = $matches['program']; } unset($matches); } else { if ($os_group == 'unix') { $matches = array(); // User_CommonName/123.213.132.231:39872 VERIFY OK: depth=1, /C=PL/ST=Malopolska/O=VLO/CN=v-lo.krakow.pl/emailAddress=root@v-lo.krakow.pl if ($entry['facility'] == 'daemon' && preg_match('#/([0-9]{1,3}\\.) {3}[0-9]{1,3}:[0-9]{4,} ([A-Z]([A-Za-z])+( ?)) {2,}:#', $entry['msg'])) { $entry['program'] = 'OpenVPN'; } else { if ($entry['facility'] == 'mail' && preg_match('/^(((pop3|imap)\\-login)|((POP3|IMAP)\\(.*\\))):/', $entry['msg'])) { $entry['program'] = 'Dovecot'; } else { if (preg_match('/^(?P<program>(\\S((\\(|\\[).*(\\)|\\])))):(?P<msg>.*)$/', $entry['msg'], $matches)) { $entry['msg'] = $matches['msg']; $entry['program'] = $matches['program']; } else { if (preg_match('/^(?P<program>[^\\s\\(\\[]*):\\ (?P<msg>.*)$/', $entry['msg'], $matches)) { $entry['msg'] = $matches['msg']; $entry['program'] = $matches['program']; } else { if (!empty($entry['program']) && preg_match('/^.*:\\ ' . $entry['program'] . ':\\ (?P<msg>[^(]+\\((?P<program>[^:]+):.*)$/', $entry['msg'], $matches)) { $entry['msg'] = $matches['msg']; $entry['program'] = $matches['program']; } else { if (empty($entry['program']) && !empty($entry['facility'])) { $entry['program'] = $entry['facility']; } } } } } } unset($matches); } else { if ($os == 'ftos') { if (empty($entry['program'])) { //1.1.1.1||23||5||5||||2014-11-23 21:48:10|| Nov 23 21:48:10.745: hostname: %STKUNIT0-M:CP %SEC-5-LOGOUT: Exec session is terminated for user rancid on line vty0|| list(, , $entry['program'], $entry['msg']) = explode(': ', $entry['msg'], 4); list(, $entry['program']) = explode(' %', $entry['program'], 2); } //Jun 3 02:33:23.489: %STKUNIT0-M:CP %SNMP-3-SNMP_AUTH_FAIL: SNMP Authentication failure for SNMP request from host 176.10.35.241 //Jun 1 17:11:50.806: %STKUNIT0-M:CP %ARPMGR-2-MAC_CHANGE: IP-4-ADDRMOVE: IP address 11.222.30.53 is moved from MAC address 52:54:00:7b:37:ad to MAC address 52:54:00:e4:ec:06 . //if (strpos($entry['msg'], '%STKUNIT') === 0) //{ // list(, $entry['program'], $entry['msg']) = explode(': ', $entry['msg'], 3); // //$entry['timestamp'] = date("Y-m-d H:i:s", strtotime($entry['timestamp'])); // convert to timestamp // list(, $entry['program']) = explode(' %', $entry['program'], 2); //} } else { if ($os == 'netscaler') { //10/03/2013:16:49:07 GMT dk-lb001a PPE-4 : UI CMD_EXECUTED 10367926 : User so_readonly - Remote_ip 10.70.66.56 - Command "stat lb vserver" - Status "Success" list(, , , $entry['msg']) = explode(' ', $entry['msg'], 4); list($entry['program'], $entry['msg']) = explode(' : ', $entry['msg'], 3); } } } } } } if ($entry['program'] == '') { /** FIXME, WHAT? Pls examples. $entry['program'] = $entry['msg']; unset($entry['msg']); */ if ($entry['msg'] == '') { // Something wrong, both program and msg empty return $entry; } } else { if (strpos($entry['program'], '(BZ2') === 0) { // Wtf is BZ2LR and BZ@.. /** *Old: 10.10.34.10||3||6||6||hostapd:||2014-07-18 11:29:35|| ath2: STA c8:dd:c9:d1:d4:aa IEEE 802.11: associated||hostapd *New: 10.10.34.10||3||6||6||(BZ2LR,00272250c1cd,v3.2.5.2791)||2014-12-12 09:36:39|| hostapd: ath2: STA dc:a9:71:1b:d6:c7 IEEE 802.11: associated||(BZ2LR,00272250c1cd,v3.2.5.2791) */ list($entry['program'], $entry['msg']) = explode(': ', $entry['msg'], 2); } } $entry['program'] = strtoupper($entry['program']); array_walk($entry, 'trim'); if ($update) { $log_id = dbInsert(array('device_id' => $entry['device_id'], 'host' => $entry['host'], 'program' => $entry['program'], 'facility' => $entry['facility'], 'priority' => $entry['priority'], 'level' => $entry['level'], 'tag' => $entry['tag'], 'msg' => $entry['msg'], 'timestamp' => $entry['timestamp']), 'syslog'); } //$req_dump = print_r(array($entry, $rules, $device_rules), TRUE); //$fp = fopen('/tmp/syslog.log', 'a'); //fwrite($fp, $req_dump); //fclose($fp); $notification_type = 'syslog'; /// FIXME, I not know how 'syslog_rules_assoc' is filled, I pass rules to all devices /// FIXME, this is copy-pasted from above, while not have WUI for syslog_rules_assoc foreach ($rules as $la_id => $rule) { if ((empty($device_rules) || isset($device_rules[$entry['device_id']][$la_id])) && preg_match($rule['la_rule'], $entry['msg_orig'])) { // Mark no notification during maintenance if (isset($maint['device'][$entry['device_id']]) || isset($maint['global']) && $maint['global'] > 0) { $notified = '-1'; } else { $notified = '0'; } $log_id = dbInsert(array('device_id' => $entry['device_id'], 'la_id' => $la_id, 'syslog_id' => $log_id, 'timestamp' => $entry['timestamp'], 'program' => $entry['program'], 'message' => $entry['msg_orig'], 'notified' => $notified), 'syslog_alerts'); // Get contacts for $la_id $transports = get_alert_contacts($entry['device_id'], $la_id, $notification_type); // Add notification to queue if ($notified != '-1' && !empty($transports)) { $device = device_by_id_cache($entry['device_id']); $message_tags = array('ALERT_STATE' => "SYSLOG", 'ALERT_URL' => generate_url(array('page' => 'device', 'device' => $device['device_id'], 'tab' => 'alert', 'entity_type' => 'syslog')), 'ALERT_ID' => $la_id, 'ALERT_MESSAGE' => $rule['la_descr'], 'CONDITIONS' => $rule['la_rule'], 'METRICS' => $entry['msg'], 'SYSLOG_RULE' => $rule['la_rule'], 'SYSLOG_MESSAGE' => $entry['msg'], 'SYSLOG_PROGRAM' => $entry['program'], 'TIMESTAMP' => $entry['timestamp'], 'DEVICE_HOSTNAME' => $device['hostname'], 'DEVICE_LINK' => generate_device_link($device), 'DEVICE_HARDWARE' => $device['hardware'], 'DEVICE_OS' => $device['os_text'] . ' ' . $device['version'] . ' ' . $device['features'], 'DEVICE_LOCATION' => $device['location'], 'DEVICE_UPTIME' => deviceUptime($device)); $message_tags['TITLE'] = alert_generate_subject($device, 'SYSLOG', $message_tags); $notification = array('device_id' => $entry['device_id'], 'log_id' => $log_id, 'aca_type' => $notification_type, 'severity' => $entry['priority'], 'endpoints' => json_encode($transports), 'notification_added' => time(), 'notification_lifetime' => 300, 'notification_entry' => json_encode($entry)); //unset($message_tags['ENTITY_GRAPHS_ARRAY']); $notification['message_tags'] = json_encode($message_tags); $notification_id = dbInsert($notification, 'notifications_queue'); } } } unset($os); } else { if ($config['syslog']['unknown_hosts']) { if ($update) { array_walk($entry, 'trim'); // Store entries for unknown hosts with NULL device_id $log_id = dbInsert(array('host' => $entry['host'], 'program' => $entry['program'], 'facility' => $entry['facility'], 'priority' => $entry['priority'], 'level' => $entry['level'], 'tag' => $entry['tag'], 'msg' => $entry['msg'], 'timestamp' => $entry['timestamp']), 'syslog'); //var_dump($entry); } } } return $entry; }
/** * Generate notifications for an alert entry * * @param array entry * @return NULL */ function alert_notifier($entry, $type = "alert") { global $config, $alert_rules; $device = device_by_id_cache($entry['device_id']); $alert = $alert_rules[$entry['alert_test_id']]; $state = json_decode($entry['state'], TRUE); $conditions = json_decode($alert['conditions'], TRUE); $entity = get_entity_by_id_cache($entry['entity_type'], $entry['entity_id']); $condition_array = array(); foreach ($state['failed'] as $failed) { $condition_array[] = $failed['metric'] . " " . $failed['condition'] . " " . $failed['value'] . " (" . $state['metrics'][$failed['metric']] . ")"; } $metric_array = array(); foreach ($state['metrics'] as $metric => $value) { $metric_array[] = $metric . ' = ' . $value; } $graphs = array(); $graph_done = array(); foreach ($state['metrics'] as $metric => $value) { if ($config['email']['graphs'] !== FALSE && is_array($config['entities'][$entry['entity_type']]['metric_graphs'][$metric]) && !in_array($config['entities'][$entry['entity_type']]['metric_graphs'][$metric]['type'], $graph_done)) { $graph_array = $config['entities'][$entry['entity_type']]['metric_graphs'][$metric]; foreach ($graph_array as $key => $val) { // Check to see if we need to do any substitution if (substr($val, 0, 1) == '@') { $nval = substr($val, 1); //echo(" replaced " . $val . " with " . $entity[$nval] . " from entity. " . PHP_EOL . "<br />"); $graph_array[$key] = $entity[$nval]; } } $image_data_uri = generate_alert_graph($graph_array); $image_url = generate_graph_url($graph_array); $graphs[] = array('label' => $graph_array['type'], 'type' => $graph_array['type'], 'url' => $image_url, 'data' => $image_data_uri); $graph_done[] = $graph_array['type']; } unset($graph_array); } if ($config['email']['graphs'] !== FALSE && count($graph_done) == 0 && is_array($config['entities'][$entry['entity_type']]['graph'])) { // We can draw a graph for this type/metric pair! $graph_array = $config['entities'][$entry['entity_type']]['graph']; foreach ($graph_array as $key => $val) { // Check to see if we need to do any substitution if (substr($val, 0, 1) == '@') { $nval = substr($val, 1); //echo(" replaced ".$val." with ". $entity[$nval] ." from entity. ".PHP_EOL."<br />"); $graph_array[$key] = $entity[$nval]; } } //print_vars($graph_array); $image_data_uri = generate_alert_graph($graph_array); $image_url = generate_graph_url($graph_array); $graphs[] = array('label' => $graph_array['type'], 'type' => $graph_array['type'], 'url' => $image_url, 'data' => $image_data_uri); unset($graph_array); } $graphs_html = ""; foreach ($graphs as $graph) { $graphs_html .= '<h4>' . $graph['type'] . '</h4>'; $graphs_html .= '<a href="' . $graph['url'] . '"><img src="' . $graph['data'] . '"></a><br />'; } //print_vars($graphs); //print_vars($graphs_html); //print_vars($entry); $message_tags = array('ALERT_STATE' => $entry['alert_status'] == '1' ? "RECOVER" : "ALERT", 'ALERT_URL' => generate_url(array('page' => 'device', 'device' => $device['device_id'], 'tab' => 'alert', 'alert_entry' => $entry['alert_table_id'])), 'ALERT_ID' => $entry['alert_table_id'], 'ALERT_MESSAGE' => $alert['alert_message'], 'CONDITIONS' => implode(PHP_EOL . ' ', $condition_array), 'METRICS' => implode(PHP_EOL . ' ', $metric_array), 'DURATION' => $entry['alert_status'] == '1' ? $entry['last_ok'] > 0 ? formatUptime(time() - $entry['last_ok']) . " (" . format_unixtime($entry['last_ok']) . ")" : "Unknown" : ($entry['last_ok'] > 0 ? formatUptime(time() - $entry['last_ok']) . " (" . format_unixtime($entry['last_ok']) . ")" : "Unknown"), 'ENTITY_LINK' => generate_entity_link($entry['entity_type'], $entry['entity_id'], $entity['entity_name']), 'ENTITY_NAME' => $entity['entity_name'], 'ENTITY_TYPE' => $alert['entity_type'], 'ENTITY_DESCRIPTION' => $entity['entity_descr'], 'ENTITY_GRAPHS_ARRAY' => json_encode($graphs), 'DEVICE_HOSTNAME' => $device['hostname'], 'DEVICE_LINK' => generate_device_link($device), 'DEVICE_HARDWARE' => $device['hardware'], 'DEVICE_OS' => $device['os_text'] . ' ' . $device['version'] . ' ' . $device['features'], 'DEVICE_LOCATION' => $device['location'], 'DEVICE_UPTIME' => deviceUptime($device)); //logfile('debug.log', var_export($message, TRUE)); $title = alert_generate_subject($device, $message_tags['ALERT_STATE'], $message_tags); $message_tags['TITLE'] = $title; $alert_id = $entry['alert_test_id']; $notify_status = FALSE; // Set alert notify status to FALSE by default $notification_type = 'alert'; $transports = get_alert_contacts($device, $alert_id, $notification_type); if (!empty($transports)) { // WARNING, alerts queue currently experimental if (isset($config['alerts']['queue']) && isset($config['alerts']['queue'])) { // Add notification to queue $notification = array('device_id' => $device['device_id'], 'log_id' => $log_id, 'aca_type' => $notification_type, 'endpoints' => json_encode($transports), 'message_graphs' => $message_tags['ENTITY_GRAPHS_ARRAY'], 'notification_added' => time(), 'notification_lifetime' => 300, 'notification_entry' => json_encode($entry)); $notification_message_tags = $message_tags; unset($notification_message_tags['ENTITY_GRAPHS_ARRAY']); $notification['message_tags'] = json_encode($notification_message_tags); $notification_id = dbInsert($notification, 'notifications_queue'); } else { // Use classic instant notifications send $notification_count = 0; foreach ($transports as $method => $endpoints) { if (isset($config['alerts']['disable'][$method]) && $config['alerts']['disable'][$method]) { continue; } // Skip if method disabled globally foreach ($endpoints as $endpoint) { $method_include = $config['install_dir'] . "/includes/alerting/" . $method . ".inc.php"; if (is_file($method_include)) { print_cli_data("Notifying", "[" . $method . "] " . $endpoint['contact_descr'] . ": " . $endpoint['contact_endpoint']); // Split out endpoint data as stored JSON in the database into array for use in transport // The original string also remains available as the contact_endpoint key foreach (json_decode($endpoint['contact_endpoint']) as $field => $value) { $endpoint[$field] = $value; } include $method_include; // FIXME check success // FIXME log notification + success/failure! if ($notify_status['success']) { $notification_count++; } } else { print_cli_data("Missing include", $method_include); } } } if ($notification_count) { dbUpdate(array('notified' => 1), 'alert_log', '`event_id` = ?', array($notification['log_id'])); } } } }