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

New reporter module for Alerta

Adding a new reporter module largely inspired by the existing
``reportSlack`` to report events in Alerta (https://alerta.io/) via the
HTTP API.
This commit is contained in:
Mircea Ulinic
2020-01-07 12:52:13 +00:00
parent 5a06bc8338
commit d12335176b
5 changed files with 157 additions and 4 deletions

View File

@@ -48,6 +48,7 @@ Please uncomment the related section and configure according to your needs.
- [reportSlack](docs/configuration.md#reportslack)
- [reportKafka](docs/configuration.md#reportkafka)
- [reportSyslog](docs/configuration.md#reportsyslog)
- [reportAlerta](docs/configuration.md#reportalerta)
- [Uptime monitoring](docs/uptime-monitor.md)
- [More information for developers](docs/develop.md)
- [All npm commands](docs/develop.md#all-npm-commands)

View File

@@ -129,7 +129,21 @@ reports:
# visibility: "++BGPalerter-5-${type}: ${summary}|${prefix}|${description}|${asn}|${earliest}|${latest}|${peers}"
# misconfiguration: "++BGPalerter-3-${type}: ${summary}|${asn}|${prefix}|${earliest}|${latest}"
# - file: reportAlerta
# channels:
# - hijack
# - newprefix
# - visibility
# - path
# - misconfiguration
# params:
# severity:
# hijack: 0
# newprefix: 2
# visibility: 4
# path: 7
# urls:
# default: _YOUR_ALERTA_API_URL_
############################
# Notification settings:

View File

@@ -270,7 +270,7 @@ Parameters for this report module:
|port| Port of the Kafka instance/broker (e.g. 9092).|
|topics| A dictionary containing a mapping from BGPalerter channels to Kafka topics (e.g. `hijack: hijack-topic`). By default all channels are sent to the topic `bgpalerter` (`default: bgpalerter`) |
#### reportSyslog
#### reportSyslog
This report module sends the alerts on Syslog.
@@ -282,4 +282,17 @@ Parameters for this report module:
|host| Host of the Syslog server (e.g. localhost).|
|port| Port of the Syslog server (e.g. 514).|
|templates| A dictionary containing string templates for each BGPalerter channels. If a channel doesn't have a template defined, the `default` template will be used (see `config.yml.example` for more details). |
#### reportAlerta
This report module sends alerts to [Alerta](https://alerta.io/).
Parameters for this report module:
|Parameter| Description |
|---|---|
|severity| The alert severity as number for a specific event. See https://docs.alerta.io/en/latest/api/alert.html#alert-severities for the list of possible values. |
|key| Optional, the Alerta API key to use for authenticated requests. |
|token| Optional value used when executing HTTP requests to the Alerta API with bearer authentication. |
|urls| A dictionary containing Alerta API URLs grouped by user group (key: group, value: API URL). |
|urls.default| The default user group. Each user group is an Alerta API URL. |

View File

@@ -172,4 +172,4 @@ export default class Report {
report = (message, content) => {
throw new Error('The method report must be implemented');
}
}
}

125
src/reports/reportAlerta.js Normal file
View File

@@ -0,0 +1,125 @@
/*
* 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 axios from "axios";
export default class ReportAlerta extends Report {
constructor(channels, params, env) {
super(channels, params, env);
this.environment = env.environment;
this.enabled = true;
if (!this.params.urls || !Object.keys(this.params.urls).length){
this.logger.log({
level: 'error',
message: "Alerta reporting is not enabled: no group is defined"
});
this.enabled = false;
} else {
if (!this.params.urls["default"]) {
this.logger.log({
level: 'error',
message: "In urls, for reportAlerta, a group named 'default' is required for communications to the admin."
});
}
}
this.headers = {};
if (this.params.key){
this.headers.Authorization = "Key " + this.params.key;
}
if (this.params.token){
this.headers.Authorization = "Bearer " + this.params.token;
}
}
_getResourceText = (message, context) => {
switch(message){
case "hijack", "visibility", "newprefix":
return context.prefix + " @ " + context.asn;
break;
default:
return message;
}
};
_createAlertaAlert = (url, message, content) => {
const severity = (this.params && this.params.severity && this.params.severity[message])
? this.params.severity[message]
: 5; // informational level
const context = this.getContext(message, content);
axios({
url: url + "/alert",
method: "POST",
headers: this.headers,
resposnseType: "json",
data: {
event: message,
resource: this._getResourceText(message, context),
text: content.message,
service: [(this.params.service || "BGPalerter")],
attributes: context,
severity: severity,
environment: this.environment
}
})
.catch((error) => {
this.logger.log({
level: 'error',
message: error
});
})
};
report = (message, content) => {
if (this.enabled){
let groups = content.data.map(i => i.matchedRule.group).filter(i => i != null);
groups = (groups.length) ? [...new Set(groups)] : Object.keys(this.params.urls); // If there are no groups defined, send to all of them
for (let group of groups) {
if (this.params.urls[group]) {
this._createAlertaAlert(this.params.urls[group], message, content);
}
}
}
}
}