Implement E-Mail alerting

This commit is contained in:
Akkadius 2017-10-03 22:26:47 -05:00
parent 8d91e033f2
commit bb8becdaaa
8 changed files with 137 additions and 327 deletions

84
app.js
View File

@ -516,11 +516,28 @@ setTimeout(function(){
console.log("[Timer] lpm: %s lpm_th: %s", leases_per_minute, glass_config.leases_per_minute_threshold); console.log("[Timer] lpm: %s lpm_th: %s", leases_per_minute, glass_config.leases_per_minute_threshold);
if (leases_per_minute <= glass_config.leases_per_minute_threshold && alert_status['leases_per_minute'] == 0) { if (leases_per_minute <= glass_config.leases_per_minute_threshold && alert_status['leases_per_minute'] == 0) {
alert_status['leases_per_minute'] = 1; alert_status['leases_per_minute'] = 1;
slack_message(":warning: WARNING: DHCP leases per minute have dropped below threshold (" + parseInt(glass_config.leases_per_minute_threshold).toLocaleString('en') + ") Current (" + parseInt(leases_per_minute).toLocaleString('en') + ")");
slack_message(":warning: WARNING: DHCP leases per minute have dropped below threshold " +
"(" + parseInt(glass_config.leases_per_minute_threshold).toLocaleString('en') + ") " +
"Current (" + parseInt(leases_per_minute).toLocaleString('en') + ")");
email_alert("CRITICAL: Leases Per Minute Threshold", "DHCP leases per minute dropped below critical threshold <br><br>" +
"Threshold: (" + parseInt(glass_config.leases_per_minute_threshold).toLocaleString('en') + ") <br>" +
"Current: (" + parseInt(leases_per_minute).toLocaleString('en') + ") <br><br>" +
"This is usually indicative of a process or hardware problem and needs to be addressed immediately");
} }
else if (leases_per_minute >= glass_config.leases_per_minute_threshold && alert_status['leases_per_minute'] == 1) { else if (leases_per_minute >= glass_config.leases_per_minute_threshold && alert_status['leases_per_minute'] == 1) {
alert_status['leases_per_minute'] = 0; alert_status['leases_per_minute'] = 0;
slack_message(":white_check_mark: CLEAR: DHCP leases per minute have returned to above threshold (" + parseInt(glass_config.leases_per_minute_threshold).toLocaleString('en') + ") Current (" + parseInt(leases_per_minute).toLocaleString('en') + ")");
slack_message(":white_check_mark: CLEAR: DHCP leases per minute have returned to above threshold " +
"(" + parseInt(glass_config.leases_per_minute_threshold).toLocaleString('en') + ") " +
"Current (" + parseInt(leases_per_minute).toLocaleString('en') + ")");
email_alert("CLEAR: Leases Per Minute Threshold", "DHCP leases per minute have returned to normal <br><br>" +
"Threshold: (" + parseInt(glass_config.leases_per_minute_threshold).toLocaleString('en') + ") <br>" +
"Current: (" + parseInt(leases_per_minute).toLocaleString('en') + ")"
);
} }
} }
}, (60 * 1000)); }, (60 * 1000));
@ -571,7 +588,11 @@ setTimeout(function(){
) )
{ {
alert_status_networks_warning[dhcp_data['shared-networks'][i].location] = 1; alert_status_networks_warning[dhcp_data['shared-networks'][i].location] = 1;
slack_message(":warning: WARNING: DHCP shared network utilization (" + dhcp_data['shared-networks'][i].location + ") Current: (" + utilization + "%) Threshold: (" + glass_config.shared_network_warning_threshold + "%)");
slack_message(":warning: WARNING: DHCP shared network utilization (" + dhcp_data['shared-networks'][i].location + ") " +
"Current: (" + utilization + "%) " +
"Threshold: (" + glass_config.shared_network_warning_threshold + "%)"
);
} }
else if ( else if (
utilization <= glass_config.shared_network_warning_threshold && utilization <= glass_config.shared_network_warning_threshold &&
@ -579,7 +600,11 @@ setTimeout(function(){
) )
{ {
alert_status_networks_warning[dhcp_data['shared-networks'][i].location] = 0; alert_status_networks_warning[dhcp_data['shared-networks'][i].location] = 0;
slack_message(":white_check_mark: CLEAR: Warning DHCP shared network utilization (" + dhcp_data['shared-networks'][i].location + ") Current: (" + utilization + "%) Threshold: (" + glass_config.shared_network_warning_threshold + "%)");
slack_message(":white_check_mark: CLEAR: Warning DHCP shared network utilization (" + dhcp_data['shared-networks'][i].location + ") " +
"Current: (" + utilization + "%) " +
"Threshold: (" + glass_config.shared_network_warning_threshold + "%)"
);
} }
} }
@ -612,4 +637,55 @@ function round(num, places) {
return Math.round(num * multiplier) / multiplier; return Math.round(num * multiplier) / multiplier;
} }
/* Load Mailer */
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
sendmail: true,
newline: 'unix',
path: '/usr/sbin/sendmail'
});
console.log("[Glass Server] Loading E-Mail template...");
fs = require('fs');
var email_body = fs.readFileSync('./public/templates/email_template.html', "utf8");
function email_alert(alert_title, alert_message) {
/* E-Mail Template Load */
console.log("Sending E-Mail...\n");
if(typeof glass_config.email_alert_to === "undefined")
return false;
if (glass_config.email_alert_to == ""){
console.log("[Glass Server] No email_to specified - returning...");
return false;
}
email_body = email_body.replace("[body_content_placeholder]", alert_message);
email_body = email_body.replace("[alert_title]", alert_title);
email_body = email_body.replace("[local_time]", new Date().toString() );
var mailOptions = {
from: "Glass Alerting Monitor glass@noreply.com",
to: glass_config.email_alert_to,
subject: "[Glass] " + alert_title,
html: email_body,
};
transporter.sendMail(mailOptions, function(error, info){
if(error){
console.log(error);
}
else {
console.log('Message sent: ' + info.response);
};
});
}
email_alert("CRITICAL: Leases Per Minute Threshold", "DHCP leases per minute dropped below critical threshold <br><br>" +
"Threshold: (" + parseInt(glass_config.leases_per_minute_threshold).toLocaleString('en') + ") <br>" +
"Current: (" + parseInt(leases_per_minute).toLocaleString('en') + ") <br><br>" +
"This is usually indicative of a process or hardware problem and needs to be addressed immediately");
console.log("[Glass Server] Bootup complete"); console.log("[Glass Server] Bootup complete");

View File

@ -5,9 +5,12 @@
"log_file": "/var/log/dhcp.log", "log_file": "/var/log/dhcp.log",
"config_file": "/etc/dhcp/dhcpd.conf", "config_file": "/etc/dhcp/dhcpd.conf",
"shared_network_critical_threshold": "95", "shared_network_critical_threshold": "95",
"shared_network_warning_threshold": "80", "shared_network_warning_threshold": "0",
"slack_webhook_url": "https://hooks.slack.com/services/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", "slack_webhook_url": "",
"slack_alert_channel": "#alerting", "slack_alert_channel": "",
"leases_per_minute_threshold": "1000", "leases_per_minute_threshold": "50",
"ip_ranges_to_allow": [""] "ip_ranges_to_allow": [
""
],
"email_alert_to": ""
} }

View File

@ -0,0 +1,3 @@
.info-box .content .text {
margin-top: 5px !important;
}

View File

@ -40,7 +40,7 @@
</div> </div>
<div class="content"> <div class="content">
<div class="text">SERVER</div> <div class="text">SERVER</div>
<div class="number" id="server-name">0</div> <div class="number" id="server-name" style="font-size:18px">0</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,336 +1,56 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<head> <head>
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Glass Alert</title> <title>Glass Alerting Monitor</title>
<style>
* {
margin: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
box-sizing: border-box;
font-size: 14px;
}
img {
max-width: 100%;
}
body {
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: none;
width: 100% !important;
height: 100%;
line-height: 1.6em;
/* 1.6em * 14px = 22.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 22px;*/
}
/* Let's make sure all tables have defaults */
table td {
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
body {
background-color: #ecf0f5;
color: #6c7b88
}
.body-wrap {
background-color: #ecf0f5;
width: 100%;
}
.container {
display: block !important;
max-width: 600px !important;
margin: 0 auto !important;
/* makes it centered */
clear: both !important;
}
.content {
max-width: 600px;
margin: 0 auto;
display: block;
padding: 20px;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background-color: #fff;
border-bottom: 2px solid #d7d7d7;
}
.content-wrap {
padding: 20px;
}
.content-block {
padding: 0 0 20px;
}
.header {
width: 100%;
margin-bottom: 20px;
}
.footer {
width: 100%;
clear: both;
color: #999;
padding: 20px;
}
.footer p, .footer a, .footer td {
color: #999;
font-size: 12px;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1, h2, h3 {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
color: #1a2c3f;
margin: 30px 0 0;
line-height: 1.2em;
font-weight: 400;
}
h1 {
font-size: 32px;
font-weight: 500;
/* 1.2em * 32px = 38.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 38px;*/
}
h2 {
font-size: 24px;
/* 1.2em * 24px = 28.8px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 29px;*/
}
h3 {
font-size: 18px;
/* 1.2em * 18px = 21.6px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 22px;*/
}
h4 {
font-size: 14px;
font-weight: 600;
}
p, ul, ol {
margin-bottom: 10px;
font-weight: normal;
}
p li, ul li, ol li {
margin-left: 5px;
list-style-position: inside;
}
/* -------------------------------------
LINKS & BUTTONS
------------------------------------- */
a {
color: #348eda;
text-decoration: underline;
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #42A5F5;
border: solid #42A5F5;
border-width: 10px 20px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 28px;*/
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
text-transform: capitalize;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.aligncenter {
text-align: center;
}
.alignright {
text-align: right;
}
.alignleft {
text-align: left;
}
.clear {
clear: both;
}
/* -------------------------------------
ALERTS
Change the class depending on warning email, good email or bad email
------------------------------------- */
.alert {
font-size: 16px;
color: #fff;
font-weight: 500;
padding: 20px;
text-align: center;
}
.alert a {
color: #fff;
text-decoration: none;
font-weight: 500;
font-size: 16px;
}
.alert.alert-warning {
background-color: #FFA726;
}
.alert.alert-bad {
background-color: #ef5350;
}
.alert.alert-good {
background-color: #8BC34A;
}
/* -------------------------------------
INVOICE
Styles for the billing table
------------------------------------- */
.invoice {
margin: 25px auto;
text-align: left;
width: 100%;
}
.invoice td {
padding: 5px 0;
}
.invoice .invoice-items {
width: 100%;
}
.invoice .invoice-items td {
border-top: #eee 1px solid;
}
.invoice .invoice-items .total td {
border-top: 2px solid #6c7b88;
font-size: 18px;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 640px) {
body {
padding: 0 !important;
}
h1, h2, h3, h4 {
font-weight: 800 !important;
margin: 20px 0 5px !important;
}
h1 {
font-size: 22px !important;
}
h2 {
font-size: 18px !important;
}
h3 {
font-size: 16px !important;
}
.container {
padding: 0 !important;
width: 100% !important;
}
.content {
padding: 0 !important;
}
.content-wrap {
padding: 10px !important;
}
.invoice {
width: 100% !important;
}
}
</style>
</head> </head>
<body itemscope itemtype="http://schema.org/EmailMessage"> <body style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6; background-color: #f6f6f6; margin: 0; padding: 0;" bgcolor="#f6f6f6">
<table class="body-wrap"> <table class="body-wrap" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; background-color: #f6f6f6; margin: 0; padding: 0;" bgcolor="#f6f6f6">
<tr> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<td></td> <td style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0;" valign="top"></td>
<td class="container" width="600"> <td class="container" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; display: block !important; clear: both !important; width: 100% !important; margin: 0 auto; padding: 0;" valign="top">
<div class="content"> <div class="content" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; display: block; margin: 0 auto; padding: 10px;">
<table class="main" width="100%" cellpadding="0" cellspacing="0"> <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 3px; background-color: #fff; margin: 0; padding: 0; border: 1px solid #e9e9e9;" bgcolor="#fff">
<tr> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<td class="alert alert-warning"> <td class="alert alert-warning" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; color: #fff; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; background-color: #ff0000; margin: 0; padding: 20px;" align="center" bgcolor="#ff9f00" valign="top">
Warning: You're approaching your limit. Please upgrade. <b>Glass Alerting Monitor</b>
</td> </td>
</tr> </tr>
<tr> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<td class="content-wrap"> <td class="content-wrap" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 20px;" valign="top">
<table width="100%" cellpadding="0" cellspacing="0"> <table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<tr> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<td class="content-block"> <td class="content-block" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
You have <strong>1 free report</strong> remaining. <h4>Alert Trigger</h4>
</td> <li>[alert_title]</li>
</tr>
<tr> <h4>Message</h4>
<td class="content-block"> <pre>[body_content_placeholder]</pre>
Add your credit card now to upgrade your account to a premium plan to ensure you don't miss out on any reports.
</td> <h4>Time</h4>
</tr> <li>[local_time]</li>
<tr>
<td class="content-block">
<a href="#" class="btn-primary">Upgrade my account</a>
</td>
</tr>
<tr>
<td class="content-block">
Thanks for choosing Company Inc.
</td> </td>
</tr> </tr>
</table> </table>
</td> </td>
</tr> </tr>
</table> </table>
<div class="footer"> <div class="footer" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;">
<table width="100%"> <table width="100%" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<tr> <tr style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0; padding: 0;">
<td class="aligncenter content-block"><a href="#">Unsubscribe</a> from these alerts.</td> <td class="aligncenter content-block" style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">
<p style="font-size: 11px; color: #999;">Glass > an isc dhcp server interface<br>Chris Miles</p>
</td>
</tr> </tr>
</table> </table>
</div></div> </div></div>
</td> </td>
<td></td> <td style="font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0;" valign="top"></td>
</tr> </tr>
</table> </table>

View File

@ -27,6 +27,8 @@
<!-- Custom Css --> <!-- Custom Css -->
<link href="assets/css/style.css" rel="stylesheet"> <link href="assets/css/style.css" rel="stylesheet">
<link href="assets/css/glass.css" rel="stylesheet">
<link href="assets/plugins/jquery-datatable/skin/bootstrap/css/dataTables.bootstrap.css" rel="stylesheet"> <link href="assets/plugins/jquery-datatable/skin/bootstrap/css/dataTables.bootstrap.css" rel="stylesheet">
<!-- AdminBSB Themes. You can choose a theme from css/themes instead of get all themes --> <!-- AdminBSB Themes. You can choose a theme from css/themes instead of get all themes -->
@ -60,7 +62,6 @@
<nav class="navbar"> <nav class="navbar">
<div class="container-fluid"> <div class="container-fluid">
<div class="navbar-header"> <div class="navbar-header">
<a href="javascript:void(0);" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false"></a>
<a href="javascript:void(0);" class="bars"></a> <a href="javascript:void(0);" class="bars"></a>
<a class="navbar-brand" href="/">[application_name]</a> <a class="navbar-brand" href="/">[application_name]</a>
</div> </div>

View File

@ -16,6 +16,7 @@ router.post('/', authorize.auth, function(req, res, next) {
glass_config.leases_per_minute_threshold = request.leases_per_minute_threshold; glass_config.leases_per_minute_threshold = request.leases_per_minute_threshold;
glass_config.slack_webhook_url = request.slack_webhook_url; glass_config.slack_webhook_url = request.slack_webhook_url;
glass_config.slack_alert_channel = request.slack_alert_channel; glass_config.slack_alert_channel = request.slack_alert_channel;
glass_config.email_alert_to = request.email_alert_to
json_file.writeFile('./config/glass_config.json', glass_config, {spaces: 2}, function(err) { json_file.writeFile('./config/glass_config.json', glass_config, {spaces: 2}, function(err) {
console.error(err); console.error(err);

View File

@ -32,13 +32,19 @@ router.get('/', authorize.auth, function(req, res, next) {
glass_settings_template = template_render.set_template_variable(glass_settings_template, "c_content", form_data); glass_settings_template = template_render.set_template_variable(glass_settings_template, "c_content", form_data);
/* Shared Network Alert Threshold (Critical) */ /* Slack Webhook URL */
input = template_render.form_input('Slack Webhook URL <img src="images/slack-icon.png" style="height:25px; width: auto;"> ', '<input type="input" class="form-control" id="slack_webhook_url" placeholder="https://hooks.slack.com/services/xxx/xxx/xxx" value="' + glass_config.slack_webhook_url + '">'); input = template_render.form_input('Slack Webhook URL <img src="images/slack-icon.png" style="height:25px; width: auto;"> ', '<input type="input" class="form-control" id="slack_webhook_url" placeholder="https://hooks.slack.com/services/xxx/xxx/xxx" value="' + glass_config.slack_webhook_url + '">');
/* Shared Network Alert Threshold (Warning) */ /* Slack Channel */
input = input + template_render.form_input('Slack Channel <img src="images/slack-icon.png" style="height:25px; width: auto;"> ', '<input type="input" class="form-control" id="slack_alert_channel" placeholder="#channel" value="' + glass_config.slack_alert_channel + '">'); input = input + template_render.form_input('Slack Channel <img src="images/slack-icon.png" style="height:25px; width: auto;"> ', '<input type="input" class="form-control" id="slack_alert_channel" placeholder="#channel" value="' + glass_config.slack_alert_channel + '">');
// <div id="glass_settings_result"></div> /* E-Mail Send To */
input = input + template_render.form_input(
'E-Mail Send To <i class="material-icons" style="font-size: 16px !important;">mail</i>',
'<input type="input" class="form-control" id="email_alert_to" placeholder="email@example.com, email2@example.com" value="' + glass_config.email_alert_to + '">'
);
// <div id="glass_settings_result"></div>
form_data = template_render.form_body("glass-notifications-form", input); form_data = template_render.form_body("glass-notifications-form", input);