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

monitor supports alerts grouping

This commit is contained in:
Massimo Candela
2019-06-26 23:24:55 +02:00
parent 557e59e850
commit bd3dfaeb53
12 changed files with 4169 additions and 138 deletions

View File

@@ -6,7 +6,11 @@ const configFile = yaml.safeLoad(fs.readFileSync('./config.yml', 'utf8'));
const config = {
monitors: [
MonitorHijack
{
class: MonitorHijack,
channel: "hijack",
name: "basic-hijack-detection"
}
]
};

View File

@@ -1,6 +1,10 @@
# Please, rename this file to config.yml
testMode: true
testMode: true,
checkStaleNotificationsSeconds: 60;
notificationIntervalSeconds: 60 * 20;
clearNotificationQueueAfterSeconds: 60 * 30; # If nothing happened in the meanwhile
bufferSize: 10,
@@ -24,7 +28,7 @@ notifiedEmails:
# 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:
- monitored_prefixes.base.yml
- prefixes.yml
# After how many announcements from different peers we trigger an alter?
numberPeersBeforeHijackAlert: 0

View File

@@ -1,9 +1,9 @@
import config from "./config";
export default class Consumer {
constructor(){
constructor(inputManager){
process.on('message', this.dispatch);
this.monitors = config.monitors.map(monitor => new monitor());
this.monitors = config.monitors.map(monitor => new monitor.class(inputManager, monitor.channel, monitor.name));
};
dispatch = (data) => {
@@ -19,9 +19,18 @@ export default class Consumer {
handleUpdate = (data) => {
const messages = this.transform(data);
for (let monitor of this.monitors){
for (const message of messages){
monitor.monitor(message);
for (let monitor of this.monitors) {
// Blocking filtering to reduce stack usage
for (const message of messages.filter(monitor.filter)) {
// Promise call to reduce waiting times
monitor.monitor(message)
.catch(error => {
// Log error properly
console.log(error);
});
}
}
};
@@ -44,6 +53,7 @@ export default class Consumer {
prefix,
peer,
path,
originAs: path[path.length - 1],
nextHop
})
}

View File

@@ -1,10 +0,0 @@
import WebSocket from "ws";
export default class Dispatcher{
constructor(){
}
}

View File

@@ -4,6 +4,10 @@ import cluster from "cluster";
import WebSocket from "ws";
import sleep from "sleep";
import Consumer from "./consumer";
import InputManager from "./inputManager";
const inputManager = new InputManager(config);
if (cluster.isMaster) {
@@ -11,13 +15,27 @@ if (cluster.isMaster) {
if (config.testMode){
const message = JSON.stringify({
// const update = {
// data: {
// withdrawals: ["124.40.52.0/22"],
// peer: "124.0.0.2"
// },
// type: "ris_message"
// };
const update = {
data: {
withdrawals: ["123.0.0.1/23"],
peer: "124.0.0.2"
announcements: [{
prefixes: ["124.40.52.0/22"],
next_hop: "124.0.0.2"
}],
peer: "124.0.0.2",
path: "1,2,3,2914".split(",")
},
type: "ris_message"
});
};
const message = JSON.stringify(update);
while (true){
worker.send(message);
@@ -44,5 +62,5 @@ if (cluster.isMaster) {
}
} else {
new Consumer()
new Consumer(inputManager)
}

53
inputManager.js Normal file
View File

@@ -0,0 +1,53 @@
import yaml from "js-yaml";
import fs from "fs";
import ip from "ip";
export default class InputManager {
constructor(config){
this.prefixes = [];
if (!config.monitoredPrefixesFiles || config.monitoredPrefixesFiles.length === 0){
throw new Error("The monitoredPrefixesFiles key is missing in the confiug file");
}
for (let prefixesFile of config.monitoredPrefixesFiles){
const monitoredPrefixesFile = yaml.safeLoad(fs.readFileSync('./' + prefixesFile, 'utf8'));
const monitoredPrefixes = Object.keys(monitoredPrefixesFile)
.map(i => Object.assign(monitoredPrefixesFile[i], { prefix: i }));
this.prefixes = this.prefixes.concat(monitoredPrefixes);
}
};
getMonitoredMoreSpecifics = () => {
return this.prefixes.filter(p => !p.ignoreMorespecifics);
};
getMonitoredMoreSpecificsBest = () => {
const prefixes = this.getMonitoredMoreSpecifics();
const length = prefixes.length;
let contained = false;
const out = [];
for (let n=0; n<length; n++) {
for (let h=0; h<length; h++) {
if (!contained) {
contained = ip.cidrSubnet(prefixes[h]).contains(prefixes[n]);
}
}
if (contained) {
out.push(prefixes);
}
}
};
getMonitoredPrefixes = () => {
return this.prefixes;
};
}

View File

@@ -1,13 +1,123 @@
import PubSub from 'pubsub-js';
import config from "../config";
export default class Monitor {
constructor(name, channel){
constructor(inputManager, name, channel){
this.input = inputManager;
this.name = name;
this.channel = channel;
this.monitored = [];
this.alerts = {};
this.sent = {};
this.updateMonitoredPrefixes();
setTimeout(this._publish, config.checkStaleNotificationsSeconds)
};
monitor = (message) => {
throw Error("You must implement a monitor method");
updateMonitoredPrefixes = () => {
this.monitored = this.input.getMonitoredPrefixes();
};
monitor = (message) =>
new Promise((resolve, reject) => {
reject("You must implement a monitor method");
});
filter = (message) => {
throw new Error('The method filter must be implemented in ' + this.name);
};
squashAlerts = (alerts) => {
throw new Error('The method squashAlerts must be implemented in ' + this.name);
};
_squash = (alerts) => {
const firstAlert = alerts[0];
const id = firstAlert.id;
let earliest = Infinity;
let latest = -Infinity;
for (let alert of alerts){
earliest = Math.max(alert.timestamp, earliest);
latest = Math.max(alert.timestamp, latest);
if (id !== alert.id) {
throw new Error('Squash MUST receive a list of events all with the same ID.');
}
}
return {
id,
origin: this.name,
earliest,
latest,
affected: firstAlert.affected,
message: this.squashAlerts(alerts),
data: alerts.map(a => a.data)
}
};
publishAlert = (eventId, message, affected, data) => {
const context = {
eventId,
timestamp: new Date(),
message,
affected,
data
};
if (!this.alerts[id]) {
this.alerts[id] = [];
}
this.alerts[id].push(context);
};
_clean = (group) => {
if (new Date().getTime() > group.latest + (config.clearNotificationQueueAfterSeconds * 1000)) {
delete this.alerts[group.id];
return true;
}
return false;
};
_checkLastSent = (group) => {
const lastTimeSent = this.sent[group.id];
const isThereSomethingNew = lastTimeSent < group.latest;
const isItTimeToSend = new Date().getTime() > lastTimeSent + (config.notificationIntervalSeconds * 1000);
return isThereSomethingNew && isItTimeToSend;
};
_publish = () => {
for (let id of this.alerts) {
const group = this._squash(this.alerts[id]);
if (this._checkLastSent(group)) {
this._publishOnChannel(group);
}
this._clean(group);
}
};
_publishOnChannel = (alert) => {
PubSub.publish(this.channel, alert);
return alert;
}
}

View File

@@ -1,16 +1,41 @@
import Monitor from "./monitor";
import ip from "ip";
export default class MonitorHijack extends Monitor {
constructor(name, channel){
super(name, channel);
constructor(inputManager, name, channel){
super(inputManager, name, channel);
};
updateMonitoredPrefixes = () => {
this.monitored = this.input.getMonitoredMoreSpecifics();
};
filter = (message) => {
return message.type === 'announcement';
};
squashAlerts = (alerts) => {
return alerts[0].message;
};
monitor = (message) => {
console.log(message);
const messagePrefix = message.prefix;
for (let item of this.monitored) {
const prefix = item.prefix;
if (prefix === messagePrefix) {
if (message.originAs !== item.asn) {
this.publishAlert(`The prefix ${prefix} is announced by the AS${message.originAs}
instead of AS${item.asn}`,);
}
} else if (ip.cidrSubnet(prefix).contains(messagePrefix)) {
}
}
};
}

3779
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,11 @@
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.7.0",
"event-stream": "^4.0.1",
"ip": "^1.1.5",
"ip-address": "^5.9.2",
"ip2buf": "^2.0.0",
"js-yaml": "^3.13.1",
"pubsub-js": "^1.7.0",
"sleep": "^6.1.0",
"websocket-stream": "^5.5.0",
"ws": "^7.0.0",

View File

@@ -1,37 +1,37 @@
27.114.0.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
58.88.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
60.32.0.0/12:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.112.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.113.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.118.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.119.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.120.144.0/20:
description: subas 64600
@@ -40,12 +40,12 @@
61.126.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.199.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.200.80.0/20:
description: subas 64600
@@ -54,12 +54,12 @@
61.207.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.208.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
61.213.144.0/20:
description: subas 64600
@@ -88,12 +88,12 @@
114.144.0.0/12:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
114.160.0.0/11:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
117.103.176.0/20:
description: subas 64600
@@ -110,12 +110,12 @@
118.0.0.0/12:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
118.16.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
120.29.144.0/21:
description: subas 64600
@@ -128,37 +128,37 @@
121.112.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
122.1.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
122.16.0.0/12:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
123.216.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
123.224.0.0/14:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
124.40.0.0/18:
description: subas 64600
asn: 2914
ignore_morespecifics: False
ignoreMorespecifics: False
124.40.32.0/19:
description: iboss
asn: 137922
ignore_morespecifics: True
ignoreMorespecifics: True
124.40.56.0/24:
description: capitalonline
@@ -171,27 +171,27 @@
124.84.0.0/14:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
124.96.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
125.170.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
125.172.0.0/14:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
125.200.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
130.94.19.0/24:
description: subas 65061
@@ -208,32 +208,32 @@
153.176.0.0/12:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
153.192.0.0/11:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
153.224.0.0/12:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
153.240.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
153.248.0.0/14:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
153.252.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
153.254.0.0/15:
description: subas 64600
@@ -242,37 +242,37 @@
180.0.0.0/10:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.12.169.0/24:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.12.168.0/24:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.12.170.0/24:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.12.171.0/24:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.12.172.0/24:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.12.173.0/24:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.210.232.0/24:
description: subas 64600
@@ -293,7 +293,7 @@
202.234.192.0/18:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
203.105.64.0/19:
description: subas 64600
@@ -302,17 +302,17 @@
203.139.160.0/19:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
203.140.96.0/20:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
203.140.112.0/20:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
203.205.112.0/20:
description: subas 64600
@@ -353,47 +353,47 @@
210.132.0.0/18:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.145.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.154.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.160.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.161.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.162.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.163.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.164.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.170.64.0/18:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.175.160.0/19:
description: subas 64600
@@ -402,57 +402,57 @@
210.190.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.225.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.226.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.232.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.248.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
210.254.128.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
211.0.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
211.6.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
211.11.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
211.16.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
211.122.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
211.129.0.0/16:
description: OCN
@@ -461,7 +461,7 @@
211.130.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
211.130.96.0/19:
description: subas 64600
@@ -474,204 +474,204 @@
218.43.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
218.44.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
218.47.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
218.224.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
218.230.128.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
219.96.128.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
219.114.0.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
219.160.0.0/14:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
219.164.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
219.166.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.96.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.98.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.99.0.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.99.128.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.104.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.106.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.108.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.110.0.0/16:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.111.0.0/19:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.111.32.0/20:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.111.48.0/20:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.111.64.0/18:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.111.128.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.220.0.0/15:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
221.113.128.0/17:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
221.184.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
222.144.0.0/13:
description: OCN
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
223.216.0.0/14:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
114.163.192.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
124.85.96.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.0.248.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.13.216.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.22.248.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.3.96.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.39.216.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.50.120.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.57.120.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
180.57.128.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
219.162.32.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
220.96.8.0/21:
description: OCN prefix
asn: 4713
ignore_morespecifics: False
ignoreMorespecifics: False
124.40.52.128/26:
description: Solid Trading / Crossivity
asn: 50601
ignore_morespecifics: False
ignoreMorespecifics: False

View File

@@ -1473,6 +1473,25 @@ invariant@^2.2.2:
dependencies:
loose-envify "^1.0.0"
ip-address@^5.9.2:
version "5.9.2"
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-5.9.2.tgz#8e7d2dab5cbf3cbf34e1f730ec6913f55fec8c74"
integrity sha512-7aeFm/7oqo0mMhubTSjZ2Juw/F+WJ3hyfCScNVRQdz5RSRhw1Rj4ZlBFsmEajeKgQDI8asqVs31h8DpxEv7IfQ==
dependencies:
jsbn "1.1.0"
lodash "^4.17.11"
sprintf-js "1.1.2"
ip2buf@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ip2buf/-/ip2buf-2.0.0.tgz#289b94a8cc107be6a2fa9624e236b46c9ae6bd66"
integrity sha512-ezW62UW6IPwpuS3mpsvOS3/3Jgx7aaNZT+uJo/+xVBxHCq7EA1ryuhzZw2MyC5GuGd1sAp3RDx7e4+nJCGt9vA==
ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
is-accessor-descriptor@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
@@ -1733,6 +1752,11 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
jsbn@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040"
integrity sha1-sBMHyym2GKHtJux56RH4A8TaAEA=
jsesc@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
@@ -1784,7 +1808,7 @@ latest-version@^3.0.0:
dependencies:
package-json "^4.0.0"
lodash@^4.17.4:
lodash@^4.17.11, lodash@^4.17.4:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
@@ -2225,6 +2249,11 @@ pstree.remy@^1.1.6:
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.7.tgz#c76963a28047ed61542dc361aa26ee55a7fa15f3"
integrity sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==
pubsub-js@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/pubsub-js/-/pubsub-js-1.7.0.tgz#eca97f9a4217bef62b2d3aaa1552005260cc2e49"
integrity sha512-Pb68P9qFZxnvDipHMuj9oT1FoIgBcXJ9C9eWdHCLZAnulaUoJ3+Y87RhGMYilWpun6DMWVmvK70T4RP4drZMSA==
randomatic@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
@@ -2540,6 +2569,11 @@ split@^1.0.1:
dependencies:
through "2"
sprintf-js@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"