mirror of
https://github.com/nttgin/BGPalerter.git
synced 2024-05-19 06:50:08 +00:00
refactoring, introduced dependency injector
This commit is contained in:
25
config.js
25
config.js
@@ -1,25 +0,0 @@
|
|||||||
import MonitorHijack from "./monitors/monitorHijack";
|
|
||||||
import ReportEmail from "./reports/reportEmail";
|
|
||||||
import yaml from "js-yaml";
|
|
||||||
import fs from "fs";
|
|
||||||
|
|
||||||
const configFile = yaml.safeLoad(fs.readFileSync('./config.yml', 'utf8'));
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
monitors: [
|
|
||||||
{
|
|
||||||
class: MonitorHijack,
|
|
||||||
channel: "hijack",
|
|
||||||
name: "basic-hijack-detection"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
reports: [
|
|
||||||
{
|
|
||||||
class: ReportEmail,
|
|
||||||
channels: ["hijack"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Object.assign(config, configFile);
|
|
34
config.yml
34
config.yml
@@ -1,6 +1,18 @@
|
|||||||
# Please, rename this file to config.yml
|
# Please, rename this file to config.yml
|
||||||
|
|
||||||
testMode: true,
|
monitors:
|
||||||
|
- class: MonitorHijack
|
||||||
|
channel: hijack
|
||||||
|
name: basic-hijack-detection
|
||||||
|
|
||||||
|
reports:
|
||||||
|
- class: ReportEmail
|
||||||
|
channels:
|
||||||
|
- hijack
|
||||||
|
- pippo
|
||||||
|
|
||||||
|
|
||||||
|
testMode: true
|
||||||
|
|
||||||
checkStaleNotificationsSeconds: 30
|
checkStaleNotificationsSeconds: 30
|
||||||
notificationIntervalSeconds: 10
|
notificationIntervalSeconds: 10
|
||||||
@@ -10,8 +22,8 @@ bufferSize: 10
|
|||||||
|
|
||||||
wsParams:
|
wsParams:
|
||||||
moreSpecific: true
|
moreSpecific: true
|
||||||
type: "UPDATE"
|
type: UPDATE
|
||||||
host: "rrc21"
|
host: rrc21
|
||||||
socketOptions:
|
socketOptions:
|
||||||
includeRaw: false
|
includeRaw: false
|
||||||
|
|
||||||
@@ -25,15 +37,21 @@ monitoredPrefixesFiles:
|
|||||||
- prefixes.yml
|
- prefixes.yml
|
||||||
|
|
||||||
|
|
||||||
|
logging:
|
||||||
|
logRotatePattern: YYYY-MM-DD # Whenever the pattern changes, a new file is created and the old one rotated
|
||||||
|
zippedArchive: true
|
||||||
|
maxSize: 20m
|
||||||
|
maxFiles: 14d
|
||||||
|
|
||||||
|
|
||||||
emailConfig:
|
emailConfig:
|
||||||
enabled: false
|
enabled: false
|
||||||
smtp: smtp.gmail.com
|
smtp: smtp.gmail.com
|
||||||
email:
|
email: sender@email
|
||||||
port: 465
|
port: 465
|
||||||
secure: true
|
secure: true
|
||||||
user:
|
user: user
|
||||||
password:
|
password: password
|
||||||
|
|
||||||
notifiedEmails:
|
notifiedEmails:
|
||||||
- me@email.it
|
- me@email.it
|
||||||
|
|
19
consumer.js
19
consumer.js
@@ -1,17 +1,9 @@
|
|||||||
import config from "./config";
|
import { config, logger, monitors } from "./env";
|
||||||
import pubSub from 'pubsub-js';
|
|
||||||
import logger from './logger';
|
|
||||||
|
|
||||||
export default class Consumer {
|
export default class Consumer {
|
||||||
|
|
||||||
constructor(inputManager){
|
constructor(){
|
||||||
process.on('message', this.dispatch);
|
process.on('message', this.dispatch);
|
||||||
this.monitors = config.monitors.map(monitor =>
|
|
||||||
new monitor.class(inputManager, monitor.name, monitor.channel, config, pubSub));
|
|
||||||
|
|
||||||
this.reports = config.reports.map(report =>
|
|
||||||
new report.class(report.channels, config, pubSub));
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch = (data) => {
|
dispatch = (data) => {
|
||||||
@@ -21,13 +13,16 @@ export default class Consumer {
|
|||||||
case "ris_message": this.handleUpdate(message)
|
case "ris_message": this.handleUpdate(message)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Don't do anything
|
logger.log({
|
||||||
|
level: 'error',
|
||||||
|
message: error
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleUpdate = (data) => {
|
handleUpdate = (data) => {
|
||||||
const messages = this.transform(data);
|
const messages = this.transform(data);
|
||||||
for (let monitor of this.monitors) {
|
for (let monitor of monitors) {
|
||||||
|
|
||||||
// Blocking filtering to reduce stack usage
|
// Blocking filtering to reduce stack usage
|
||||||
for (const message of messages.filter(monitor.filter)) {
|
for (const message of messages.filter(monitor.filter)) {
|
||||||
|
92
env.js
Normal file
92
env.js
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import yaml from "js-yaml";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import pubSub from 'pubsub-js';
|
||||||
|
import winston from 'winston';
|
||||||
|
import InputManager from "./inputManager";
|
||||||
|
require('winston-daily-rotate-file');
|
||||||
|
const { combine, timestamp, label, printf } = winston.format;
|
||||||
|
|
||||||
|
const vector = {
|
||||||
|
env: "dev" // Get the real one later
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = yaml.safeLoad(fs.readFileSync(path.resolve(__dirname, 'config.yml'), 'utf8'));
|
||||||
|
|
||||||
|
const formatLine = printf(({ level, message, label, timestamp }) => `${timestamp} [${label}] ${level}: ${message}`);
|
||||||
|
const verboseFilter = winston.format((info, opts) => info.level === 'verbose' ? info : false);
|
||||||
|
const transportError = new (winston.transports.DailyRotateFile)({
|
||||||
|
filename: 'logs/error-%DATE%.log',
|
||||||
|
datePattern: config.logging.logRotatePattern,
|
||||||
|
zippedArchive: config.logging.zippedArchive,
|
||||||
|
maxSize: config.logging.maxSize,
|
||||||
|
maxFiles: config.logging.maxFiles,
|
||||||
|
level: 'error',
|
||||||
|
timestamp: true,
|
||||||
|
eol: '\n',
|
||||||
|
json: false,
|
||||||
|
format: combine(
|
||||||
|
label({ label: vector.env}),
|
||||||
|
timestamp(),
|
||||||
|
formatLine
|
||||||
|
)
|
||||||
|
});
|
||||||
|
const transportReports = new (winston.transports.DailyRotateFile)({
|
||||||
|
filename: 'logs/reports-%DATE%.log',
|
||||||
|
datePattern: config.logging.logRotatePattern,
|
||||||
|
zippedArchive: config.logging.zippedArchive,
|
||||||
|
maxSize: config.logging.maxSize,
|
||||||
|
maxFiles: config.logging.maxFiles,
|
||||||
|
level: 'verbose',
|
||||||
|
timestamp: true,
|
||||||
|
eol: '\n',
|
||||||
|
json: false,
|
||||||
|
format: combine(
|
||||||
|
verboseFilter(),
|
||||||
|
label({ label: vector.env}),
|
||||||
|
timestamp(),
|
||||||
|
formatLine
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
const logger = winston.createLogger({
|
||||||
|
level: 'info',
|
||||||
|
transports: [
|
||||||
|
transportError,
|
||||||
|
transportReports
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (vector.env === 'prod') {
|
||||||
|
logger.remove(logger.transports.Console);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.monitors = (config.monitors || [])
|
||||||
|
.map(item => {
|
||||||
|
return {
|
||||||
|
class: require("./monitors/" + item.class).default,
|
||||||
|
channel: item.channel,
|
||||||
|
name: item.name
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
config.reports = (config.reports || [])
|
||||||
|
.map(item => {
|
||||||
|
|
||||||
|
return {
|
||||||
|
class: require("./reports/" + item.class).default,
|
||||||
|
channels: item.channels
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const input = new InputManager(config);
|
||||||
|
|
||||||
|
vector.config = config;
|
||||||
|
vector.logger = logger;
|
||||||
|
vector.input = input;
|
||||||
|
vector.pubSub = pubSub;
|
||||||
|
vector.monitors = config.monitors.map(monitor => new monitor.class(monitor.name, monitor.channel, vector));
|
||||||
|
vector.reports = config.reports.map(report => new report.class(report.channels, vector));
|
||||||
|
|
||||||
|
module.exports = vector;
|
8
index.js
8
index.js
@@ -1,12 +1,8 @@
|
|||||||
import config from "./config";
|
import { config, logger } from "./env";
|
||||||
import cluster from "cluster";
|
import cluster from "cluster";
|
||||||
import WebSocket from "ws";
|
import WebSocket from "ws";
|
||||||
import sleep from "sleep";
|
import sleep from "sleep";
|
||||||
import Consumer from "./consumer";
|
import Consumer from "./consumer";
|
||||||
import InputManager from "./inputManager";
|
|
||||||
import logger from './logger';
|
|
||||||
|
|
||||||
const inputManager = new InputManager(config);
|
|
||||||
|
|
||||||
if (cluster.isMaster) {
|
if (cluster.isMaster) {
|
||||||
|
|
||||||
@@ -65,5 +61,5 @@ if (cluster.isMaster) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
new Consumer(inputManager)
|
new Consumer();
|
||||||
}
|
}
|
||||||
|
19
logger.js
19
logger.js
@@ -1,4 +1,6 @@
|
|||||||
|
import { config, logger } from "./env";
|
||||||
import winston from 'winston';
|
import winston from 'winston';
|
||||||
|
|
||||||
require('winston-daily-rotate-file');
|
require('winston-daily-rotate-file');
|
||||||
|
|
||||||
const { combine, timestamp, label, printf } = winston.format;
|
const { combine, timestamp, label, printf } = winston.format;
|
||||||
@@ -13,12 +15,13 @@ const verboseFilter = winston.format((info, opts) => {
|
|||||||
return info.level === 'verbose' ? info : false
|
return info.level === 'verbose' ? info : false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const transportError = new (winston.transports.DailyRotateFile)({
|
const transportError = new (winston.transports.DailyRotateFile)({
|
||||||
filename: 'logs/error-%DATE%.log',
|
filename: 'logs/error-%DATE%.log',
|
||||||
datePattern: 'YYYY-MM-DD',
|
datePattern: config.logging.logRotatePattern,
|
||||||
zippedArchive: true,
|
zippedArchive: config.logging.zippedArchive,
|
||||||
maxSize: '20m',
|
maxSize: config.logging.maxSize,
|
||||||
maxFiles: '14d',
|
maxFiles: config.logging.maxFiles,
|
||||||
level: 'error',
|
level: 'error',
|
||||||
timestamp: true,
|
timestamp: true,
|
||||||
eol: '\n',
|
eol: '\n',
|
||||||
@@ -32,10 +35,10 @@ const transportError = new (winston.transports.DailyRotateFile)({
|
|||||||
|
|
||||||
const transportReports = new (winston.transports.DailyRotateFile)({
|
const transportReports = new (winston.transports.DailyRotateFile)({
|
||||||
filename: 'logs/reports-%DATE%.log',
|
filename: 'logs/reports-%DATE%.log',
|
||||||
datePattern: 'YYYY-MM-DD',
|
datePattern: config.logging.logRotatePattern,
|
||||||
zippedArchive: true,
|
zippedArchive: config.logging.zippedArchive,
|
||||||
maxSize: '20m',
|
maxSize: config.logging.maxSize,
|
||||||
maxFiles: '14d',
|
maxFiles: config.logging.maxFiles,
|
||||||
level: 'verbose',
|
level: 'verbose',
|
||||||
timestamp: true,
|
timestamp: true,
|
||||||
eol: '\n',
|
eol: '\n',
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
import logger from '../logger';
|
|
||||||
|
|
||||||
export default class Monitor {
|
export default class Monitor {
|
||||||
|
|
||||||
constructor(inputManager, name, channel, config, pubSub) {
|
constructor(name, channel, env) {
|
||||||
this.config = config;
|
this.config = env.config;
|
||||||
this.pubSub = pubSub;
|
this.pubSub = env.pubSub;
|
||||||
this.input = inputManager;
|
this.logger = env.logger;
|
||||||
|
this.input = env.input;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.monitored = [];
|
this.monitored = [];
|
||||||
@@ -132,8 +132,7 @@ export default class Monitor {
|
|||||||
|
|
||||||
this.pubSub.publish(this.channel, alert);
|
this.pubSub.publish(this.channel, alert);
|
||||||
|
|
||||||
console.log(alert);
|
this.logger.log({
|
||||||
logger.log({
|
|
||||||
level: 'verbose',
|
level: 'verbose',
|
||||||
message: alert.message
|
message: alert.message
|
||||||
});
|
});
|
||||||
|
@@ -4,8 +4,8 @@ import ip from "ip";
|
|||||||
|
|
||||||
export default class MonitorHijack extends Monitor {
|
export default class MonitorHijack extends Monitor {
|
||||||
|
|
||||||
constructor(inputManager, name, channel, config, pubSub){
|
constructor(name, channel, env){
|
||||||
super(inputManager, name, channel, config, pubSub);
|
super(name, channel, env);
|
||||||
};
|
};
|
||||||
|
|
||||||
updateMonitoredPrefixes = () => {
|
updateMonitoredPrefixes = () => {
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import Monitor from "./monitor";
|
import Monitor from "./monitor";
|
||||||
import ipUtils from "../ipUtils";
|
import ipUtils from "../ipUtils";
|
||||||
import ip from "ip";
|
|
||||||
|
|
||||||
export default class MonitorVisibility extends Monitor {
|
export default class MonitorVisibility extends Monitor {
|
||||||
|
|
||||||
|
@@ -12,21 +12,19 @@
|
|||||||
"author": "Massimo Candela",
|
"author": "Massimo Candela",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"babel-cli": "^6.26.0",
|
||||||
"nodemon": "^1.19.1"
|
"nodemon": "^1.19.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"JSONStream": "^1.3.5",
|
|
||||||
"babel-cli": "^6.26.0",
|
|
||||||
"babel-core": "^6.26.3",
|
"babel-core": "^6.26.3",
|
||||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||||
"babel-preset-env": "^1.7.0",
|
"babel-preset-env": "^1.7.0",
|
||||||
"event-stream": "^4.0.1",
|
"event-stream": "^4.0.1",
|
||||||
"ip": "https://github.com/MaxCam/node-ip.git#contains-prefix",
|
"ip": "https://github.com/MaxCam/node-ip.git#contains-prefix",
|
||||||
"ip-address": "^5.9.2",
|
|
||||||
"ip2buf": "^2.0.0",
|
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"nodemailer": "^6.2.1",
|
"nodemailer": "^6.2.1",
|
||||||
|
"path": "^0.12.7",
|
||||||
"pubsub-js": "^1.7.0",
|
"pubsub-js": "^1.7.0",
|
||||||
"sleep": "^6.1.0",
|
"sleep": "^6.1.0",
|
||||||
"websocket-stream": "^5.5.0",
|
"websocket-stream": "^5.5.0",
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
|
|
||||||
export default class Report {
|
export default class Report {
|
||||||
|
|
||||||
constructor(channels, config, pubSub) {
|
constructor(channels, env) {
|
||||||
|
|
||||||
|
this.config = env.config;
|
||||||
|
this.logger = env.logger;
|
||||||
|
this.pubSub = env.pubSub;
|
||||||
|
|
||||||
this.config = config;
|
|
||||||
for (let channel of channels){
|
for (let channel of channels){
|
||||||
pubSub.subscribe(channel, (message, content) => {
|
env.pubSub.subscribe(channel, (message, content) => {
|
||||||
this.report(message, content);
|
this.report(message, content);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,10 @@
|
|||||||
import Report from "./report";
|
import Report from "./report";
|
||||||
import nodemailer from "nodemailer";
|
import nodemailer from "nodemailer";
|
||||||
import logger from '../logger';
|
|
||||||
|
|
||||||
|
|
||||||
export default class ReportEmail extends Report {
|
export default class ReportEmail extends Report {
|
||||||
|
|
||||||
constructor(channels, config, pubSub) {
|
constructor(channels, env) {
|
||||||
super(channels, config, pubSub);
|
super(channels, env);
|
||||||
|
|
||||||
if (this.config.emailConfig.enabled) {
|
if (this.config.emailConfig.enabled) {
|
||||||
this.transporter = nodemailer.createTransport({
|
this.transporter = nodemailer.createTransport({
|
||||||
@@ -32,7 +30,7 @@ export default class ReportEmail extends Report {
|
|||||||
text: "Hello world?"
|
text: "Hello world?"
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
logger.log({
|
this.logger.log({
|
||||||
level: 'error',
|
level: 'error',
|
||||||
message: error
|
message: error
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user