1
0
mirror of https://github.com/nttgin/BGPalerter.git synced 2024-05-19 06:50:08 +00:00

working pull api

This commit is contained in:
Massimo Candela
2021-05-21 15:24:56 +02:00
parent fc24dd6c62
commit d063a4ebd4
6 changed files with 209 additions and 17 deletions

View File

@@ -241,6 +241,10 @@ reports:
notificationIntervalSeconds: 86400
persistStatus: true
rest:
host: null
port: 8011
logging:
directory: logs
logRotatePattern: YYYY-MM-DD

View File

@@ -111,6 +111,10 @@ export default class Config {
preCacheROAs: true,
refreshVrpListMinutes: 15
},
rest: {
host: null,
port: 8011
},
checkForUpdatesAtBoot: true,
pidFile: "bgpalerter.pid",
fadeOffSeconds: 360,

View File

@@ -53,7 +53,7 @@ export default class Input {
// This implements a fast basic fixed space cache, other approaches lru-like use too much cpu
setInterval(() => {
if (Object.keys(this.cache.matched).length > 10000) {
delete this.cache.matched;
this.cache.matched = {};
}
}, 10000);

View File

@@ -31,8 +31,8 @@
*/
import Uptime from "./uptime";
import restify from "restify";
import env from "../env";
import RestApi from "../utils/restApi";
export default class UptimeApi extends Uptime {
@@ -40,23 +40,16 @@ export default class UptimeApi extends Uptime {
super(connectors, params);
this.server = null;
this.connectors = connectors;
let restDefault = env.config.rest || { port: params.port, host: params.host };
const rest = new RestApi(restDefault);
try {
this.server = restify.createServer();
this.server.pre(restify.pre.sanitizePath());
this.server.get('/status', this.respond);
this.server.head('/status', this.respond);
if (params.host) {
this.server.listen(params.port, params.host);
} else {
this.server.listen(params.port);
}
} catch (error) {
rest.addUrl('/status', this.respond)
.catch(error => {
env.logger.log({
level: 'error',
message: error
});
}
});
};
respond = (req, res, next) => {

View File

@@ -0,0 +1,128 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2019, NTT Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import Report from "./report";
import RestApi from "../utils/restApi";
import md5 from "md5";
import moment from "moment";
export default class ReportPullAPI extends Report {
constructor(channels, params, env) {
super(channels, params, env);
this.name = "reportPullAPI" || this.params.name;
this.enabled = true;
this.maxAlertsAmount = 100;
this.lastCheck = null;
let restDefault = env.config.rest || { port: params.port, host: params.host };
const rest = new RestApi(restDefault);
rest.addUrl('/alerts', this.respond)
.catch(error => {
env.logger.log({
level: 'error',
message: error
});
});
rest.addUrl('/alerts/:hash', this.respond)
.catch(error => {
env.logger.log({
level: 'error',
message: error
});
});
rest.addUrl('/alerts/groups/:group', this.respond)
.catch(error => {
env.logger.log({
level: 'error',
message: error
});
});
this.alerts = [];
};
respond = (req, res, next) => {
res.contentType = 'json';
res.send({
meta: {
lastCheck: this.lastCheck
},
data: this._getAlerts(req.params)
});
next();
this.lastCheck = moment(new Date()).utc();
};
_getAlerts = ({ hash, group }) => {
let alerts;
if (group) {
alerts = this.alerts.filter(i => i.group === group);
} else if (hash) {
const mid = md5(hash);
alerts = this.alerts.filter(i => i.alert.hash === mid);
} else {
alerts = this.alerts;
}
return alerts.map(i => i.alert);
}
getUserGroup = (group) => {
const groups = this.params.hooks || this.params.userGroups;
return groups[group] || groups["default"];
};
report = (channel, content) => {
if (this.enabled) {
let groups = content.data.map(i => i.matchedRule.group).filter(i => i != null);
groups = (groups.length) ? [...new Set(groups)] : [this.getUserGroup("default")];
content.hash = md5(content.id);
for (let group of groups) {
this.alerts.push({
group,
alert: content
});
this.alerts = this.alerts.slice(-this.maxAlertsAmount);
}
}
};
}

63
src/utils/restApi.js Normal file
View File

@@ -0,0 +1,63 @@
import restify from "restify";
export default class RestApi {
static _instance;
constructor(params) {
this.params = params;
this.port = this.params.port || 8011;
this.host = this.params.host || null;
this.enabled = false;
this.urls = {};
this._serverPromise = null;
if (!!RestApi._instance) {
return RestApi._instance;
}
RestApi._instance = this;
}
_startServer = () => {
if (!this._serverPromise) {
this._serverPromise = new Promise((resolve, reject) => {
try {
if (this.host && this.port) {
this.server = restify.createServer();
this.server.pre(restify.pre.sanitizePath());
this.server.listen(this.port, this.host);
this.enabled = true;
resolve();
} else if (this.port) {
this.server = restify.createServer();
this.server.pre(restify.pre.sanitizePath());
this.server.listen(this.port);
this.enabled = true;
resolve();
} else {
this.enabled = false
reject("The port parameter must be specified to start the REST API.")
}
} catch (error) {
this.enabled = false;
reject(error);
}
});
}
return this._serverPromise;
};
addUrl = (url, callback) => {
if (this.urls[url]) {
return Promise.reject("The URL for the REST API already exists and cannot be replaced");
} else {
this.urls[url] = callback;
return this._startServer()
.then(() => {
this.server.get(url, this.urls[url]);
})
}
}
}