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

v1.26.0 release hotfix (#295)

* updated development dependencies to bump lodash version to 4.17.19

* updated rpki-validator version

* update rpki-validator to support external vrps

* improved stability of monitorRPKI, increased test coverage
This commit is contained in:
Massimo Candela
2020-07-18 18:43:30 +02:00
committed by GitHub
parent 8cd07e465b
commit a8647f6dee
20 changed files with 676 additions and 233 deletions

View File

@@ -9,6 +9,8 @@ jobs:
script: npm run test
- name: "Tests reports"
script: npm run test-reports
- name: "Tests rpki"
script: npm run test-rpki
- name: "Tests with proxy"
before_script:
- npm install -g anyproxy

View File

@@ -3,7 +3,13 @@
[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
# BGPalerter
Real-time BGP monitoring tool, pre-configured for visibility loss and hijacks detection.
Self-configuring BGP monitoring tool, which will allow you to monitor in **real-time** if:
* any of your prefixes loses visibility;
* any of your prefixes is hijacked;
* your AS is announcing a RPKI invalid prefix (e.g. not matching prefix length);
* your AS is announcing a prefix not covered by a ROA;
* your AS is announcing a new prefix that was never announced before;
* one of the AS path used to reach your prefix matches a specific condition defined by you.
You just run it. You don't need to provide any data source or connect it to anything in your network since it connects to public repos.
@@ -46,18 +52,25 @@ Read the documentation below for more options.
- [Prefix attributes description](docs/prefixes.md#prefixes-fields)
- [Configuration](docs/configuration.md)
- [Composition](docs/configuration.md#composition)
- [Connectors](docs/configuration.md#connectors)
- [Monitors](docs/configuration.md#monitors)
- [Reports](docs/configuration.md#reports)
- [reportFile](docs/configuration.md#reportfile)
- [reportEmail](docs/configuration.md#reportemail)
- [reportSlack](docs/configuration.md#reportslack)
- [reportKafka](docs/configuration.md#reportkafka)
- [reportSyslog](docs/configuration.md#reportsyslog)
- [reportAlerta](docs/configuration.md#reportalerta)
- [reportWebex](docs/configuration.md#reportwebex)
- [reportHTTP](docs/configuration.md#reporthttp)
- [reportTelegram](docs/configuration.md#reporttelegram)
- [Monitor for](docs/configuration.md#monitors)
- [Hijacks](docs/configuration.md#monitorhijack)
- [Visibility loss](docs/configuration.md#monitorvisibility)
- [RPKI invalid announcements](docs/configuration.md#monitorrpki)
- [Announcements of more specifics](docs/configuration.md#monitornewprefix)
- [Announcements of new prefixes](docs/configuration.md#monitoras)
- [Path matching](docs/configuration.md#monitorpath)
- [Send alerts to](docs/configuration.md#reports)
- [File](docs/configuration.md#reportfile)
- [E-mail](docs/configuration.md#reportemail)
- [Slack](docs/configuration.md#reportslack)
- [Kafka](docs/configuration.md#reportkafka)
- [Syslog](docs/configuration.md#reportsyslog)
- [Alerta dashboard](docs/configuration.md#reportalerta)
- [Webex](docs/configuration.md#reportwebex)
- [HTTP URL](docs/configuration.md#reporthttp)
- [Telegram](docs/configuration.md#reporttelegram)
- [Mattermost](docs/report-http.md#mattermost)
- [Pushover](docs/report-http.md#pushover)
- [Process/Uptime monitoring](docs/process-monitors.md)
- [Notification user groups](docs/usergroups.md)
- [HTTP/HTTPS proxy](docs/http-proxy.md)

View File

@@ -49,6 +49,8 @@ monitors:
params:
thresholdMinPeers: 1
checkUncovered: false
preCacheROAs: true,
refreshVrpListMinutes: 15
reports:
- file: reportFile

View File

@@ -41,7 +41,7 @@ You can compose the tool with 3 main components: connectors, monitors, and repor
* Connectors retrieve/listen to the data from different sources and transform them to a common format.
* Monitors analyze the data flow and produce alerts. Different monitors try to detect different issues.
* Reports send/store the alerts, e.g. by email or to a file.
* Reports send/store the alerts, e.g. by email or to a file. Reports can also provide the data triggering such alerts.
> In config.yml.example there are all the possible components declarations (similar to the one of the example below). You can enable the various components by uncommenting the related block.
@@ -109,6 +109,9 @@ Each connector is composed of:
### Connectors
Connectors retrieve/listen to the data from different sources and transform them to a common format.
Possible connectors are:
#### connectorRIS
It connects to RIPE RIS https://ris-live.ripe.net/ and receives BGP updates coming from 600+ peers.
@@ -128,6 +131,9 @@ Connector used for testing purposes, it provokes all types of alerting. Needed t
### Monitors
Monitors analyze the data flow and produce alerts. Different monitors try to detect different issues.
Possible monitors are:
#### monitorHijack
@@ -300,14 +306,33 @@ Parameters for this monitor module:
|Parameter| Description|
|---|---|
|checkUncovered| If set to true, the monitor will alert also for prefixes not covered by ROAs in addition of RPKI invalid prefixes. |
|preCacheROAs| This parameter allows to download locally VRPs lists. This is suggested in the case you want to validate many BGP updates (e.g. for research purposes). For normal production monitoring do NOT set this parameter. |
|preCacheROAs| When this parameter is set to true (default), BGPalerter will download Validated ROA Payloads (VRPs) lists locally instead of using online validation. More info [here](https://github.com/massimocandela/rpki-validator).|
|refreshVrpListMinutes| If `preCacheROAs` is set to true, this parameter allows to specify a refresh time for the VRPs lists (it has to be > 15 minutes) |
|thresholdMinPeers| Minimum number of peers that need to see the BGP update before to trigger an alert. |
|vrpProvider| A string indicating the provider of the VRPs list. Possible options are: `ntt` (default), `ripe`, `external`. Use external only if you wish to specify a file with `vrpFile`. More info [here](https://github.com/massimocandela/rpki-validator#options).|
|vrpFile| A JSON file with an array of VRPs. See example below.|
|maxDataSamples| Maximum number of collected BGP messages for each alert which doesn't reach yet the `thresholdMinPeers`. Default to 1000. As soon as the `thresholdMinPeers` is reached, the collected BGP messages are flushed, independently from the value of `maxDataSamples`.|
> VRPs file example:
> ```json5
> [
> {
> "prefix": "123.4.5.0/22",
> "asn": "1234",
> "maxLength": 24
> },
> {
> "prefix": "321.4.5.0/22",
> "asn": "9876",
> "maxLength": 22
> }
> ]
> ```
### Reports
Reports send/store the alerts, e.g. by email or to a file. Reports can also provide the data triggering such alerts.
Possible reports are:
#### reportFile
@@ -426,6 +451,7 @@ Parameters for this report module:
|headers| Additional headers to use in the GET request. For example for authentication.|
|showPaths| Amount of AS_PATHs to report in the alert (0 to disable). |
[See here some examples of how to adapt reportHTTP to some common applications.](report-http.md)
#### reportTelegram

87
docs/report-http.md Normal file
View File

@@ -0,0 +1,87 @@
# Send alerts with POST requests
BGPalerter can send alerts by means of POST requests to a provided URL.
This can be done by configuring the module reportHTTP. Read [here](configuration.md#reporthttp) to understand how.
For configuring reportHTTP, essentially you need to specify two things:
* The URL
* A template of the POST request.
If you are using [user groups](usergroups.md), you can specify a URL for every user group. This can be done inside `hooks`, a dictionary containing API URLs grouped by user group (key: group, value: URL).
The default user group is mandatory.
Example:
```yaml
hooks:
default: https://MY_WEB_HOOK/
noc: https://MY_WEB_HOOK_FOR_THE_NOC_GROUP
```
You can also specify a template for each type of alert (channel).
Example:
```yaml
isTemplateJSON: true
templates:
default: '{"message": "${summary}", "color": "blue"}'
visibility: '{"message": "${summary}", "color": "orange"}'
```
Templates are expressed as strings. If the parameter `isTemplateJSON` is set to true, the string will be converted to JSON before to be posted.
What follows is a list of examples showing how to adapt this module to some well-known applications.
## Mattermost
Mattermost is an open source messaging platform.
```yaml
reports:
- file: reportHTTP
channels:
- hijack
- newprefix
- visibility
- path
- misconfiguration
- rpki
params:
templates:
default: '{"attachments": [
{"fields": [ {"title": "Prefix:", "value": "${prefix}", "short": "false"},
{"title": "Expected from:", "value": "AS ${asn}", "short": "true"},
{"title": "Seen from:", "value": "AS ${neworigin}", "short": "true"},
{"title": "Since:", "value": "${earliest}", "short": "true"},
{"title": "Event description":, "value": "${summary}"} ],
"text": "#bgpalerter #${type}", "color": "#ffffff"}]}'
isTemplateJSON: true
headers:
showPaths: 0 # Amount of AS_PATHs to report in the alert
hooks:
default: WEBHOOK_URL
```
Thanks to [@fstolba](https://github.com/nttgin/BGPalerter/issues/81).
## Pushover
Pushover is an app that makes it easy to get real-time notifications on your Android, iPhone, iPad, and Desktop.
```yaml
- file: reportHTTP
channels:
- hijack
- newprefix
- visibility
- path
- misconfiguration
- rpki
params:
templates:
default: '{"message": "${channel}: ${summary}", "title": "BGPalerter", "priority": "1", "token": "_YOUR_API_TOKEN_HERE_", "user": "_YOUR_USER_KEY_HERE_"}'
headers:
isTemplateJSON: true
showPaths: 0
hooks:
default: https://api.pushover.net/1/messages.json
```
Thanks to [Hugo Salgado](https://twitter.com/huguei/status/1278771420525408258).

View File

@@ -3,5 +3,5 @@
BGPalerter can be easily updated. The configuration of BGPalerter is persisted in `config.yml` and `prefixes.yml`, as long as you preserve such files you will not need to reconfigure it after the update.
* if you are using the binary, go in the [releases tab](https://github.com/nttgin/BGPalerter/releases), download the new binary and replace the old one.
* if you are using the source code, simply do a git pull of the master branch.
* if you are using docker, do `docker pull nttgin/bgpalerter:latest`, after stop and remove your current container and [run it again](installation.md#running-bgpalerter-in-docker).
* if you are using the source code, simply do a git pull of the master branch. After, do `npm install` to update the dependencies.
* if you are using docker, do `docker pull nttgin/bgpalerter:latest`, after stop and remove your current container and [run it again](installation.md#running-bgpalerter-in-docker).

277
package-lock.json generated
View File

@@ -5,9 +5,9 @@
"requires": true,
"dependencies": {
"@babel/cli": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.10.4.tgz",
"integrity": "sha512-xX99K4V1BzGJdQANK5cwK+EpF1vP9gvqhn+iWvG+TubCjecplW7RSQimJ2jcCvu6fnK5pY6mZMdu6EWTj32QVA==",
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.10.5.tgz",
"integrity": "sha512-j9H9qSf3kLdM0Ao3aGPbGZ73mEA9XazuupcS6cDGWuiyAcANoguhP0r2Lx32H5JGw4sSSoHG3x/mxVnHgvOoyA==",
"dev": true,
"requires": {
"chokidar": "^2.1.8",
@@ -15,7 +15,7 @@
"convert-source-map": "^1.1.0",
"fs-readdir-recursive": "^1.1.0",
"glob": "^7.0.0",
"lodash": "^4.17.13",
"lodash": "^4.17.19",
"make-dir": "^2.1.0",
"slash": "^2.0.0",
"source-map": "^0.5.0"
@@ -66,35 +66,89 @@
}
},
"@babel/core": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.4.tgz",
"integrity": "sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA==",
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.5.tgz",
"integrity": "sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
"@babel/generator": "^7.10.4",
"@babel/helper-module-transforms": "^7.10.4",
"@babel/generator": "^7.10.5",
"@babel/helper-module-transforms": "^7.10.5",
"@babel/helpers": "^7.10.4",
"@babel/parser": "^7.10.4",
"@babel/parser": "^7.10.5",
"@babel/template": "^7.10.4",
"@babel/traverse": "^7.10.4",
"@babel/types": "^7.10.4",
"@babel/traverse": "^7.10.5",
"@babel/types": "^7.10.5",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.1",
"json5": "^2.1.2",
"lodash": "^4.17.13",
"lodash": "^4.17.19",
"resolve": "^1.3.2",
"semver": "^5.4.1",
"source-map": "^0.5.0"
},
"dependencies": {
"@babel/generator": {
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz",
"integrity": "sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig==",
"dev": true,
"requires": {
"@babel/types": "^7.10.5",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
},
"@babel/helper-module-transforms": {
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz",
"integrity": "sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.10.4",
"@babel/helper-replace-supers": "^7.10.4",
"@babel/helper-simple-access": "^7.10.4",
"@babel/helper-split-export-declaration": "^7.10.4",
"@babel/template": "^7.10.4",
"@babel/types": "^7.10.5",
"lodash": "^4.17.19"
}
},
"@babel/parser": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
"integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz",
"integrity": "sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ==",
"dev": true
},
"@babel/traverse": {
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz",
"integrity": "sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
"@babel/generator": "^7.10.5",
"@babel/helper-function-name": "^7.10.4",
"@babel/helper-split-export-declaration": "^7.10.4",
"@babel/parser": "^7.10.5",
"@babel/types": "^7.10.5",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.19"
}
},
"@babel/types": {
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz",
"integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"lodash": "^4.17.19",
"to-fast-properties": "^2.0.0"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -424,15 +478,15 @@
}
},
"@babel/node": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/node/-/node-7.10.4.tgz",
"integrity": "sha512-U41uyQkG0J1ezCb8KCdhDJotQF68Z/OsUbcgdxaC0M4JoXKZVdaKQJ+ecnr7aaWjNLt0Vee6Vddj6VL4JEMJnQ==",
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/node/-/node-7.10.5.tgz",
"integrity": "sha512-suosS7zZ2roj+fYVCnDuVezUbRc0sdoyF0Gj/1FzWxD4ebbGiBGtL5qyqHH4NO34B5m4vWWYWgyNhSsrqS8vwA==",
"dev": true,
"requires": {
"@babel/register": "^7.10.4",
"@babel/register": "^7.10.5",
"commander": "^4.0.1",
"core-js": "^3.2.1",
"lodash": "^4.17.13",
"lodash": "^4.17.19",
"node-environment-flags": "^1.0.5",
"regenerator-runtime": "^0.13.4",
"resolve": "^1.13.1",
@@ -1056,13 +1110,13 @@
}
},
"@babel/register": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/register/-/register-7.10.4.tgz",
"integrity": "sha512-whHmgGiWNVyTVnYTSawtDWhaeYsc+noeU8Rmi+MPnbGhDYmr5QpEDMrQcIA07D2RUv0BlThPcN89XcHCqq/O4g==",
"version": "7.10.5",
"resolved": "https://registry.npmjs.org/@babel/register/-/register-7.10.5.tgz",
"integrity": "sha512-eYHdLv43nyvmPn9bfNfrcC4+iYNwdQ8Pxk1MFJuU/U5LpSYl/PH4dFMazCYZDFVi8ueG3shvO+AQfLrxpYulQw==",
"dev": true,
"requires": {
"find-cache-dir": "^2.0.0",
"lodash": "^4.17.13",
"lodash": "^4.17.19",
"make-dir": "^2.1.0",
"pirates": "^4.0.0",
"source-map-support": "^0.5.16"
@@ -1077,15 +1131,6 @@
"regenerator-runtime": "^0.13.4"
}
},
"@babel/runtime-corejs3": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz",
"integrity": "sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw==",
"requires": {
"core-js-pure": "^3.0.0",
"regenerator-runtime": "^0.13.4"
}
},
"@babel/template": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
@@ -1185,99 +1230,88 @@
}
},
"@sentry/apm": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@sentry/apm/-/apm-5.19.0.tgz",
"integrity": "sha512-CwjXwkj31TlktW3FAM9GqF9zbjAyH58nrguCwx/uPTkpJN1Uj4MGh74oWFo45a4f/cLjjrpLA/mbwBdhs0z8sw==",
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/@sentry/apm/-/apm-5.19.2.tgz",
"integrity": "sha512-V7p5niqG/Nn1OSMAyreChiIrQFYzFHKADKNaDEvIXqC4hxFnMG8lPRqEFJH49fNjsFBFfIG9iY1rO1ZFg3S42Q==",
"requires": {
"@sentry/browser": "5.19.0",
"@sentry/hub": "5.19.0",
"@sentry/minimal": "5.19.0",
"@sentry/types": "5.19.0",
"@sentry/utils": "5.19.0",
"@sentry/browser": "5.19.2",
"@sentry/hub": "5.19.2",
"@sentry/minimal": "5.19.2",
"@sentry/types": "5.19.2",
"@sentry/utils": "5.19.2",
"tslib": "^1.9.3"
}
},
"@sentry/browser": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.19.0.tgz",
"integrity": "sha512-Cz8PnzC5NGfpHIGCmHLgA6iDEBVELwo4Il/iFweXjs4+VL4biw62lI32Q4iLCCpmX0t5UvrWBOnju2v8zuFIjA==",
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.19.2.tgz",
"integrity": "sha512-o6Z532n+0N5ANDzgR9GN+Q6CU7zVlIJvBEW234rBiB+ZZj6XwTLS1dD+JexGr8lCo8PeXI2rypKcj1jUGLVW8w==",
"requires": {
"@sentry/core": "5.19.0",
"@sentry/types": "5.19.0",
"@sentry/utils": "5.19.0",
"@sentry/core": "5.19.2",
"@sentry/types": "5.19.2",
"@sentry/utils": "5.19.2",
"tslib": "^1.9.3"
}
},
"@sentry/core": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.19.0.tgz",
"integrity": "sha512-ry1Zms6jrVQPEwmfywItyUhOgabPrykd8stR1x/u2t1YiISWlR813fE5nzdwgW5mxEitXz/ikTwvrfK3egsDWQ==",
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.19.2.tgz",
"integrity": "sha512-sfbBsVXpA0WYJUichz5IhvqKD8xJUfQvsszrTsUKa7PQAMAboOmuh6bo8KquaVQnAZyZWZU08UduvlSV3tA7tw==",
"requires": {
"@sentry/hub": "5.19.0",
"@sentry/minimal": "5.19.0",
"@sentry/types": "5.19.0",
"@sentry/utils": "5.19.0",
"@sentry/hub": "5.19.2",
"@sentry/minimal": "5.19.2",
"@sentry/types": "5.19.2",
"@sentry/utils": "5.19.2",
"tslib": "^1.9.3"
}
},
"@sentry/hub": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.19.0.tgz",
"integrity": "sha512-UFaQLa1XAa02ZcxUmN9GdDpGs3vHK1LpOyYooimX8ttWa4KAkMuP+O5uXH1TJabry6o/cRwYisg2k6PBSy8gxw==",
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.19.2.tgz",
"integrity": "sha512-2KkEYX4q9TDCOiaVEo2kQ1W0IXyZxJxZtIjDdFQyes9T4ubYlKHAbvCjTxHSQv37lDO4t7sOIApWG9rlkHzlEA==",
"requires": {
"@sentry/types": "5.19.0",
"@sentry/utils": "5.19.0",
"@sentry/types": "5.19.2",
"@sentry/utils": "5.19.2",
"tslib": "^1.9.3"
}
},
"@sentry/minimal": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.19.0.tgz",
"integrity": "sha512-3FHgirwOuOMF4VlwHboYObPT9c0S9b9y5FW0DGgNt8sJPezS00VaJti/38ZwOHQJ4fJ6ubt/Y3Kz0eBTVxMCCQ==",
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.19.2.tgz",
"integrity": "sha512-rApEOkjy+ZmkeqEItgFvUFxe5l+dht9AumuUzq74pWp+HJqxxv9IVTusKppBsE1adjtmyhwK4O3Wr8qyc75xlw==",
"requires": {
"@sentry/hub": "5.19.0",
"@sentry/types": "5.19.0",
"@sentry/hub": "5.19.2",
"@sentry/types": "5.19.2",
"tslib": "^1.9.3"
}
},
"@sentry/node": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.19.0.tgz",
"integrity": "sha512-dqpH9ff+ropVpv0vJnNEOm601Gq/VFvdiN4Ge6JaKEVz+utx6JafEXjXsQqngxXp3xvJw6g0s6cw4HJ+Mx7dow==",
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.19.2.tgz",
"integrity": "sha512-gbww3iTWkdvYIAhOmULbv8znKwkIpklGJ0SPtAh0orUMuaa0lVht+6HQIhRgeXp50lMzNaYC3fuzkbFfYgpS7A==",
"requires": {
"@sentry/apm": "5.19.0",
"@sentry/core": "5.19.0",
"@sentry/hub": "5.19.0",
"@sentry/types": "5.19.0",
"@sentry/utils": "5.19.0",
"@sentry/apm": "5.19.2",
"@sentry/core": "5.19.2",
"@sentry/hub": "5.19.2",
"@sentry/types": "5.19.2",
"@sentry/utils": "5.19.2",
"cookie": "^0.3.1",
"https-proxy-agent": "^4.0.0",
"https-proxy-agent": "^5.0.0",
"lru_map": "^0.3.3",
"tslib": "^1.9.3"
},
"dependencies": {
"https-proxy-agent": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz",
"integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==",
"requires": {
"agent-base": "5",
"debug": "4"
}
}
}
},
"@sentry/types": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.19.0.tgz",
"integrity": "sha512-NlHLS9mwCEimKUA5vClAwVhXFLsqSF3VJEXU+K61fF6NZx8zfJi/HTrIBtoM4iNSAt9o4XLQatC1liIpBC06tg=="
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.19.2.tgz",
"integrity": "sha512-O6zkW8oM1qK5Uma9+B/UMlmlm9/gkw9MooqycWuEhIaKfDBj/yVbwb/UTiJmNkGc5VJQo0v1uXUZZQt6/Xq1GA=="
},
"@sentry/utils": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.19.0.tgz",
"integrity": "sha512-EU/T9aJrI8isexRnyDx5InNw/HjSQ0nKI7YWdiwfFrJusqQ/uisnCGK7vw6gGHDgiAHMXW3TJ38NHpNBin6y7Q==",
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.19.2.tgz",
"integrity": "sha512-gEPkC0CJwvIWqcTcPSdIzqJkJa9N5vZzUZyBvdu1oiyJu7MfazpJEvj3whfJMysSfXJQxoJ+a1IPrA73VY23VA==",
"requires": {
"@sentry/types": "5.19.0",
"@sentry/types": "5.19.2",
"tslib": "^1.9.3"
}
},
@@ -1307,11 +1341,6 @@
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true
},
"agent-base": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
"integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g=="
},
"ajv": {
"version": "6.12.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
@@ -2236,11 +2265,6 @@
}
}
},
"core-js-pure": {
"version": "3.6.5",
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz",
"integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA=="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -3578,9 +3602,9 @@
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
},
"inquirer": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.0.tgz",
"integrity": "sha512-K+LZp6L/6eE5swqIcVXrxl21aGDU4S50gKH0/d96OMQnSBCyGyZl/oZhbkVmdp5sBoINHd4xZvFSARh2dk6DWA==",
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.2.tgz",
"integrity": "sha512-DF4osh1FM6l0RJc5YWYhSDB6TawiBRlbV9Cox8MWlidU218Tb7fm3lQTULyUJDfJ0tjbzl0W4q651mrCCEM55w==",
"requires": {
"ansi-escapes": "^4.2.1",
"chalk": "^4.1.0",
@@ -3588,7 +3612,7 @@
"cli-width": "^3.0.0",
"external-editor": "^3.0.3",
"figures": "^3.0.0",
"lodash": "^4.17.15",
"lodash": "^4.17.16",
"mute-stream": "0.0.8",
"run-async": "^2.4.0",
"rxjs": "^6.6.0",
@@ -4113,9 +4137,9 @@
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
},
"lodash.find": {
"version": "4.6.0",
@@ -5643,7 +5667,8 @@
"regenerator-runtime": {
"version": "0.13.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
"dev": true
},
"regenerator-transform": {
"version": "0.14.5",
@@ -5914,9 +5939,9 @@
}
},
"rpki-validator": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/rpki-validator/-/rpki-validator-2.0.1.tgz",
"integrity": "sha512-fsXyImjaFf/4NXF70XWKxhbN9lv6Xf2dM2Q4P5Hqek3+e/7yCykrnRNDeqw7STr04udXVeSMHF2W/XIAoCrMYw==",
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/rpki-validator/-/rpki-validator-2.1.3.tgz",
"integrity": "sha512-WFZ+jb3Ep5ik15bG0olqg1eOKj8gT2pMl/OvHSirGi0EwNyzuCHM2cfnEihrUYvSr9FrN6e9/Z3ir5WlS6vsTw==",
"requires": {
"axios": "^0.19.2",
"brembo": "^2.0.4",
@@ -7173,14 +7198,6 @@
"integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
"dev": true
},
"xregexp": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz",
"integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==",
"requires": {
"@babel/runtime-corejs3": "^7.8.3"
}
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -7198,12 +7215,12 @@
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"yargs": {
"version": "15.4.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.0.tgz",
"integrity": "sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw==",
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"requires": {
"cliui": "^6.0.0",
"decamelize": "^3.2.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
@@ -7213,16 +7230,6 @@
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
},
"dependencies": {
"decamelize": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-3.2.0.tgz",
"integrity": "sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==",
"requires": {
"xregexp": "^4.2.4"
}
}
}
},
"yargs-parser": {

View File

@@ -13,6 +13,7 @@
"test": "rm -rf volumetests/ && ./node_modules/.bin/mocha --exit tests/*.js --require @babel/register && rm -rf volumetests/",
"test-reports": "./node_modules/.bin/mocha --exit tests/reports_tests/*.js --require @babel/register",
"test-proxy": "./node_modules/.bin/mocha --exit tests/proxy_tests/*.js --require @babel/register",
"test-rpki": "./node_modules/.bin/mocha --exit tests/rpki_tests/tests.default.js --require @babel/register && ./node_modules/.bin/mocha --exit tests/rpki_tests/tests.external.js --require @babel/register",
"build": "./build.sh",
"watch-and-serve": "nodemon -e yml,js,json,txt --inspect --exec babel-node index.js",
"serve": "babel-node index.js",
@@ -23,9 +24,9 @@
"author": "Massimo Candela",
"license": "BSD-3-Clause",
"devDependencies": {
"@babel/cli": "^7.10.4",
"@babel/core": "^7.10.4",
"@babel/node": "^7.10.4",
"@babel/cli": "^7.10.5",
"@babel/core": "^7.10.5",
"@babel/node": "^7.10.5",
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/plugin-proposal-object-rest-spread": "^7.10.4",
"@babel/preset-env": "^7.10.4",
@@ -38,12 +39,12 @@
"syslogd": "^1.1.2"
},
"dependencies": {
"@sentry/node": "^5.19.0",
"@sentry/node": "^5.19.2",
"axios": "^0.19.2",
"batch-promises": "^0.0.3",
"brembo": "^2.0.4",
"https-proxy-agent": "^5.0.0",
"inquirer": "^7.3.0",
"inquirer": "^7.3.2",
"ip-address": "^6.3.0",
"ip-sub": "^1.0.7",
"js-yaml": "^3.14.0",
@@ -51,11 +52,11 @@
"nodemailer": "^6.4.10",
"path": "^0.12.7",
"restify": "^8.5.1",
"rpki-validator": "^2.0.1",
"rpki-validator": "^2.1.3",
"semver": "^7.3.2",
"syslog-client": "^1.1.1",
"ws": "^7.3.1",
"yargs": "^15.4.0"
"yargs": "^15.4.1"
},
"pkg": {
"scripts": [

View File

@@ -116,6 +116,8 @@ let config = {
channel: "rpki",
name: "rpki-monitor",
params: {
preCacheROAs: true,
refreshVrpListMinutes: 15,
thresholdMinPeers: 1,
checkUncovered: false
}

View File

@@ -1,10 +1,17 @@
import Monitor from "./monitor";
import rpki from "rpki-validator";
import fs from "fs";
export default class MonitorRPKI extends Monitor {
constructor(name, channel, params, env){
super(name, channel, params, env);
this.providers = [ "ntt", "ripe", "external"]; // First provider is the default one
this.refreshVrpListMinutes = this.params.refreshVrpListMinutes || 15;
this.preCacheROAs = this.params.preCacheROAs !== false;
this.input.onChange(() => {
this.updateMonitoredResources();
});
@@ -13,24 +20,40 @@ export default class MonitorRPKI extends Monitor {
this.validationQueue = [];
const rpkiValidatorOptions = {
connector: this.params.vrpProvider || "ntt"
connector: this.providers[0],
clientId: env.clientId
};
if (this.params.vrpProvider) {
if (this.providers.includes(this.params.vrpProvider)) {
rpkiValidatorOptions.connector = this.params.vrpProvider;
} else {
this.logger.log({
level: 'error',
message: "The specified vrpProvider is not valid. Using default vrpProvider."
});
}
}
if (this.params.vrpFile) {
this._readExternalVrpsFile(env.config.volume + this.params.vrpFile, rpkiValidatorOptions);
}
if (!this.params.noProxy && env.agent) {
rpkiValidatorOptions.httpsAgent = env.agent;
}
this.rpki = new rpki(rpkiValidatorOptions);
if (this.params.preCacheROAs) {
this.rpki.preCache(Math.max(this.params.refreshVrpListMinutes, 15))
if (!!this.preCacheROAs) {
this.rpki.preCache(Math.max(this.refreshVrpListMinutes, 15))
.then(() => {
console.log("Downloaded");
setInterval(this.validateBatch, 100);
})
.catch(() => {
this.logger.log({
level: 'error',
message: "One of the VRPs lists cannot be downloaded. Anyway, the RPKI monitoring should be working."
message: "One of the VRPs lists cannot be downloaded. The RPKI monitoring should be able to work anyway."
});
});
} else {
@@ -38,11 +61,55 @@ export default class MonitorRPKI extends Monitor {
}
};
_readExternalVrpsFile = (file, rpkiValidatorOptions) => {
if (!!this.params.vrpProvider && this.params.vrpProvider !== "external") {
rpkiValidatorOptions.connector = this.providers[0];
delete rpkiValidatorOptions.vrps;
this.logger.log({
level: 'error',
message: "You cannot specify a vrpProvider different from 'external' if you want to use a vrps file. Using default vrpProvider."
});
} else {
if (fs.existsSync(file)) {
try {
const vrps = JSON.parse(fs.readFileSync(file));
if (vrps.length > 0) {
rpkiValidatorOptions.connector = "external";
rpkiValidatorOptions.vrps = vrps;
} else {
rpkiValidatorOptions.connector = this.providers[0];
delete rpkiValidatorOptions.vrps;
this.logger.log({
level: 'error',
message: "The provided VRPs file is empty. Using default vrpProvider."
});
}
} catch (error) {
rpkiValidatorOptions.connector = this.providers[0];
delete rpkiValidatorOptions.vrps;
this.logger.log({
level: 'error',
message: "The provided VRPs file cannot be parsed. Using default vrpProvider."
});
}
} else {
rpkiValidatorOptions.connector = this.providers[0];
delete rpkiValidatorOptions.vrps;
this.logger.log({
level: 'error',
message: "The provided VRPs file cannot be found. Using default vrpProvider."
});
}
}
};
updateMonitoredResources = () => {
this.monitored = this.input.getMonitoredASns();
};
validateBatch = () => {
this.validationQueue.forEach(this.validate);
this.validationQueue = [];
@@ -60,25 +127,23 @@ export default class MonitorRPKI extends Monitor {
const firstAlert = alerts[0];
const message = firstAlert.matchedMessage;
const extra = firstAlert.extra;
const covering = (extra.covering && extra.covering[0]) ? extra.covering[0] : false;
const coveringString = (covering) ? `Valid ROA: origin AS${covering.origin} prefix ${covering.prefix} max length ${covering.maxLength}` : '';
const covering = (extra.covering && extra.covering.length) ? extra.covering.map(i => `${i.prefix}|AS${i.asn}|maxLength:${i.maxLength}`).join(", ") : false;
const coveringString = (covering) ? `Valid ROAs: ${covering}`: '';
if (extra.valid === null && this.params.checkUncovered) {
return `The route ${message.prefix} announced by ${message.originAS} is not covered by a ROA. Accepted with AS path: ${message.path}`;
} else {
return `The route ${message.prefix} announced by ${message.originAS} is not RPKI valid. Accepted with AS path: ${message.path}. ${coveringString}`;
return `The route ${message.prefix} announced by ${message.originAS} is not RPKI valid. Accepted with AS path: ${message.path}. ${coveringString}`;
}
}
};
validate = ({ message, matchedRule} ) => {
const prefix = message.prefix;
const origin = message.originAS.getValue();
this.rpki.validate(prefix, origin, true)
this.rpki
.validate(prefix, origin.toString(), true)
.then(result => {
if (result) {
const key = "a" + [prefix, origin, result.valid]
@@ -117,13 +182,15 @@ export default class MonitorRPKI extends Monitor {
const messageOrigin = message.originAS;
const prefix = message.prefix;
const matchedASRule = this.getMonitoredAsMatch(messageOrigin);
const matchedPrefixRule = this.getMoreSpecificMatch(prefix, false);
if (matchedPrefixRule) {
this.validationQueue.push({ message, matchedRule: matchedPrefixRule });
} else if (matchedASRule) {
this.validationQueue.push({ message, matchedRule: matchedASRule });
} else {
const matchedASRule = this.getMonitoredAsMatch(messageOrigin);
if (matchedASRule) {
this.validationQueue.push({ message, matchedRule: matchedASRule });
}
}
return Promise.resolve(true);

View File

@@ -1 +0,0 @@
{"date":1593370465044,"value":{"alerts":{},"sent":{"a175_254_205_0_25-4321-":1593370435894,"a2a00_5884___32-15563-":1593370435894,"a2a00_5884___32-204092-":1593370435895,"a2a00_5884_ffff___48-208585-":1593370435895,"a175_254_205_0_25-1234-":1593370441912,"a2a00_5884___32-45-":1593370441912,"a2a00_5884_ffff___48-204092-":1593370441912,"a2a0e_240___32-1345-false":1593370441913,"a94_5_4_3_22-2914-false":1593370447966,"a98_5_4_3_22-2914-":1593370447967,"a99_5_4_3_22-2914-":1593370447967,"a2001_db8_123___48-65000-":1593370453985,"a2001_db8_123___49-65000-":1593370453985,"a2001_db9_123___49-2914-":1593370453985,"a2_2_2_3_22-2914-false":1593370453986,"a2_2_2_5_22-2914-false":1593370453986,"a2a0e_240___32-2914-false":1593370453986,"a103_21_244_0_24-13335-false":1593370460039,"a8_8_8_8_22-2914-":1593370460039},"truncated":{},"fadeOff":{}}}

View File

@@ -154,7 +154,6 @@ describe("Core functions", function() {
"params": {
"thresholdMinPeers": 1,
"preCacheROAs": false,
"refreshVrpListMinutes": 15,
"checkUncovered": true
}
});

View File

@@ -531,58 +531,6 @@ describe("Alerting", function () {
}).timeout(asyncTimeout);
it("RPKI monitoring", function (done) {
pubSub.publish("test-type", "rpki");
const expectedData = {
"a103_21_244_0_24-13335-false": {
id: "a103_21_244_0_24-13335-false",
origin: 'rpki-monitor',
affected: '103.21.244.0/24',
message: 'The route 103.21.244.0/24 announced by AS13335 is not RPKI valid. Accepted with AS path: [1,2,3,4321,13335]. Valid ROA: origin AS0 prefix 103.21.244.0/23 max length 23',
},
"a8_8_8_8_22-2914-": {
id: "a8_8_8_8_22-2914-",
origin: 'rpki-monitor',
affected: '8.8.8.8/22',
message: 'The route 8.8.8.8/22 announced by AS2914 is not covered by a ROA. Accepted with AS path: [1,2,3,4321,5060,2914]',
}
};
let rpkiTestCompleted = false;
pubSub.subscribe("rpki", function (type, message) {
if (!rpkiTestCompleted) {
message = JSON.parse(JSON.stringify(message));
const id = message.id;
expect(Object.keys(expectedData).includes(id)).to.equal(true);
expect(expectedData[id] != null).to.equal(true);
expect(message).to
.containSubset(expectedData[id]);
expect(message).to.contain
.keys([
"latest",
"earliest"
]);
delete expectedData[id];
if (Object.keys(expectedData).length === 0) {
setTimeout(() => {
rpkiTestCompleted = true;
done();
}, 5000);
}
}
});
}).timeout(asyncTimeout);
it("fading alerting", function (done) {
pubSub.publish("test-type", "fade-off");

View File

@@ -43,7 +43,6 @@ monitors:
params:
thresholdMinPeers: 1
preCacheROAs: false
refreshVrpListMinutes: 15
checkUncovered: true

View File

@@ -33,11 +33,10 @@
const chai = require("chai");
const chaiSubset = require('chai-subset');
const Syslogd = require("syslogd");
chai.use(chaiSubset);
const expect = chai.expect;
const volume = "volumetests/";
const asyncTimeout = 20000;
chai.use(chaiSubset);
global.EXTERNAL_VERSION_FOR_TEST = "0.0.1";
global.EXTERNAL_CONFIG_FILE = "tests/reports_tests/config.reports.test.yml";

View File

@@ -0,0 +1,43 @@
environment: test
connectors:
- file: connectorTest
name: tes
params:
testType: withdrawal
monitors:
- file: monitorRPKI
channel: rpki
name: rpki-monitor
params:
thresholdMinPeers: 1
preCacheROAs: true
refreshVrpListMinutes: 15
checkUncovered: true
# The file containing the monitored prefixes. Please see monitored_prefixes_test.yml for an example
# This is an array (use new lines and dashes!)
monitoredPrefixesFiles:
- tests/prefixes.test.yml
logging:
directory: logs
logRotatePattern: YYYY-MM-DD # Whenever the pattern changes, a new file is created and the old one rotated
backlogSize: 1
maxRetainedFiles: 10
maxFileSizeMB: 15
compressOnRotation: true
checkForUpdatesAtBoot: false
persistStatus: false
notificationIntervalSeconds: 1800 # Repeat the same alert (which keeps being triggered) after x seconds
alertOnlyOnce: false
fadeOffSeconds: 10
checkFadeOffGroupsSeconds: 2
pidFile: bgpalerter.pid
multiProcess: false
maxMessagesPerSecond: 6000

View File

@@ -0,0 +1,44 @@
environment: test
connectors:
- file: connectorTest
name: tes
params:
testType: withdrawal
monitors:
- file: monitorRPKI
channel: rpki
name: rpki-monitor
params:
thresholdMinPeers: 1
preCacheROAs: true
vrpFile: tests/rpki_tests/vrp.json
refreshVrpListMinutes: 15
checkUncovered: true
# The file containing the monitored prefixes. Please see monitored_prefixes_test.yml for an example
# This is an array (use new lines and dashes!)
monitoredPrefixesFiles:
- tests/prefixes.test.yml
logging:
directory: logs
logRotatePattern: YYYY-MM-DD # Whenever the pattern changes, a new file is created and the old one rotated
backlogSize: 1
maxRetainedFiles: 10
maxFileSizeMB: 15
compressOnRotation: true
checkForUpdatesAtBoot: false
persistStatus: false
notificationIntervalSeconds: 1800 # Repeat the same alert (which keeps being triggered) after x seconds
alertOnlyOnce: false
fadeOffSeconds: 10
checkFadeOffGroupsSeconds: 2
pidFile: bgpalerter.pid
multiProcess: false
maxMessagesPerSecond: 6000

View File

@@ -0,0 +1,98 @@
/*
* 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.
*/
const chai = require("chai");
const chaiSubset = require('chai-subset');
const expect = chai.expect;
const asyncTimeout = 200000;
chai.use(chaiSubset);
global.EXTERNAL_CONFIG_FILE = "tests/rpki_tests/config.rpki.test.default.yml";
const worker = require("../../index");
const pubSub = worker.pubSub;
describe("RPKI monitoring 1", function() {
it("default connector", function (done) {
const expectedData = {
"a103_21_244_0_24-13335-false": {
id: "a103_21_244_0_24-13335-false",
origin: 'rpki-monitor',
affected: '103.21.244.0/24',
message: 'The route 103.21.244.0/24 announced by AS13335 is not RPKI valid. Accepted with AS path: [1,2,3,4321,13335]. Valid ROAs: 103.21.244.0/23|AS0|maxLength:23',
},
"a8_8_8_8_22-2914-": {
id: "a8_8_8_8_22-2914-",
origin: 'rpki-monitor',
affected: '8.8.8.8/22',
message: 'The route 8.8.8.8/22 announced by AS2914 is not covered by a ROA. Accepted with AS path: [1,2,3,4321,5060,2914]',
}
};
let rpkiTestCompleted = false;
pubSub.subscribe("rpki", function (type, message) {
if (!rpkiTestCompleted) {
message = JSON.parse(JSON.stringify(message));
const id = message.id;
expect(Object.keys(expectedData).includes(id)).to.equal(true);
expect(expectedData[id] != null).to.equal(true);
expect(message).to
.containSubset(expectedData[id]);
expect(message).to.contain
.keys([
"latest",
"earliest"
]);
delete expectedData[id];
if (Object.keys(expectedData).length === 0) {
setTimeout(() => {
rpkiTestCompleted = true;
done();
}, 5000);
}
}
});
pubSub.publish("test-type", "rpki");
}).timeout(asyncTimeout);
});

View File

@@ -0,0 +1,90 @@
/*
* 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.
*/
const chai = require("chai");
const chaiSubset = require('chai-subset');
const expect = chai.expect;
const asyncTimeout = 200000;
chai.use(chaiSubset);
global.EXTERNAL_CONFIG_FILE = "tests/rpki_tests/config.rpki.test.external.yml";
const worker = require("../../index");
const pubSub = worker.pubSub;
describe("RPKI monitoring 2", function() {
it("external connector", function (done) {
const expectedData = {
"a82_112_100_0_24-2914-false" : {
id: 'a82_112_100_0_24-2914-false',
origin: 'rpki-monitor',
affected: '82.112.100.0/24',
message: 'The route 82.112.100.0/24 announced by AS2914 is not RPKI valid. Accepted with AS path: [1,2,3,4321,2914]. Valid ROAs: 82.112.100.0/24|AS1234|maxLength:24'
}
};
let rpkiTestCompletedExternal = false;
pubSub.subscribe("rpki", function (type, message) {
if (!rpkiTestCompletedExternal) {
message = JSON.parse(JSON.stringify(message));
const id = message.id;
expect(Object.keys(expectedData).includes(id)).to.equal(true);
expect(expectedData[id] != null).to.equal(true);
expect(message).to
.containSubset(expectedData[id]);
expect(message).to.contain
.keys([
"latest",
"earliest"
]);
delete expectedData[id];
if (Object.keys(expectedData).length === 0) {
setTimeout(() => {
rpkiTestCompletedExternal = true;
done();
}, 5000);
}
}
});
pubSub.publish("test-type", "rpki");
}).timeout(asyncTimeout);
});

17
tests/rpki_tests/vrp.json Normal file
View File

@@ -0,0 +1,17 @@
[
{
"asn": "13335",
"prefix": "103.21.244.0/24",
"maxLength": 24
},
{
"asn": "AS2914",
"prefix": "8.8.8.0/22",
"maxLength": 24
},
{
"asn": 1234,
"prefix": "82.112.100.0/24",
"maxLength": 24
}
]