mirror of
https://github.com/nttgin/BGPalerter.git
synced 2024-05-19 06:50:08 +00:00
fixed include/excludeMonitor for monitorRPKI (#441) and improved tests
This commit is contained in:
@@ -141,7 +141,7 @@ export default class ConnectorRIS extends Connector {
|
||||
|
||||
if (monitoredPrefixes
|
||||
.filter(
|
||||
i => (ipUtils._isEqualPrefix(i.prefix, '0:0:0:0:0:0:0:0/0') || ipUtils._isEqualPrefix(i.prefix,'0.0.0.0/0'))
|
||||
i => (ipUtils.isEqualPrefix(i.prefix, '0:0:0:0:0:0:0:0/0') || ipUtils.isEqualPrefix(i.prefix,'0.0.0.0/0'))
|
||||
).length === 2) {
|
||||
|
||||
delete params.prefix;
|
||||
@@ -307,6 +307,5 @@ export default class ConnectorRIS extends Connector {
|
||||
} else if (message.type === 'ris_error') {
|
||||
throw new Error("Error from RIS: " + message.data.message);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
@@ -32,6 +32,7 @@
|
||||
|
||||
import Connector from "./connector";
|
||||
import {AS, Path} from "../model";
|
||||
import ipUtils from "ip-sub";
|
||||
|
||||
export default class ConnectorTest extends Connector{
|
||||
|
||||
@@ -451,41 +452,65 @@ export default class ConnectorTest extends Connector{
|
||||
|
||||
static transform = (message) => {
|
||||
if (message.type === 'ris_message') {
|
||||
message = message.data;
|
||||
const components = [];
|
||||
const announcements = message["announcements"] || [];
|
||||
const withdrawals = message["withdrawals"] || [];
|
||||
const aggregator = message["aggregator"] || null;
|
||||
const peer = message["peer"];
|
||||
try {
|
||||
message = message.data;
|
||||
const components = [];
|
||||
const announcements = message["announcements"] || [];
|
||||
const aggregator = message["aggregator"] || null;
|
||||
const withdrawals = message["withdrawals"] || [];
|
||||
const peer = message["peer"];
|
||||
const communities = message["community"] || [];
|
||||
const timestamp = message["timestamp"] * 1000;
|
||||
let path, originAS;
|
||||
|
||||
for (let announcement of announcements){
|
||||
const nextHop = announcement["next_hop"];
|
||||
const prefixes = announcement["prefixes"] || [];
|
||||
let path = new Path(message["path"].map(i => new AS(i)));
|
||||
let originAS = path.getLast();
|
||||
if (message["path"] && message["path"].length) {
|
||||
path = new Path(message["path"].map(i => new AS(i)));
|
||||
originAS = path.getLast();
|
||||
} else {
|
||||
path = new Path([]);
|
||||
originAS = null;
|
||||
}
|
||||
|
||||
for (let prefix of prefixes){
|
||||
if (originAS && path.length()) {
|
||||
for (let announcement of announcements) {
|
||||
const nextHop = announcement["next_hop"];
|
||||
|
||||
if (ipUtils.isValidIP(nextHop)) {
|
||||
const prefixes = (announcement["prefixes"] || [])
|
||||
.filter(prefix => ipUtils.isValidPrefix(prefix));
|
||||
|
||||
for (let prefix of prefixes) {
|
||||
components.push({
|
||||
type: "announcement",
|
||||
prefix,
|
||||
peer,
|
||||
path,
|
||||
originAS,
|
||||
nextHop,
|
||||
aggregator,
|
||||
timestamp,
|
||||
communities
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let prefix of withdrawals) {
|
||||
components.push({
|
||||
type: "announcement",
|
||||
type: "withdrawal",
|
||||
prefix,
|
||||
peer,
|
||||
path,
|
||||
originAS,
|
||||
nextHop,
|
||||
aggregator
|
||||
timestamp
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (let prefix of withdrawals){
|
||||
components.push({
|
||||
type: "withdrawal",
|
||||
prefix,
|
||||
peer
|
||||
})
|
||||
return components;
|
||||
} catch (error) {
|
||||
throw new Error(`Error during transform (${this.name}): ` + error.message);
|
||||
}
|
||||
|
||||
return components;
|
||||
} else if (message.type === 'ris_error') {
|
||||
throw new Error("Error from RIS: " + message.data.message);
|
||||
}
|
||||
};
|
||||
}
|
@@ -121,7 +121,7 @@ export default class Input {
|
||||
getMoreSpecificMatch = (prefix, includeIgnoredMorespecifics) => {
|
||||
|
||||
for (let p of this.prefixes) {
|
||||
if (ipUtils._isEqualPrefix(p.prefix, prefix)) { // Used internal method to avoid validation overhead
|
||||
if (ipUtils.isEqualPrefix(p.prefix, prefix)) {
|
||||
return p;
|
||||
} else {
|
||||
|
||||
|
@@ -253,18 +253,35 @@ export default class Monitor {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
getMoreSpecificMatch = (prefix, includeIgnoredMorespecifics) => {
|
||||
const matched = this.input.getMoreSpecificMatch(prefix, includeIgnoredMorespecifics);
|
||||
|
||||
if (matched) {
|
||||
if (matched.includeMonitors.length > 0 && !matched.includeMonitors.includes(this.name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (matched.excludeMonitors.includes(this.name)) ? null : matched;
|
||||
_included = (matched) => {
|
||||
if (matched.includeMonitors.length > 0) {
|
||||
return matched.includeMonitors.includes(this.name);
|
||||
} else {
|
||||
return !matched.excludeMonitors.includes(this.name);
|
||||
}
|
||||
};
|
||||
|
||||
getMoreSpecificMatch = (prefix, includeIgnoredMorespecifics, verbose=false) => {
|
||||
const matched = this.input.getMoreSpecificMatch(prefix, includeIgnoredMorespecifics);
|
||||
|
||||
if (matched) {
|
||||
const included = this._included(matched);
|
||||
|
||||
if (verbose) {
|
||||
return {
|
||||
matched,
|
||||
included
|
||||
};
|
||||
} else if (included) {
|
||||
return matched;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
}
|
@@ -57,7 +57,7 @@ export default class MonitorHijack extends Monitor {
|
||||
const message = alerts[0].matchedMessage;
|
||||
const asnText = matchedRule.asn;
|
||||
|
||||
return (ipUtils._isEqualPrefix(message.prefix, matchedRule.prefix)) ?
|
||||
return (ipUtils.isEqualPrefix(message.prefix, matchedRule.prefix)) ?
|
||||
`The prefix ${matchedRule.prefix} (${matchedRule.description}) is announced by ${message.originAS} instead of ${asnText}` :
|
||||
`A new prefix ${message.prefix} is announced by ${message.originAS}. ` +
|
||||
`It should be instead ${matchedRule.prefix} (${matchedRule.description}) announced by ${asnText}`;
|
||||
@@ -80,7 +80,6 @@ export default class MonitorHijack extends Monitor {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
monitor = (message) =>
|
||||
new Promise((resolve, reject) => {
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
import Monitor from "./monitor";
|
||||
import ipUtils from "ip-sub";
|
||||
|
||||
export default class MonitorNewPrefix extends Monitor {
|
||||
|
||||
@@ -56,7 +57,6 @@ export default class MonitorNewPrefix extends Monitor {
|
||||
const matchedRule = alerts[0].matchedRule;
|
||||
|
||||
return `Possible change of configuration. A new prefix ${message.prefix} is announced by ${message.originAS}. It is a more specific of ${matchedRule.prefix} (${matchedRule.description})`;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -68,7 +68,9 @@ export default class MonitorNewPrefix extends Monitor {
|
||||
const messagePrefix = message.prefix;
|
||||
const matchedRule = this.getMoreSpecificMatch(messagePrefix, false);
|
||||
|
||||
if (matchedRule && !matchedRule.ignore && matchedRule.asn.includes(message.originAS) && matchedRule.prefix !== messagePrefix) {
|
||||
if (matchedRule && !matchedRule.ignore &&
|
||||
matchedRule.asn.includes(message.originAS) &&
|
||||
!ipUtils.isEqualPrefix(matchedRule.prefix, messagePrefix)) {
|
||||
|
||||
this.publishAlert(message.originAS.getId() + "-" + message.prefix,
|
||||
matchedRule.asn.getId(),
|
||||
|
@@ -179,19 +179,27 @@ export default class MonitorRPKI extends Monitor {
|
||||
};
|
||||
|
||||
monitor = (message) => {
|
||||
try {
|
||||
const messageOrigin = message.originAS;
|
||||
const prefix = message.prefix;
|
||||
|
||||
const messageOrigin = message.originAS;
|
||||
const prefix = message.prefix;
|
||||
const matchedPrefixRule = this.getMoreSpecificMatch(prefix, false, true);
|
||||
|
||||
const matchedPrefixRule = this.getMoreSpecificMatch(prefix, false);
|
||||
|
||||
if (matchedPrefixRule && !matchedPrefixRule.ignore) {
|
||||
this.validate(message, matchedPrefixRule);
|
||||
} else {
|
||||
const matchedASRule = this.getMonitoredAsMatch(messageOrigin);
|
||||
if (matchedASRule) {
|
||||
this.validate(message, matchedASRule);
|
||||
if (matchedPrefixRule.matched) { // There is a prefix match
|
||||
if (!matchedPrefixRule.matched.ignore && matchedPrefixRule.included) { // The prefix match is not excluded in any way
|
||||
this.validate(message, matchedPrefixRule.matched);
|
||||
}
|
||||
} else { // No prefix match
|
||||
const matchedASRule = this.getMonitoredAsMatch(messageOrigin); // Try AS match
|
||||
if (matchedASRule) {
|
||||
this.validate(message, matchedASRule);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.log({
|
||||
level: 'error',
|
||||
message: error
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve(true);
|
||||
|
@@ -77,7 +77,7 @@ export default class MonitorVisibility extends Monitor {
|
||||
const messagePrefix = message.prefix;
|
||||
const matchedRule = this.getMoreSpecificMatch(messagePrefix, false);
|
||||
|
||||
if (matchedRule && !matchedRule.ignore && ipUtils._isEqualPrefix(matchedRule.prefix, messagePrefix)) {
|
||||
if (matchedRule && !matchedRule.ignore && ipUtils.isEqualPrefix(matchedRule.prefix, messagePrefix)) {
|
||||
|
||||
let key = matchedRule.prefix;
|
||||
|
||||
|
@@ -50,6 +50,7 @@ describe("Reports 2", function() {
|
||||
server.use(restify.plugins.bodyParser({ mapParams: true }));
|
||||
let expectedData = [
|
||||
"The prefix 2a00:5884::/32 (alarig fix test) is announced by AS15563 instead of AS204092, and AS45. Top 1 most used AS paths: [2,3,15563].",
|
||||
"A new prefix 165.254.255.0/25 is announced by AS15562, and AS4. It should be instead 165.254.255.0/24 (description 2) announced by AS15562. Top 1 most used AS paths: [2,3,[15562,4]].",
|
||||
"A new prefix 2a00:5884:ffff::/48 is announced by AS208585. It should be instead 2a00:5884::/32 (alarig fix test) announced by AS204092, and AS45. Top 1 most used AS paths: [2,3,208585].",
|
||||
];
|
||||
|
||||
|
Reference in New Issue
Block a user