2019-11-27 20:14:04 +01:00
/ *
* 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 .
* /
2020-06-28 18:21:50 +02:00
const chai = require ( "chai" ) ;
2020-06-28 21:18:16 +02:00
const fs = require ( "fs" ) ;
2020-06-28 18:21:50 +02:00
const chaiSubset = require ( 'chai-subset' ) ;
2020-07-06 02:01:01 +02:00
const Syslogd = require ( "syslogd" ) ;
2019-11-27 20:14:04 +01:00
chai . use ( chaiSubset ) ;
2020-06-28 18:21:50 +02:00
const expect = chai . expect ;
2020-06-28 20:38:33 +02:00
const volume = "volumetests/" ;
2020-06-28 21:18:16 +02:00
const cacheCloneDirectory = "tests/.cache_clone/" ;
2020-06-28 18:21:50 +02:00
const asyncTimeout = 20000 ;
2019-11-27 20:14:04 +01:00
global . EXTERNAL _VERSION _FOR _TEST = "0.0.1" ;
2020-06-28 20:38:33 +02:00
global . EXTERNAL _CONFIG _FILE = volume + "config.test.yml" ;
2019-11-27 20:14:04 +01:00
2020-07-06 02:01:01 +02:00
const worker = require ( "../index" ) ;
const pubSub = worker . pubSub ;
2019-11-27 20:14:04 +01:00
describe ( "Alerting" , function ( ) {
it ( "visibility reporting" , function ( done ) {
pubSub . publish ( "test-type" , "visibility" ) ;
const expectedData = {
"165.254.225.0/24" : {
id : '165.254.225.0/24' ,
origin : 'withdrawal-detection' ,
affected : 15562 ,
2020-01-18 18:48:08 +01:00
message : 'The prefix 165.254.225.0/24 (description 1) has been withdrawn. It is no longer visible from 4 peers'
2019-11-27 20:14:04 +01:00
} ,
"2a00:5884::/32" : {
id : '2a00:5884::/32' ,
origin : 'withdrawal-detection' ,
affected : "204092-45" ,
2020-01-18 18:48:08 +01:00
message : 'The prefix 2a00:5884::/32 (alarig fix test) has been withdrawn. It is no longer visible from 4 peers'
2020-01-24 15:14:17 +01:00
} ,
"2001:db8:123::/48" : {
id : '2001:db8:123::/48' ,
origin : 'withdrawal-detection' ,
affected : 65000 ,
message : 'The prefix 2001:db8:123::/48 (exact matching test) has been withdrawn. It is no longer visible from 4 peers'
2019-11-27 20:14:04 +01:00
}
} ;
2020-01-24 17:00:09 +01:00
let visibilityTestCompleted = false ;
2019-11-27 20:14:04 +01:00
pubSub . subscribe ( "visibility" , function ( type , message ) {
2020-01-24 17:00:09 +01:00
if ( ! visibilityTestCompleted ) {
2020-01-18 18:17:54 +01:00
message = JSON . parse ( JSON . stringify ( message ) ) ;
2019-11-27 20:14:04 +01:00
2020-01-18 18:17:54 +01:00
const id = message . id ;
2019-11-27 20:14:04 +01:00
2020-01-18 18:17:54 +01:00
expect ( Object . keys ( expectedData ) . includes ( id ) ) . to . equal ( true ) ;
expect ( expectedData [ id ] != null ) . to . equal ( true ) ;
2019-11-27 20:14:04 +01:00
2020-01-18 18:17:54 +01:00
expect ( message ) . to
. containSubset ( expectedData [ id ] ) ;
2019-11-27 20:14:04 +01:00
2020-01-18 18:17:54 +01:00
expect ( message ) . to . contain
. keys ( [
"latest" ,
"earliest"
] ) ;
2019-11-27 20:14:04 +01:00
2020-01-18 18:17:54 +01:00
delete expectedData [ id ] ;
if ( Object . keys ( expectedData ) . length === 0 ) {
2020-01-24 17:00:09 +01:00
setTimeout ( ( ) => {
visibilityTestCompleted = true ;
done ( ) ;
} , 5000 ) ;
2020-01-18 18:17:54 +01:00
}
2019-11-27 20:14:04 +01:00
}
} ) ;
} ) . timeout ( asyncTimeout ) ;
it ( "hijack reporting" , function ( done ) {
pubSub . publish ( "test-type" , "hijack" ) ;
const expectedData = {
"15562-4-165.254.255.0/25" : {
id : '15562-4-165.254.255.0/25' ,
origin : 'basic-hijack-detection' ,
affected : 15562 ,
2020-01-09 18:33:28 +01:00
message : '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' ,
2019-11-27 20:14:04 +01:00
data : [
{
extra : { } ,
matchedRule : {
prefix : "165.254.255.0/24" ,
group : "groupName" ,
description : "description 2" ,
asn : [ 15562 ] ,
ignoreMorespecifics : false
} ,
matchedMessage : {
type : "announcement" ,
prefix : "165.254.255.0/25" ,
peer : "124.0.0.2" ,
path : [ 1 , 2 , 3 , [ 4 , 15562 ] ] ,
originAS : [ 4 ] ,
nextHop : "124.0.0.2"
}
}
]
} ,
2020-01-18 01:45:02 +01:00
"208585-2a00:5884:ffff::/48" : {
id : '208585-2a00:5884:ffff::/48' ,
2019-11-27 20:14:04 +01:00
origin : 'basic-hijack-detection' ,
affected : "204092-45" ,
2020-01-18 01:45:02 +01:00
message : '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' ,
2019-11-27 20:14:04 +01:00
data : [
{
extra : { } ,
matchedRule : {
prefix : "2a00:5884::/32" ,
group : "default" ,
description : "alarig fix test" ,
asn : [ 204092 , 45 ] ,
ignoreMorespecifics : false
} ,
matchedMessage : {
type : "announcement" ,
2020-01-18 01:45:02 +01:00
prefix : "2a00:5884:ffff::/48" ,
2019-11-27 20:14:04 +01:00
peer : "124.0.0.3" ,
path : [ 1 , 2 , 3 , 208585 ] ,
originAS : [ 208585 ] ,
nextHop : "124.0.0.3"
}
}
]
} ,
"15563-2a00:5884::/32" : {
id : '15563-2a00:5884::/32' ,
origin : 'basic-hijack-detection' ,
affected : "204092-45" ,
message : 'The prefix 2a00:5884::/32 (alarig fix test) is announced by AS15563 instead of AS204092, and AS45' ,
data : [
{
extra : { } ,
matchedRule : {
prefix : "2a00:5884::/32" ,
group : "default" ,
description : "alarig fix test" ,
asn : [ 204092 , 45 ] ,
ignoreMorespecifics : false
} ,
matchedMessage : {
type : "announcement" ,
prefix : "2a00:5884::/32" ,
peer : "124.0.0.3" ,
path : [ 1 , 2 , 3 , 15563 ] ,
originAS : [ 15563 ] ,
nextHop : "124.0.0.3"
}
}
]
}
} ;
2020-01-24 17:00:09 +01:00
let hijackTestCompleted = false
2020-01-12 05:12:00 +01:00
pubSub . subscribe ( "hijack" , function ( type , message ) {
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
if ( ! hijackTestCompleted ) {
message = JSON . parse ( JSON . stringify ( message ) ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
const id = message . id ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( Object . keys ( expectedData ) . includes ( id ) ) . to . equal ( true ) ;
expect ( expectedData [ id ] != null ) . to . equal ( true ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( message ) . to
. containSubset ( expectedData [ id ] ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( message ) . to . contain
. keys ( [
"latest" ,
"earliest"
] ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
delete expectedData [ id ] ;
if ( Object . keys ( expectedData ) . length === 0 ) {
setTimeout ( ( ) => {
hijackTestCompleted = true ;
done ( ) ;
} , 5000 ) ;
}
2019-11-27 20:14:04 +01:00
}
} ) ;
} ) . timeout ( asyncTimeout ) ;
it ( "newprefix reporting" , function ( done ) {
pubSub . publish ( "test-type" , "newprefix" ) ;
const expectedData = {
"1234-175.254.205.0/25" : {
id : '1234-175.254.205.0/25' ,
origin : 'prefix-detection' ,
affected : 1234 ,
2020-01-18 18:48:08 +01:00
message : 'Possible change of configuration. A new prefix 175.254.205.0/25 is announced by AS1234. It is a more specific of 175.254.205.0/24 (include exclude test)' ,
2019-11-27 20:14:04 +01:00
data : [
{
extra : { } ,
matchedRule : {
prefix : '175.254.205.0/24' ,
group : 'default' ,
description : 'include exclude test' ,
asn : [ 1234 ] ,
ignoreMorespecifics : false ,
ignore : false ,
excludeMonitors : [ "basic-hijack-detection" , "withdrawal-detection" ]
} ,
matchedMessage : {
type : 'announcement' ,
prefix : '175.254.205.0/25' ,
peer : '124.0.0.3' ,
path : [ 1 , 2 , 3 , 1234 ] ,
originAS : [ 1234 ] ,
nextHop : '124.0.0.3'
}
}
]
} ,
"1234-170.254.205.0/25" : {
id : '1234-170.254.205.0/25' ,
origin : 'prefix-detection' ,
affected : 1234 ,
2020-01-18 18:48:08 +01:00
message : 'Possible change of configuration. A new prefix 170.254.205.0/25 is announced by AS1234. It is a more specific of 170.254.205.0/24 (include exclude test)' ,
2019-11-27 20:14:04 +01:00
data : [
{
extra : { } ,
matchedRule : {
prefix : '170.254.205.0/24' ,
group : 'default' ,
description : 'include exclude test' ,
asn : [ 1234 ] ,
ignoreMorespecifics : false ,
includeMonitors : [ "prefix-detection" ] ,
ignore : false
} ,
matchedMessage : {
type : 'announcement' ,
prefix : '170.254.205.0/25' ,
peer : '124.0.0.3' ,
path : [ 1 , 2 , 3 , 1234 ] ,
originAS : [ 1234 ] ,
nextHop : '124.0.0.3'
}
}
]
} ,
"15562-165.254.255.0/25" :
{
id : '15562-165.254.255.0/25' ,
origin : 'prefix-detection' ,
affected : 15562 ,
2020-01-18 18:48:08 +01:00
message : 'Possible change of configuration. A new prefix 165.254.255.0/25 is announced by AS15562. It is a more specific of 165.254.255.0/24 (description 2)' ,
2019-11-27 20:14:04 +01:00
data : [
{
extra : { } ,
matchedRule : {
prefix : '165.254.255.0/24' ,
group : 'groupName' ,
description : 'description 2' ,
asn : [ 15562 ] ,
ignoreMorespecifics : false
} ,
matchedMessage : {
type : 'announcement' ,
prefix : '165.254.255.0/25' ,
peer : '124.0.0.2' ,
path : [ 1 , 2 , 3 , 15562 ] ,
originAS : [ 15562 ] ,
nextHop : '124.0.0.2'
}
}
]
} ,
2020-01-18 01:45:02 +01:00
"204092-2a00:5884:ffff::/48" : {
id : '204092-2a00:5884:ffff::/48' ,
2019-11-27 20:14:04 +01:00
origin : 'prefix-detection' ,
affected : "204092-45" ,
2020-01-18 18:48:08 +01:00
message : 'Possible change of configuration. A new prefix 2a00:5884:ffff::/48 is announced by AS204092. It is a more specific of 2a00:5884::/32 (alarig fix test)' ,
2019-11-27 20:14:04 +01:00
data : [
{
extra : { } ,
matchedRule : {
prefix : '2a00:5884::/32' ,
group : 'default' ,
description : 'alarig fix test' ,
asn : [ 204092 , 45 ] ,
ignoreMorespecifics : false
} ,
matchedMessage : {
type : 'announcement' ,
2020-01-18 01:45:02 +01:00
prefix : '2a00:5884:ffff::/48' ,
2019-11-27 20:14:04 +01:00
peer : '124.0.0.3' ,
path : [ 1 , 2 , 3 , 204092 ] ,
originAS : [ 204092 ] ,
nextHop : '124.0.0.3'
}
}
]
}
} ;
2020-01-24 17:00:09 +01:00
let newprefixTestCompleted = false ;
2019-11-27 20:14:04 +01:00
pubSub . subscribe ( "newprefix" , function ( type , message ) {
2020-01-24 17:00:09 +01:00
if ( ! newprefixTestCompleted ) {
message = JSON . parse ( JSON . stringify ( message ) ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
const id = message . id ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( Object . keys ( expectedData ) . includes ( id ) ) . to . equal ( true ) ;
expect ( expectedData [ id ] != null ) . to . equal ( true ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( message ) . to
. containSubset ( expectedData [ id ] ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( message ) . to . contain
. keys ( [
"latest" ,
"earliest"
] ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
delete expectedData [ id ] ;
if ( Object . keys ( expectedData ) . length === 0 ) {
setTimeout ( ( ) => {
newprefixTestCompleted = true ;
done ( ) ;
} , 5000 ) ;
}
2019-11-27 20:14:04 +01:00
}
} ) ;
} ) . timeout ( asyncTimeout ) ;
it ( "path match reporting" , function ( done ) {
pubSub . publish ( "test-type" , "path" ) ;
const expectedData = {
"98.5.4.3/22" : {
id : '98.5.4.3/22' ,
origin : 'path-matching' ,
affected : "98.5.4.3/22" ,
2020-01-18 18:48:08 +01:00
message : 'Matched test description on prefix 98.5.4.3/22 (including length violation) 1 times' ,
2019-11-27 20:14:04 +01:00
data : [
{
extra : {
lengthViolation : true
} ,
matchedRule : {
prefix : '98.5.4.3/22' ,
group : 'default' ,
description : 'path matching test regex and maxLength' ,
asn : [ 2914 ] ,
ignoreMorespecifics : false ,
ignore : false ,
path : {
match : ".*2914$" ,
matchDescription : "test description" ,
maxLength : 3 ,
}
} ,
matchedMessage : {
type : 'announcement' ,
prefix : '98.5.4.3/22' ,
peer : '124.0.0.3' ,
path : [ 1 , 2 , 3 , 4321 , 5060 , 2914 ] ,
originAS : [ 2914 ] ,
nextHop : '124.0.0.3'
}
}
]
} ,
"99.5.4.3/22" : {
id : '99.5.4.3/22' ,
origin : 'path-matching' ,
affected : "99.5.4.3/22" ,
2020-01-18 18:48:08 +01:00
message : 'Matched test description on prefix 99.5.4.3/22 1 times' ,
2019-11-27 20:14:04 +01:00
data : [
{
extra : {
lengthViolation : false
} ,
matchedRule : {
prefix : '99.5.4.3/22' ,
group : 'default' ,
description : 'path matching test regex and minLength' ,
asn : [ 2914 ] ,
ignoreMorespecifics : false ,
ignore : false ,
path : {
match : ".*2914$" ,
matchDescription : "test description" ,
minLength : 2 ,
}
} ,
matchedMessage : {
type : 'announcement' ,
prefix : '99.5.4.3/22' ,
peer : '124.0.0.3' ,
path : [ 1 , 2 , 3 , 4321 , 5060 , 2914 ] ,
originAS : [ 2914 ] ,
nextHop : '124.0.0.3'
}
}
]
} ,
} ;
2020-01-24 17:00:09 +01:00
let pathTestCompleted = false ;
2019-11-27 20:14:04 +01:00
pubSub . subscribe ( "path" , function ( type , message ) {
2020-01-24 17:00:09 +01:00
if ( ! pathTestCompleted ) {
message = JSON . parse ( JSON . stringify ( message ) ) ;
const id = message . id ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( Object . keys ( expectedData ) . includes ( id ) ) . to . equal ( true ) ;
expect ( expectedData [ id ] != null ) . to . equal ( true ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( message ) . to
. containSubset ( expectedData [ id ] ) ;
2019-11-28 15:49:06 +01:00
2020-01-24 17:00:09 +01:00
expect ( message ) . to . contain
. keys ( [
"latest" ,
"earliest"
] ) ;
2019-11-28 15:49:06 +01:00
2020-01-24 17:00:09 +01:00
delete expectedData [ id ] ;
if ( Object . keys ( expectedData ) . length === 0 ) {
setTimeout ( ( ) => {
pathTestCompleted = true ;
done ( ) ;
} , 5000 ) ;
}
2019-11-28 15:49:06 +01:00
}
} ) ;
} ) . timeout ( asyncTimeout ) ;
it ( "asn monitoring reporting" , function ( done ) {
pubSub . publish ( "test-type" , "misconfiguration" ) ;
const expectedData = {
2020-01-24 17:00:09 +01:00
"2914-2.2.2.3/22" : {
id : "2914-2.2.2.3/22" ,
2019-11-28 15:49:06 +01:00
origin : 'asn-monitor' ,
affected : 2914 ,
2019-11-28 19:14:01 +01:00
message : 'AS2914 is announcing 2.2.2.3/22 but this prefix is not in the configured list of announced prefixes' ,
2020-01-24 17:00:09 +01:00
} ,
"2914-2001:db9:123::/49" : {
id : '2914-2001:db9:123::/49' ,
origin : 'asn-monitor' ,
affected : 2914 ,
message : 'AS2914 is announcing 2001:db9:123::/49 but this prefix is not in the configured list of announced prefixes' ,
2019-11-28 15:49:06 +01:00
}
} ;
2020-01-24 17:00:09 +01:00
let misconfigurationTestCompleted = false ;
2019-11-28 15:49:06 +01:00
pubSub . subscribe ( "misconfiguration" , function ( type , message ) {
2020-01-24 17:00:09 +01:00
if ( ! misconfigurationTestCompleted ) {
message = JSON . parse ( JSON . stringify ( message ) ) ;
const id = message . id ;
2019-11-28 15:49:06 +01:00
2020-01-24 17:00:09 +01:00
expect ( Object . keys ( expectedData ) . includes ( id ) ) . to . equal ( true ) ;
expect ( expectedData [ id ] != null ) . to . equal ( true ) ;
2019-11-28 15:49:06 +01:00
2020-01-24 17:00:09 +01:00
expect ( message ) . to
. containSubset ( expectedData [ id ] ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
expect ( message ) . to . contain
. keys ( [
"latest" ,
"earliest"
] ) ;
2019-11-27 20:14:04 +01:00
2020-01-24 17:00:09 +01:00
delete expectedData [ id ] ;
if ( Object . keys ( expectedData ) . length === 0 ) {
setTimeout ( ( ) => {
misconfigurationTestCompleted = true ;
done ( ) ;
} , 5000 ) ;
}
2019-11-27 20:14:04 +01:00
}
} ) ;
2020-01-18 18:17:54 +01:00
} ) . timeout ( asyncTimeout ) ;
it ( "fading alerting" , function ( done ) {
pubSub . publish ( "test-type" , "fade-off" ) ;
let notReceived = true ;
setTimeout ( ( ) => {
if ( notReceived ) {
done ( ) ;
}
} , 15000 ) ;
2019-11-27 20:14:04 +01:00
2020-01-18 18:17:54 +01:00
pubSub . subscribe ( "visibility" , function ( type , message ) {
notReceived = false ;
} ) ;
2019-11-27 20:14:04 +01:00
} ) . timeout ( asyncTimeout ) ;
2020-06-28 21:18:16 +02:00
} ) ;
describe ( "Status storage" , function ( ) {
it ( "alerts stored" , function ( done ) {
const files = fs . readdirSync ( cacheCloneDirectory ) ;
for ( let f of files ) {
const fileClone = cacheCloneDirectory + f ;
const fileOriginal = volume + ".cache/" + f ;
const exists = fs . existsSync ( fileOriginal ) ;
2019-11-27 20:14:04 +01:00
2020-06-28 21:18:16 +02:00
expect ( exists ) . to . equal ( true ) ;
if ( exists ) {
const clone = JSON . parse ( fs . readFileSync ( fileClone , 'utf8' ) ) . value ;
const original = JSON . parse ( fs . readFileSync ( fileOriginal , 'utf8' ) ) . value ;
expect ( original . sent ) . to . have . keys ( Object . keys ( clone . sent ) ) ;
}
}
done ( ) ;
} ) . timeout ( asyncTimeout ) ;
2019-11-27 20:14:04 +01:00
} ) ;