diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4f4773f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.php diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..9754ad5 --- /dev/null +++ b/.htaccess @@ -0,0 +1,22 @@ + + +RewriteEngine on + +# passthroughs +RewriteRule ^index.php$ - [L] +RewriteRule ^(css|js|app|test)/.*$ - [L] +RewriteRule ^(css|js|app|test)/.*$ - [L] + +# redirect errors +ErrorDocument 400 /error/400/ +ErrorDocument 401 /error/401/ +ErrorDocument 403 /error/403/ +ErrorDocument 404 /error/404/ +ErrorDocument 500 /error/500/ + +# Rewrites +RewriteRule ^(.*)/(.*)/(.*)/$ index.php?app=$1&page=$2&id1=$3 [L] +RewriteRule ^(.*)/(.*)/$ index.php?app=$1&page=$2 [L] +RewriteRule ^(.*)/$ index.php?app=$1 [L] + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..dcd6eb0 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +## php-snmptraps + +###### php snmptrap handler and web UI for management + +php-snmptraps is an php trpahandler that processes snmp traps, writes them to database and/or file and sends +notifications via sms/email/pushover to users, based on web settings. + +It comes with nice HMTL5 UI: +..* Dashboard that shows overview of last messages +..* Displays messages sent by specific host +..* Displays messages per severity +..* Displays specific messages received +..* Live update of received traps + +and more. + +You can set severity level for each received message, ignore specific message types, create maintaneance periods +for hosts, set per-user quiet hours and more. + + +Notifications are set per-user/severity, by default aupported are: +..* Email notification +..* Pushover notification +..* SMS notification + +The can be easily extended to any other custom notification type. diff --git a/app/dashboard/index.php b/app/dashboard/index.php new file mode 100644 index 0000000..929f14e --- /dev/null +++ b/app/dashboard/index.php @@ -0,0 +1,89 @@ +check_user_session(); + +# set limit +$Trap->reset_print_limit (30); +# fetch all traps for each +$all_error_traps = $Trap->fetch_traps (array("emergency", "alert", "critical")); + +$Trap->reset_print_limit (13); +$all_warning_traps = $Trap->fetch_traps (array("error", "warning")); +$all_info_traps = $Trap->fetch_traps (array("notice", "informational", "debug")); +$all_unknown_traps = $Trap->fetch_traps (array("unknown")); + +# set fields +$tfields = array( "id"=>"", + "hostname"=>"Hostname", + "ip"=>"IP address", + "date"=>"Date", + "message"=>"Message", + "severity"=>"Severity" + ); +$Table_print->set_snmp_table_fields ($tfields); + +# structure +print "
"; + +# critical +print "
"; +print "
"; +print "

Emergency, Critical and Alert events

"; +print "
"; +print ""; +if ($all_error_traps!==false) { $Table_print->print_snmp_table ($all_error_traps); } +else { print ""; } +print "
".$Result->show("info", "No messages found", false, false, true)."
"; +print "
"; +print "
"; +print "
"; + +# warning, info +print "
"; +print "
"; +print "

Error and Warning events

"; +print "
"; +print ""; +if ($all_warning_traps!==false) { $Table_print->print_snmp_table ($all_warning_traps); } +else { print ""; } +print "
".$Result->show("info", "No messages found", false, false, true)."
"; +print "
"; +print "
"; +print "
"; + +print "
"; +print "
"; +print "

Informational, Notice and Debug events

"; +print "
"; +print ""; +if ($all_info_traps!==false) { $Table_print->print_snmp_table ($all_info_traps); } +else { print ""; } +print "
".$Result->show("info", "No messages found", false, false, true)."
"; +print "
"; +print "
"; +print "
"; + +# unknown +print "
"; +print "
"; +print "

Unknown severity events

"; +print "
"; +print ""; +if ($all_unknown_traps!==false) { $Table_print->print_snmp_table ($all_unknown_traps); } +else { print ""; } +print "
".$Result->show("info", "No messages found", false, false, true)."
"; +print "
"; +print "
"; +print "
"; + +print "
"; + + +?> \ No newline at end of file diff --git a/app/footer.php b/app/footer.php new file mode 100644 index 0000000..c9a03c2 --- /dev/null +++ b/app/footer.php @@ -0,0 +1 @@ +php-snmptrap management \ No newline at end of file diff --git a/app/host/index.php b/app/host/index.php new file mode 100644 index 0000000..8b0310a --- /dev/null +++ b/app/host/index.php @@ -0,0 +1,78 @@ +check_user_session(); + +# set limit to 10 +$Trap->reset_print_limit (200); + +# fetch all traps +if(isset($_GET['page'])) { + $all_traps = $Trap->fetch_traps_host ($_GET['page']); +} + +# fetch all unique hosts +$unique_hosts = $Trap->fetch_unique_hosts (); + +# print badges if page set +if (isset($_GET['page'])) { + # print title + print "

Traps for host $_GET[page]

"; + + # badges + print "
"; + print "
"; + print "
"; + foreach ($unique_hosts as $h) { + // ignore unknown + if ($h->hostname!="") { + // active + $active = $h->hostname==$_GET['page'] ? "badge-active" : ""; + // print + print "$h->hostname"; + } + } + print "
"; + print "
"; + print "

"; + + + # set fields + $tfields = array( "id"=>"", + "hostname"=>"Hostname", + "ip"=>"IP address", + "date"=>"Date", + "message"=>"Message", + "severity"=>"Severity", + "content"=>"Content" + ); + $Table_print->set_snmp_table_fields ($tfields); + + + # print table + print ""; + $Table_print->print_snmp_table ($all_traps); + print "
"; +} +else { + # print title + print "

Select host

"; + + foreach ($unique_hosts as $h) { + // ignore unknown + if ($h->hostname!="") { + // active + $active = $h->hostname==$_GET['page'] ? "badge-active" : ""; + // print + print "$h->hostname"; + } + } + +} +?> \ No newline at end of file diff --git a/app/live/index.php b/app/live/index.php new file mode 100644 index 0000000..9291d5c --- /dev/null +++ b/app/live/index.php @@ -0,0 +1,72 @@ +check_user_session(); + +# set limit to 10 +$Trap->reset_print_limit (200); + +# fetch all traps +$traps = $Trap->fetch_traps ("all"); + + +# set fields +$tfields = array( "id"=>"", + "hostname"=>"Hostname", + "ip"=>"IP address", + "date"=>"Date", + "message"=>"Message", + "severity"=>"Severity", + "content"=>"Content" + ); +$Table_print->set_snmp_table_fields ($tfields); + +# structure +print "
"; + +# critical +print "

Live message update


"; +print "
Messages will be updated each 15 seconds
"; +print ""; +$Table_print->print_snmp_table ($traps); +print "
"; + +print "
"; + +?> + + + diff --git a/app/live/update.php b/app/live/update.php new file mode 100644 index 0000000..ced14f7 --- /dev/null +++ b/app/live/update.php @@ -0,0 +1,48 @@ +check_user_session(); + +# fetch all traps +$traps = $Trap->get_new_traps ($_POST['id']); + +# false - no new items +if ($traps!==false) { + + # set fields + $tfields = array( "id"=>"", + "hostname"=>"Hostname", + "ip"=>"IP address", + "date"=>"Date", + "message"=>"Message", + "severity"=>"Severity", + "content"=>"Content" + ); + $Table_print->set_snmp_table_fields ($tfields); + + # Print new items + $Table_print->print_snmp_table ($traps, false, false); + +} +else { + print "False"; +} +?> \ No newline at end of file diff --git a/app/login/index.php b/app/login/index.php new file mode 100644 index 0000000..822a6c8 --- /dev/null +++ b/app/login/index.php @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + Snmptraps + + + + + + + + + + + + + + + + + +
+ + +
...
+ + +
+ +
+ + + +
+
+

Login to phptrapd server

+
+
Please enter your username / password to login to system. In case of any issues please contact system administrator!
+ + +
+
+ + + +
+ + + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/app/login/login-form.php b/app/login/login-form.php new file mode 100644 index 0000000..0f6957f --- /dev/null +++ b/app/login/login-form.php @@ -0,0 +1,45 @@ +
+
+ + +
+
+ +
+ + +
+
+ + "; + } + ?> +
+
+
+ +
+ +
+ +
+ + + +
+is_authenticated() ) { + # print result + if($_GET['app']=="timeout") { $Result->show("success", _('You session has timed out')); } + else { $Result->show("success", _('You have logged out')); } + # destroy session + $User->destroy_session(); +} +?> +
diff --git a/app/login/login_check.php b/app/login/login_check.php new file mode 100644 index 0000000..2be680c --- /dev/null +++ b/app/login/login_check.php @@ -0,0 +1,32 @@ +strip_input_tags ($_POST); + +# Authenticate +if( !empty($_POST['trapusername']) && !empty($_POST['trappassword']) ) { + # all good, try to authentucate user + $User->authenticate ($_POST['trapusername'], $_POST['trappassword']); +} +# Username / pass not provided +else { + $Result->show("danger", _('Please enter your username and password'), true); +} +?> diff --git a/app/message/edit-submit.php b/app/message/edit-submit.php new file mode 100644 index 0000000..830922e --- /dev/null +++ b/app/message/edit-submit.php @@ -0,0 +1,27 @@ +check_user_session(); + +/* +print "
";
+var_dump($_POST);
+die('alert-danger');
+*/
+
+# execute
+if ($_POST['action']=="define")     { $Trap_update->update_trap ($_POST['action'], $_POST); }
+elseif ($_POST['action']=="delete") { $Trap_update->update_trap ($_POST['action'], $_POST); }
+elseif ($_POST['action']=="ignore") { $Trap_update->update_trap ($_POST['action'], $_POST); }
+else                                { $Result->show ("warning", "Not implemented yet !", false); }
+?>
\ No newline at end of file
diff --git a/app/message/edit.php b/app/message/edit.php
new file mode 100644
index 0000000..00b7e78
--- /dev/null
+++ b/app/message/edit.php
@@ -0,0 +1,190 @@
+check_user_session();
+
+# fetch item
+$item = $Trap->fetch_snmp_trap ($_GET['id']);
+
+
+# validate
+if ($item!==false) {
+    // set title
+    $title = ucwords($_GET['action'])." message";
+    // footer text
+    $btn_text = ucwords($_GET['action']);
+
+
+    // add exception
+    if ($_GET['action']=="ignore") {
+
+        // distinct hosts
+        $uniq = $Common->fetch_unique_items ("traps", "hostname");
+        if ($uniq!==false) {
+            foreach ($uniq as $u) {
+                $unique_hosts[] = $u->hostname;
+            }
+            // add all
+            $unique_hosts = array_filter(array_merge(array("all"=>"all"), $unique_hosts));
+        }
+
+        // title
+        $title = "Ignore message";
+
+        // content
+        $html[] = "Here you define for some OID to be excluded from processing. All existing records with this OID will be deleted.

"; + + $html[] = ""; + + // save content + $content = implode("\n", $html); + } + // define + elseif ($_GET['action']=="define") { + // title + $title = "Define severity for message"; + + // content + $html[] = "Here you can change severities for OID messages. All existing records with this OID will be updated.

"; + + $html[] = ""; + + // save content + $content = implode("\n", $html); + + } + // delete all + elseif ($_GET['action']=="delete") { + // title + $title = "Delete all traps for oid"; + + // content + $html[] = "Here you can remove all traps for specific OID. All existing records with this OID will be removed. If content is defined than it will search by content also.

"; + + $html[] = ""; + + // save content + $content = implode("\n", $html); + } + // false + else { + $title = "Error"; + $btn_text = ""; + $content = $Result->show ("danger", _('Invalid action'), false, false, true); + } +} +else { + $title = "Error"; + $btn_text = ""; + $content = $Result->show ("danger", _('Invalid item'), false, false, true); +} + + + +# print modal +$Modal->modal_print ($title, $content, $btn_text, "app/message/edit-submit.php"); +?> \ No newline at end of file diff --git a/app/message/index.php b/app/message/index.php new file mode 100644 index 0000000..71df644 --- /dev/null +++ b/app/message/index.php @@ -0,0 +1,81 @@ +check_user_session(); + +# set limit to 10 +$Trap->reset_print_limit (200); + +# decode +$_GET['page'] = base64_decode($_GET['page']); + +# fetch all traps +if(isset($_GET['page'])) { + $all_traps = $Trap->fetch_traps_message ($_GET['page']); + + # get first item and output description + if($all_traps!==false) { + $msg_description = $Trap->fetch_snmp_trap ($all_traps[0]->id);; + + # process oid + if ($msg_description!==false) { + $Trap->process_oid ($msg_description->oid); + // set additional items + $msg_description->trap_description = strlen($Trap->trap_description)>0 ? str_replace("\n", "", $Trap->trap_description) : "/"; + $msg_description->trap_objects = is_array($Trap->trap_objects) ? " - ".implode("
- ", $Trap->trap_objects) : "/"; + $msg_description->mib_file_name = strlen($Trap->mib_file_name)>0 ? $Trap->mib_file_name : "/"; + + # set fields + $tfields = array( "message"=>"Message", + "oid"=>"OID", + "severity"=>"Severity", + "trap_objects"=>"Trap objects", + "trap_description"=>"Trap description", + "mib_file_name"=>"MIB file", + "actions"=>"Actions" + ); + $Table_print->set_snmp_table_fields ($tfields); + + # structure + print "

Details for message $_GET[page]


"; + print "
"; + + // print + print ""; + $Table_print->print_snmp_item ($msg_description); + print "
"; + + print "
"; + } + } +} + +# print title +print "

Traps for message $_GET[page]


"; + +// if queried +if (isset($_GET['page'])) { + # set fields + $tfields = array( "id"=>"", + "hostname"=>"Hostname", + "ip"=>"IP address", + "date"=>"Date", + "message"=>"Message", + "severity"=>"Severity", + "content"=>"Content" + ); + $Table_print->set_snmp_table_fields ($tfields); + + + # print table + print ""; + $Table_print->print_snmp_table ($all_traps); + print "
"; +} +?> \ No newline at end of file diff --git a/app/settings/exceptions.php b/app/settings/exceptions.php new file mode 100644 index 0000000..1f5db09 --- /dev/null +++ b/app/settings/exceptions.php @@ -0,0 +1,49 @@ +

Ignored messages (Exceptions)

+
+ +Below messages will not be placed to database, and notification message for below definitions will not be sent. If only OID is set, than trap containing this OID will not be processes. +If hostname is set it will match hostname also, same goes for messages for better fine-tuning. +

+is_admin (); + +# Common class +$Common = new Database_wrapper (); + +// fetch all objects +$maintaneance = $Common->fetch_all_objects ("exceptions", "id", false); +// table definitions +$fields_db = $Common->get_table_definition("exceptions"); + + +# set fields +$tfields = array(); +if($fields_db!==false) { + foreach ($fields_db as $f) { + // no id + if($f->Field!=="id") { + $tfields[] = $f->Field; + } + } +} +// add actions +$tfields["actions"]="actions"; + +// print +$Table_print->set_snmp_table_fields ($tfields); +// print add item +$Table_print->print_add_item ("app/settings/item-edit.php", "exceptions"); +# print table +print ""; +$Table_print->print_table ($maintaneance, true, "app/settings/item-edit.php", "exceptions"); +print "
"; + +?> \ No newline at end of file diff --git a/app/settings/general.php b/app/settings/general.php new file mode 100644 index 0000000..83cd502 --- /dev/null +++ b/app/settings/general.php @@ -0,0 +1,16 @@ +is_admin (); +?> + +

General settings

+
+ +General settings must be for now set in functions/config.php file, later they will move to database. Here is content of config.php: + +

+ +
<?php
+$f = readfile(dirname(__FILE__)."/../../config.php");
+?>
+
\ No newline at end of file diff --git a/app/settings/index.php b/app/settings/index.php new file mode 100644 index 0000000..6f7c460 --- /dev/null +++ b/app/settings/index.php @@ -0,0 +1,65 @@ +is_admin (); + +// items +$items = array( + "general" => "General settings", + "severity_definitions" => "Severity definitions", + "exceptions" => "Ignored messages", + "maintaneance" => "Maintaneance", + "mibs" => "MIB files", + "users" => "User management" +); +// default +if(!isset($_GET['page'])) { $_GET['page'] = "severity_definitions"; } +?> + + +

Settings

+
+ + +
+
+ + +
+
    + $i) { + // active + $active = $k==$_GET['page'] ? "active" : ""; + // print + print "
  • "; + print " $i"; + print "
  • "; + } + ?> +
+
+ + +
+
+ show("danger", "Error: Invalid page!", false); + } + } + else { + print "Select settings on side menu."; + } + ?> +
+
+ +
+
diff --git a/app/settings/item-edit.php b/app/settings/item-edit.php new file mode 100644 index 0000000..cb7bd00 --- /dev/null +++ b/app/settings/item-edit.php @@ -0,0 +1,194 @@ +is_admin (); + + +// validate script +if (!in_array($_GET['script'], $scripts)) { + $title = "Error item ".$_GET['action']; + $btn_text = ""; + $content = $Result->show("danger", "Invalid script", false, false, true); +} +else { + // fetch object + if($_GET['action']!=="add") { + $item = $Common->fetch_object ($_GET['script'], "id", $_GET['id']); + } + else { + $item = true; + } + + // distinct hosts + $uniq = $Common->fetch_unique_items ("traps", "hostname"); + if ($uniq!==false) { + foreach ($uniq as $u) { + $unique_hosts[] = $u->hostname; + } + } + + // table definitions + $fields_db = $Common->get_table_definition($_GET['script']); + + // remove unneeded + if ($_GET['script']=="users") { + foreach ($fields_db as $k=>$f) { + if ($f->Field=="last_login" || $f->Field=="last_activity") { + unset($fields_db[$k]); + } + } + } + + # validate + if ($item!==false) { + // set title + $title = ucwords($_GET['action'])." ".$_GET['script']." item"; + // footer text + $btn_text = ucwords($_GET['action']); + + + // add + if ($_GET['action']=="add") { + // content + $html[] = "Add new item to $_GET[script]:

"; + + $html[] = ""; + + // save content + $content = implode("\n", $html); + } + + // edit + elseif ($_GET['action']=="edit") { + // content + $html[] = "Edit $_GET[script] item:

"; + + $html[] = ""; + + // save content + $content = implode("\n", $html); + } + + // delete + elseif ($_GET['action']=="delete") { + // content + $html[] = "Remove the following $_GET[script] item:

"; + + $html[] = ""; + // loop + foreach ($fields_db as $f) { + // no id + if ($f->Field!=="id") { + $html[] = ""; + $html[] = " "; + $html[] = " "; + $html[] = ""; + } + } + $html[] = "
$f->Field".$item->{$f->Field}."
"; + + // fake form + $html[] = " "; + + // save content + $content = implode("\n", $html); + } + // false + else { + $title = "Error"; + $btn_text = ""; + $content = $Result->show ("danger", _('Invalid action'), false, false, true); + } + } + else { + $title = "Error"; + $btn_text = ""; + $content = $Result->show ("danger", _('Invalid item'), false, false, true); + } + + +} + +# print modal +$Modal->modal_print ($title, $content, $btn_text, "app/settings/item-submit.php"); +?> \ No newline at end of file diff --git a/app/settings/item-submit.php b/app/settings/item-submit.php new file mode 100644 index 0000000..c971c51 --- /dev/null +++ b/app/settings/item-submit.php @@ -0,0 +1,78 @@ +is_admin (); + +# valid scripts +$scripts = array("maintaneance", "exceptions", "severity_definitions", "users"); + +# validate script +if (!in_array($_POST['script'], $scripts)) { + $Result->show ("danger", 'Invalid script', true); +} + +# users checkbox override +if($_POST['script']=="users" && $_POST['action']!="delete") { + // init + $notification_types = array(); + $notification_severities = array(); + + // loop + foreach ($_POST as $k=>$p) { + if (strpos($k, "notification_types")!==false) { + $notification_types[] = str_replace("notification_types-", "", $k); + unset($_POST[$k]); + } + elseif (strpos($k, "notification_severities")!==false) { + $notification_severities[] = str_replace("notification_severities-", "", $k); + unset($_POST[$k]); + } + } + + // join + $_POST['notification_types'] = implode(";", $notification_types); + $_POST['notification_severities'] = implode(";", $notification_severities); + + // empty fix + if (strlen($_POST['notification_types'])==0) { $_POST['notification_types'] = "none"; } + if (strlen($_POST['notification_severities'])==0) { $_POST['notification_severities'] = "none"; } + + // password + if($_POST['action']=="edit" && strlen($_POST['password'])==0) { unset($_POST['password']); } + elseif (strlen($_POST['password'])<8) { $Result->show("danger", "Invalid password - 8 characters required!", true); } + else { $_POST['password'] = $User->crypt_user_pass ($_POST['password']); } +} + +# add +if ($_POST['action']=="add") { + if($Common->create_object ($_POST['script'], $_POST)===true) { $Result->show ("success", ucwords($_POST['script']).' object created', false); } + else { $Result->show ("danger", ucwords($_POST['script']).' object create failed', false); } +} +# delete +elseif ($_POST['action']=="delete") { + if($Common->remove_object ($_POST['script'], $_POST['id'])===true) { $Result->show ("success", ucwords($_POST['script']).' object removed', false); } + else { $Result->show ("danger", ucwords($_POST['script']).' object delete failed', false);} +} +# edit +elseif ($_POST['action']=="edit") { + if($Common->update_object ($_POST['script'], $_POST)===true) { $Result->show ("success", ucwords($_POST['script']).' object updated', false); } + else { $Result->show ("danger", ucwords($_POST['script']).' object update failed', false);} +} +# die +else { + $Result->show ("danger", 'Invalid action', false); +} +?> \ No newline at end of file diff --git a/app/settings/maintaneance.php b/app/settings/maintaneance.php new file mode 100644 index 0000000..e8065bd --- /dev/null +++ b/app/settings/maintaneance.php @@ -0,0 +1,55 @@ +

Maintaneance periods for hosts

+
+ +Here you can set maintaneance periods for specific hosts. During maintaneance period you will not be receiving notifications for this host, but notifications will still be arraving to database. +

+is_admin (); + +// fetch all objects +$maintaneance = $Common->fetch_all_objects ("maintaneance", "start", false); +// table definitions +$fields_db = $Common->get_table_definition("maintaneance"); + + +# set fields +$tfields = array(); +if($fields_db!==false) { + foreach ($fields_db as $f) { + // no id + if($f->Field!=="id") { + $tfields[] = $f->Field; + } + } + $tfields[] = "valid"; +} +// add validity +if ($maintaneance!==false) { + foreach ($maintaneance as $k=>$m) { + $maintaneance[$k]->valid = strtotime(date("Y-m-d H:i:s")) > strtotime($m->stop) ? "

No

" : "

Yes

"; + } +} +// add actions +$tfields["actions"]="actions"; + +// print +$Table_print->set_snmp_table_fields ($tfields); +// print add item +$Table_print->print_add_item ("app/settings/item-edit.php", "maintaneance"); +# print table +print ""; +$Table_print->print_table ($maintaneance, true, "app/settings/item-edit.php", "maintaneance"); +print "
"; + +?> \ No newline at end of file diff --git a/app/settings/mib_definition_create.php b/app/settings/mib_definition_create.php new file mode 100644 index 0000000..ab4e745 --- /dev/null +++ b/app/settings/mib_definition_create.php @@ -0,0 +1,86 @@ +is_admin (); + +# SNMP class to read file +$Snmp_read_MIB = new Snmp_read_MIB; +$Snmp_read_MIB->set_mib_direcotry (); + + +// set items +$mib = new StdClass; +$mib->file = $m; + +// process mib +$tmp = $Snmp_read_MIB->read_mib_file ($_GET['mibfile']); + +// save +$mib->notification_objects_full = $Snmp_read_MIB->detect_mib_objects (); +// save oid +$mib->oid = $Snmp_read_MIB->detect_mib_oid(); + +// title +$title = "Create new severity definition"; + +// content +$html[] = "