mirror of
https://github.com/nttgin/BGPalerter.git
synced 2024-05-19 06:50:08 +00:00
introduced email reporting with templates
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"brembo": "^2.0.3",
|
||||
"event-stream": "^4.0.1",
|
||||
"ip": "https://github.com/MaxCam/node-ip.git#contains-prefix",
|
||||
"js-yaml": "^3.13.1",
|
||||
|
||||
15
reports/email_templates/hijack.txt
Normal file
15
reports/email_templates/hijack.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
${summary}
|
||||
|
||||
|
||||
DETAILS:
|
||||
------------------------------------------------------
|
||||
Monitored prefix: ${prefix}
|
||||
Prefix Description: ${description}
|
||||
Usual prefix origin: AS${asn}
|
||||
Event type: ${type}
|
||||
Now announced by: AS${neworigin}
|
||||
Now announced with: ${newprefix}
|
||||
When event started: ${earliest} UTC
|
||||
Last event: ${latest} UTC
|
||||
Detected by peers: ${peers}
|
||||
See in BGPlay: ${bgplay}
|
||||
13
reports/email_templates/visibility.txt
Normal file
13
reports/email_templates/visibility.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
${summary}
|
||||
|
||||
|
||||
DETAILS:
|
||||
------------------------------------------------------
|
||||
Monitored prefix: ${prefix}
|
||||
Prefix Description: ${description}
|
||||
Prefix origin: AS${asn}
|
||||
Event type: ${type}
|
||||
When event started: ${earliest} UTC
|
||||
Last event: ${latest} UTC
|
||||
Detected by peers: ${peers}
|
||||
See in BGPlay: ${bgplay}
|
||||
@@ -1,11 +1,18 @@
|
||||
import Report from "./report";
|
||||
import brembo from "brembo";
|
||||
import fs from "fs";
|
||||
import moment from "moment";
|
||||
import nodemailer from "nodemailer";
|
||||
import path from "path";
|
||||
|
||||
export default class ReportEmail extends Report {
|
||||
|
||||
constructor(channels,params, env) {
|
||||
super(channels, params, env);
|
||||
|
||||
this.templates = {};
|
||||
this.emailBacklog = [];
|
||||
|
||||
this.transporter = nodemailer.createTransport({
|
||||
host: this.params.smtp,
|
||||
port: this.params.port,
|
||||
@@ -20,6 +27,25 @@ export default class ReportEmail extends Report {
|
||||
rejectUnauthorizedCertificate: this.params.rejectUnauthorizedCertificate
|
||||
}
|
||||
});
|
||||
|
||||
for (let channel of channels) {
|
||||
try {
|
||||
const file = path.resolve('reports/email_templates', `${channel}.txt`);
|
||||
this.templates[channel] = fs.readFileSync(file, "utf8");
|
||||
} catch (error){
|
||||
this.logger.log({
|
||||
level: 'error',
|
||||
message: channel + ' template cannot be loaded'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
const nextEmail = this.emailBacklog.pop();
|
||||
if (nextEmail) {
|
||||
this._sendEmail(nextEmail);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
getEmails = (content) => {
|
||||
@@ -48,31 +74,90 @@ export default class ReportEmail extends Report {
|
||||
return [];
|
||||
};
|
||||
|
||||
getEmailText = (message, content) => {
|
||||
return content.message;
|
||||
_getBGPlayLink = (prefix, start, end, instant = null, rrcs = [0,1,2,5,6,7,10,11,13,14,15,16,18,20]) => {
|
||||
const bgplayTimeOffset = 5 * 60; // 5 minutes
|
||||
return brembo.build("https://stat.ripe.net/", {
|
||||
path: ["widget", "bgplay"],
|
||||
params: {
|
||||
"w.resource": prefix,
|
||||
"w.ignoreReannouncements": true,
|
||||
"w.starttime": moment(start).utc().unix() - bgplayTimeOffset,
|
||||
"w.endtime": moment(end).utc().unix(),
|
||||
"w.rrcs": rrcs.join(","),
|
||||
"w.instant": null,
|
||||
"w.type": "bgp",
|
||||
|
||||
}
|
||||
}).replace("?", "#");
|
||||
};
|
||||
|
||||
report = (message, content) => {
|
||||
getEmailText = (channel, content) => {
|
||||
let context = {
|
||||
summary: content.message,
|
||||
earliest: moment(content.earliest).utc().format("YYYY-MM-DD hh:mm:ss"),
|
||||
latest: moment(content.latest).utc().format("YYYY-MM-DD hh:mm:ss"),
|
||||
channel,
|
||||
type: content.origin,
|
||||
};
|
||||
|
||||
let matched = null;
|
||||
|
||||
switch(channel){
|
||||
case "hijack":
|
||||
matched = content.data[0].matchedRule;
|
||||
context.prefix = matched.prefix;
|
||||
context.description = matched.description;
|
||||
context.asn = matched.asn;
|
||||
context.peers = [...new Set(content.data.map(alert => alert.matchedMessage.peer))].length;
|
||||
context.neworigin = content.data[0].matchedMessage.originAs;
|
||||
context.newprefix = content.data[0].matchedMessage.prefix;
|
||||
context.bgplay = this._getBGPlayLink(matched.prefix, content.earliest, content.latest);
|
||||
break;
|
||||
|
||||
case "visibility":
|
||||
matched = content.data[0].matchedRule;
|
||||
context.prefix = matched.prefix;
|
||||
context.description = matched.description;
|
||||
context.asn = matched.asn;
|
||||
context.peers = [...new Set(content.data.map(alert => alert.matchedMessage.peer))].length;
|
||||
context.bgplay = this._getBGPlayLink(matched.prefix, content.earliest, content.latest);
|
||||
break;
|
||||
|
||||
case "newprefix":
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return this.templates[channel].replace(/\${([^}]*)}/g, (r,k)=>context[k]);
|
||||
};
|
||||
|
||||
_sendEmail = (email) => {
|
||||
if (this.transporter) {
|
||||
const emailGroups = this.getEmails(content);
|
||||
this.transporter
|
||||
.sendMail(email)
|
||||
.catch(error => {
|
||||
this.logger.log({
|
||||
level: 'error',
|
||||
message: error
|
||||
});
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
for (let emails of emailGroups) {
|
||||
report = (channel, content) => {
|
||||
const emailGroups = this.getEmails(content);
|
||||
|
||||
for (let emails of emailGroups) {
|
||||
|
||||
const text = this.getEmailText(channel, content);
|
||||
|
||||
this.emailBacklog.push({
|
||||
from: this.params.email,
|
||||
to: emails.join(', '),
|
||||
subject: 'BGP alert: ' + channel,
|
||||
text: text
|
||||
});
|
||||
|
||||
this.transporter
|
||||
.sendMail({
|
||||
from: this.params.email,
|
||||
to: emails.join(', '),
|
||||
subject: 'BGP alert: ' + message,
|
||||
text: this.getEmailText(message, content)
|
||||
})
|
||||
.catch(error => {
|
||||
this.logger.log({
|
||||
level: 'error',
|
||||
message: error
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,7 +248,9 @@ describe("Alerting", function() {
|
||||
]);
|
||||
|
||||
done();
|
||||
process.exit()
|
||||
setTimeout(function () {
|
||||
process.exit()
|
||||
}, 20000);
|
||||
});
|
||||
|
||||
}).timeout(10000);
|
||||
|
||||
@@ -790,6 +790,11 @@ braces@^2.3.1, braces@^2.3.2:
|
||||
split-string "^3.0.2"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
brembo@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/brembo/-/brembo-2.0.3.tgz#2b94bc75774b94cfa50f9c531f9115e584088524"
|
||||
integrity sha512-KLapbDMsMhrsXDvNl/mzl3HHqwJFSh9fBCdvRrkDQADA/CxNMmznVQHp24I9XVg22Y+qkY6PGRcG/11/aArhWA==
|
||||
|
||||
browser-stdout@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
|
||||
Reference in New Issue
Block a user