Last active
August 29, 2015 14:11
-
-
Save sstelfox/0e9fc22b32af26e22fa1 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| #!/usr/bin/env ruby | |
| require 'csv' | |
| require 'liquid' | |
| require 'ostruct' | |
| module Engine | |
| def self.compound(name = nil, &blk) | |
| rule_list.push(CompoundRule.new(name, &blk)) | |
| end | |
| def self.evaluate_obj(obj) | |
| rule_list.each { |r| r.evaluate_obj(obj) } | |
| end | |
| def self.rule(name = nil, &blk) | |
| rule_list.push(StandardRule.new(name = nil, &blk)) | |
| end | |
| def self.rule_list | |
| @rule_list ||= [] | |
| end | |
| end | |
| module ShortcutMatches | |
| def offline | |
| match { status == "offline" } | |
| end | |
| def online | |
| match { status == "online" } | |
| end | |
| end | |
| module RuleCommons | |
| def alert(msg) | |
| @alert_msg = msg | |
| end | |
| def print_alert(obj) | |
| string_keyed_obj = Hash[obj.to_h.map { |k, v| [k.to_s, v] }] | |
| puts Liquid::Template.parse(@alert_msg).render(string_keyed_obj) | |
| end | |
| end | |
| class CompoundRule | |
| include RuleCommons | |
| def evaluate_obj(obj) | |
| return false unless @enabled | |
| if @matcher.call(@rules.map { |r| r.evaluate_obj(obj) }) | |
| print_alert(obj) if @alert_msg | |
| end | |
| end | |
| def disable | |
| @enabled = false | |
| end | |
| def initialize(name = nil, &blk) | |
| @enabled = true | |
| @name = name | |
| @rules = [] | |
| instance_eval(&blk) if block_given? | |
| end | |
| def rule(&blk) | |
| @rules.push(StandardRule.new(&blk)) | |
| end | |
| def true_if(&blk) | |
| @matcher = blk | |
| end | |
| end | |
| class StandardRule | |
| include ShortcutMatches | |
| include RuleCommons | |
| def disable | |
| @enabled = false | |
| end | |
| def evaluate_obj(obj) | |
| return false unless @enabled | |
| @matches.each do |m| | |
| # Break out of our rule checking as soon as one fails | |
| return false unless (obj.instance_eval(&m) rescue false) | |
| end | |
| # All rules passed | |
| print_alert(obj) if @alert_msg | |
| true | |
| end | |
| def initialize(name = nil, &blk) | |
| @enabled = true | |
| @name = name | |
| @matches = [] | |
| instance_eval(&blk) if block_given? | |
| end | |
| def match(&blk) | |
| @matches.push(blk) | |
| end | |
| end | |
| Engine.rule do | |
| online | |
| match { protocol == 'tcp' && port == '22' } | |
| alert "Detected an SSH server on a network host (ID: {{ id }})" | |
| end | |
| Engine.evaluate_obj(OpenStruct.new(sensor: '1', protocol: 'tcp', port: '22', status: 'offline', id: '12')) | |
| Engine.evaluate_obj(OpenStruct.new(sensor: '2', protocol: 'tcp', port: '22', status: 'online', id: '5')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment