Last active
August 5, 2019 22:26
-
-
Save Enteee/2679f6e7130946db9c54caff0d5eb294 to your computer and use it in GitHub Desktop.
FluentFlow Example: If you see within 2 seconds two invalid login attemps followed by a successful login from the same source, then alert.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ff = require('fluentflow') | |
const $ = ff.RuleBuilder; | |
const _ = require('lodash'); | |
const moment = require('moment') | |
/** | |
* Not interesting if older than 2 seconds | |
*/ | |
function isInteresting(c, pc){ | |
return moment.duration( | |
moment(c.moment).diff( | |
moment(pc.get('moment')) | |
) | |
).seconds() < 2; | |
} | |
/** | |
* If you see within 2 seconds two invalid login attemps followed by a successful login from the same source, then alert. | |
*/ | |
const ffm = ff.Matcher( | |
$( | |
// not successful login | |
(o, p, c, pc, match) => { | |
c.moment = moment().format(); | |
return match(!o.get('success')) | |
} | |
).followedBy( | |
// not successful login | |
(o, p, c, pc, match, forget) => { | |
c.moment = moment().format(); | |
if (!isInteresting(c, pc)){ | |
console.log('Forget', p.toJS()); | |
return forget(); | |
} | |
return match( | |
o.get('source') == p.get(0).get('source') && !o.get('success') | |
); | |
} | |
).followedBy( | |
// successful login | |
(o, p, c, pc, match, forget) => { | |
c.moment = moment().format(); | |
if (!isInteresting(c, pc)){ | |
console.log('Forget', p.toJS()); | |
return forget(); | |
} | |
return match( | |
o.get('source') == p.get(0).get('source') && o.get('success') | |
); | |
} | |
).then( | |
(objs, next) => next(console.log('ALERT!', objs.toJS())) | |
) | |
); | |
// generate and match new random events | |
id = 0; | |
setInterval( | |
() => { | |
const loginEvent = { | |
id: id++, | |
source: _.sample([ | |
'User1', 'User2', 'User3' | |
]), | |
success: _.sample([true, false]) | |
}; | |
console.log('Event', loginEvent) | |
ffm(loginEvent) | |
}, | |
100 | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ node events.js | |
Event { id: 0, source: 'User2', success: false } | |
Event { id: 1, source: 'User3', success: false } | |
Event { id: 2, source: 'User1', success: false } | |
Event { id: 3, source: 'User1', success: true } | |
Event { id: 4, source: 'User2', success: true } | |
Event { id: 5, source: 'User2', success: true } | |
Event { id: 6, source: 'User1', success: false } | |
Event { id: 7, source: 'User2', success: true } | |
Event { id: 8, source: 'User2', success: true } | |
Event { id: 9, source: 'User2', success: true } | |
Event { id: 10, source: 'User3', success: true } | |
Event { id: 11, source: 'User2', success: false } | |
Event { id: 12, source: 'User2', success: true } | |
ALERT! [ { id: 12, source: 'User2', success: true }, | |
{ id: 11, source: 'User2', success: false }, | |
{ id: 0, source: 'User2', success: false } ] | |
Event { id: 13, source: 'User2', success: true } | |
ALERT! [ { id: 13, source: 'User2', success: true }, | |
{ id: 11, source: 'User2', success: false }, | |
{ id: 0, source: 'User2', success: false } ] | |
Event { id: 14, source: 'User1', success: true } | |
ALERT! [ { id: 14, source: 'User1', success: true }, | |
{ id: 6, source: 'User1', success: false }, | |
{ id: 2, source: 'User1', success: false } ] | |
Event { id: 15, source: 'User1', success: false } | |
Event { id: 16, source: 'User2', success: true } | |
ALERT! [ { id: 16, source: 'User2', success: true }, | |
{ id: 11, source: 'User2', success: false }, | |
{ id: 0, source: 'User2', success: false } ] | |
Event { id: 17, source: 'User2', success: false } | |
Forget [ { id: 0, source: 'User2', success: false } ] | |
Forget [ { id: 1, source: 'User3', success: false } ] | |
Forget [ { id: 2, source: 'User1', success: false } ] | |
Forget [ { id: 6, source: 'User1', success: false } ] | |
Forget [ { id: 6, source: 'User1', success: false }, | |
{ id: 2, source: 'User1', success: false } ] | |
Event { id: 18, source: 'User2', success: false } | |
Event { id: 19, source: 'User1', success: false } | |
Event { id: 20, source: 'User1', success: false } | |
Event { id: 21, source: 'User2', success: false } | |
Event { id: 22, source: 'User1', success: true } | |
Event { id: 23, source: 'User1', success: false } | |
Event { id: 24, source: 'User3', success: false } | |
Event { id: 25, source: 'User2', success: true } | |
Event { id: 26, source: 'User2', success: false } | |
Event { id: 27, source: 'User2', success: true } | |
Event { id: 28, source: 'User1', success: true } | |
Event { id: 29, source: 'User3', success: true } | |
Event { id: 30, source: 'User3', success: false } | |
Event { id: 31, source: 'User3', success: true } | |
Event { id: 32, source: 'User2', success: true } | |
Event { id: 33, source: 'User2', success: true } | |
Event { id: 34, source: 'User1', success: true } | |
Event { id: 35, source: 'User1', success: true } | |
Event { id: 36, source: 'User1', success: true } | |
Event { id: 37, source: 'User3', success: true } | |
^C |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment