threatinator 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +23 -0
  3. data/CONTRIBUTING.md +119 -0
  4. data/Gemfile +28 -0
  5. data/LICENSE +165 -0
  6. data/README.md +45 -0
  7. data/Rakefile +45 -0
  8. data/VERSION +1 -0
  9. data/bin/threatinator +5 -0
  10. data/lib/threatinator.rb +3 -0
  11. data/lib/threatinator/action.rb +14 -0
  12. data/lib/threatinator/actions/list.rb +2 -0
  13. data/lib/threatinator/actions/list/action.rb +53 -0
  14. data/lib/threatinator/actions/list/config.rb +10 -0
  15. data/lib/threatinator/actions/run.rb +2 -0
  16. data/lib/threatinator/actions/run/action.rb +45 -0
  17. data/lib/threatinator/actions/run/config.rb +32 -0
  18. data/lib/threatinator/actions/run/coverage_observer.rb +54 -0
  19. data/lib/threatinator/actions/run/output_config.rb +59 -0
  20. data/lib/threatinator/cli.rb +13 -0
  21. data/lib/threatinator/cli/action_builder.rb +33 -0
  22. data/lib/threatinator/cli/list_action_builder.rb +19 -0
  23. data/lib/threatinator/cli/parser.rb +113 -0
  24. data/lib/threatinator/cli/run_action_builder.rb +41 -0
  25. data/lib/threatinator/config.rb +6 -0
  26. data/lib/threatinator/config/base.rb +35 -0
  27. data/lib/threatinator/config/feed_search.rb +25 -0
  28. data/lib/threatinator/decoder.rb +24 -0
  29. data/lib/threatinator/decoders/gzip.rb +30 -0
  30. data/lib/threatinator/event.rb +27 -0
  31. data/lib/threatinator/event_builder.rb +41 -0
  32. data/lib/threatinator/exceptions.rb +61 -0
  33. data/lib/threatinator/feed.rb +82 -0
  34. data/lib/threatinator/feed_builder.rb +156 -0
  35. data/lib/threatinator/feed_registry.rb +47 -0
  36. data/lib/threatinator/feed_runner.rb +118 -0
  37. data/lib/threatinator/fetcher.rb +22 -0
  38. data/lib/threatinator/fetchers/http.rb +46 -0
  39. data/lib/threatinator/filter.rb +12 -0
  40. data/lib/threatinator/filters/block.rb +18 -0
  41. data/lib/threatinator/filters/comments.rb +16 -0
  42. data/lib/threatinator/filters/whitespace.rb +19 -0
  43. data/lib/threatinator/output.rb +50 -0
  44. data/lib/threatinator/parser.rb +23 -0
  45. data/lib/threatinator/parsers/csv.rb +7 -0
  46. data/lib/threatinator/parsers/csv/parser.rb +77 -0
  47. data/lib/threatinator/parsers/getline.rb +8 -0
  48. data/lib/threatinator/parsers/getline/parser.rb +45 -0
  49. data/lib/threatinator/parsers/json.rb +8 -0
  50. data/lib/threatinator/parsers/json/adapters/oj.rb +65 -0
  51. data/lib/threatinator/parsers/json/parser.rb +45 -0
  52. data/lib/threatinator/parsers/json/record.rb +20 -0
  53. data/lib/threatinator/parsers/xml.rb +8 -0
  54. data/lib/threatinator/parsers/xml/node.rb +79 -0
  55. data/lib/threatinator/parsers/xml/node_builder.rb +39 -0
  56. data/lib/threatinator/parsers/xml/parser.rb +44 -0
  57. data/lib/threatinator/parsers/xml/path.rb +70 -0
  58. data/lib/threatinator/parsers/xml/pattern.rb +53 -0
  59. data/lib/threatinator/parsers/xml/record.rb +14 -0
  60. data/lib/threatinator/parsers/xml/sax_document.rb +64 -0
  61. data/lib/threatinator/plugin_loader.rb +115 -0
  62. data/lib/threatinator/plugins/output/csv.rb +47 -0
  63. data/lib/threatinator/plugins/output/null.rb +17 -0
  64. data/lib/threatinator/plugins/output/rubydebug.rb +16 -0
  65. data/lib/threatinator/property_definer.rb +101 -0
  66. data/lib/threatinator/record.rb +22 -0
  67. data/lib/threatinator/registry.rb +53 -0
  68. data/lib/threatinator/util.rb +15 -0
  69. data/spec/feeds/ET_compromised-ip_reputation_spec.rb +50 -0
  70. data/spec/feeds/alienvault-ip_reputation_spec.rb +50 -0
  71. data/spec/feeds/arbor_fastflux-domain_reputation_spec.rb +50 -0
  72. data/spec/feeds/arbor_ssh-ip_reputation_spec.rb +50 -0
  73. data/spec/feeds/autoshun_shunlist_spec.rb +42 -0
  74. data/spec/feeds/blocklist_de_apache-ip_reputation_spec.rb +50 -0
  75. data/spec/feeds/blocklist_de_bots-ip_reputation_spec.rb +50 -0
  76. data/spec/feeds/blocklist_de_ftp-ip_reputation_spec.rb +50 -0
  77. data/spec/feeds/blocklist_de_imap-ip_reputation_spec.rb +50 -0
  78. data/spec/feeds/blocklist_de_pop3-ip_reputation_spec.rb +50 -0
  79. data/spec/feeds/blocklist_de_proftpd-ip_reputation_spec.rb +50 -0
  80. data/spec/feeds/blocklist_de_sip-ip_reputation_spec.rb +50 -0
  81. data/spec/feeds/blocklist_de_ssh-ip_reputation_spec.rb +50 -0
  82. data/spec/feeds/blocklist_de_strongips-ip_reputation_spec.rb +50 -0
  83. data/spec/feeds/ciarmy-ip_reputation_spec.rb +50 -0
  84. data/spec/feeds/cruzit-ip_reputation_spec.rb +50 -0
  85. data/spec/feeds/dan_me_uk_torlist-ip_reputation_spec.rb +50 -0
  86. data/spec/feeds/data/ET_compromised-ip_reputation.txt +11 -0
  87. data/spec/feeds/data/alienvault-ip_reputation.txt +18 -0
  88. data/spec/feeds/data/arbor_domainlist.txt +11 -0
  89. data/spec/feeds/data/arbor_ssh.txt +16 -0
  90. data/spec/feeds/data/autoshun_shunlist.csv +20 -0
  91. data/spec/feeds/data/blocklist_de_apache-ip-reputation.txt +17 -0
  92. data/spec/feeds/data/blocklist_de_bots-ip-reputation.txt +15 -0
  93. data/spec/feeds/data/blocklist_de_ftp-ip-reputation.txt +7 -0
  94. data/spec/feeds/data/blocklist_de_imap-ip-reputation.txt +8 -0
  95. data/spec/feeds/data/blocklist_de_pop3-ip-reputation.txt +11 -0
  96. data/spec/feeds/data/blocklist_de_proftpd-ip-reputation.txt +12 -0
  97. data/spec/feeds/data/blocklist_de_sip-ip-reputation.txt +9 -0
  98. data/spec/feeds/data/blocklist_de_ssh-ip-reputation.txt +10 -0
  99. data/spec/feeds/data/blocklist_de_strongips-ip-reputation.txt +11 -0
  100. data/spec/feeds/data/ciarmy-ip-reputation.txt +11 -0
  101. data/spec/feeds/data/cruzit-ip-reputation.txt +14 -0
  102. data/spec/feeds/data/dan_me_uk_torlist-ip-reputation.txt +11 -0
  103. data/spec/feeds/data/dshield_topattackers.xml +4 -0
  104. data/spec/feeds/data/feodo_domainlist.txt +18 -0
  105. data/spec/feeds/data/feodo_iplist.txt +20 -0
  106. data/spec/feeds/data/infiltrated_iplist.txt +16 -0
  107. data/spec/feeds/data/malc0de_domainlist.txt +18 -0
  108. data/spec/feeds/data/malc0de_iplist.txt +14 -0
  109. data/spec/feeds/data/mirc_domainlist.txt +31 -0
  110. data/spec/feeds/data/nothink_irc_iplist.txt +14 -0
  111. data/spec/feeds/data/nothink_ssh_iplist.txt +10 -0
  112. data/spec/feeds/data/openbl_iplist.txt +12 -0
  113. data/spec/feeds/data/palevo_domainlist.txt +25 -0
  114. data/spec/feeds/data/palevo_iplist.txt +24 -0
  115. data/spec/feeds/data/phishtank-sample.json.gz +0 -0
  116. data/spec/feeds/data/spyeye_domainlist.txt +16 -0
  117. data/spec/feeds/data/spyeye_iplist.txt +19 -0
  118. data/spec/feeds/data/t-arend-de_ssh_iplist.txt +17 -0
  119. data/spec/feeds/data/the_haleys_ssh_iplist.txt +12 -0
  120. data/spec/feeds/data/yourcmc_ssh-ip_reputation.txt +27 -0
  121. data/spec/feeds/data/zeus-ip_reputation.txt +285 -0
  122. data/spec/feeds/data/zeus_domainlist.txt +27 -0
  123. data/spec/feeds/dshield_attackers-top1000_spec.rb +43 -0
  124. data/spec/feeds/feodo-domain_reputation_spec.rb +50 -0
  125. data/spec/feeds/feodo-ip_reputation_spec.rb +50 -0
  126. data/spec/feeds/infiltrated-ip_reputation_spec.rb +50 -0
  127. data/spec/feeds/malc0de-domain_reputation_spec.rb +50 -0
  128. data/spec/feeds/malc0de-ip_reputation_spec.rb +50 -0
  129. data/spec/feeds/mirc-domain_reputation_spec.rb +50 -0
  130. data/spec/feeds/nothink_irc-ip_reputation_spec.rb +50 -0
  131. data/spec/feeds/nothink_ssh-ip_reputation_spec.rb +50 -0
  132. data/spec/feeds/openbl-ip_reputation_spec.rb +50 -0
  133. data/spec/feeds/palevo-domain_reputation_spec.rb +50 -0
  134. data/spec/feeds/palevo-ip_reputation_spec.rb +50 -0
  135. data/spec/feeds/phishtank_spec.rb +45 -0
  136. data/spec/feeds/spyeye-domain_reputation_spec.rb +50 -0
  137. data/spec/feeds/spyeye-ip_reputation_spec.rb +50 -0
  138. data/spec/feeds/t-arend-de_ssh-ip_reputation_spec.rb +50 -0
  139. data/spec/feeds/the_haleys_ssh-ip_reputation_spec.rb +50 -0
  140. data/spec/feeds/yourcmc_ssh-ip_reputation_spec.rb +50 -0
  141. data/spec/feeds/zeus-domain_reputation_spec.rb +50 -0
  142. data/spec/feeds/zeus-ip_reputation_spec.rb +50 -0
  143. data/spec/fixtures/feed/provider1/feed1.feed +6 -0
  144. data/spec/fixtures/parsers/test.xml +13 -0
  145. data/spec/fixtures/parsers/test_self_closing.xml +20 -0
  146. data/spec/fixtures/plugins/bad/threatinator/plugins/test_error1/plugin.rb +1 -0
  147. data/spec/fixtures/plugins/bad/threatinator/plugins/test_missing1/plugin.rb +0 -0
  148. data/spec/fixtures/plugins/fake.rb +19 -0
  149. data/spec/fixtures/plugins/good/threatinator/plugins/test_type1/plugin_a.rb +8 -0
  150. data/spec/fixtures/plugins/good/threatinator/plugins/test_type1/plugin_b.rb +8 -0
  151. data/spec/fixtures/plugins/good/threatinator/plugins/test_type2/plugin_c.rb +8 -0
  152. data/spec/fixtures/plugins/good/threatinator/plugins/test_type2/plugin_d.rb +8 -0
  153. data/spec/fixtures/plugins/good/threatinator/plugins/test_type3/plugin_e.rb +8 -0
  154. data/spec/fixtures/plugins/good/threatinator/plugins/test_type3/plugin_f.rb +8 -0
  155. data/spec/spec_helper.rb +52 -0
  156. data/spec/support/bad_feeds/missing_fetcher.feed +7 -0
  157. data/spec/support/bad_feeds/missing_name.feed +6 -0
  158. data/spec/support/bad_feeds/missing_parser.feed +3 -0
  159. data/spec/support/bad_feeds/missing_provider.feed +5 -0
  160. data/spec/support/factories/event.rb +27 -0
  161. data/spec/support/factories/feed.rb +32 -0
  162. data/spec/support/factories/feed_builder.rb +65 -0
  163. data/spec/support/factories/feed_registry.rb +8 -0
  164. data/spec/support/factories/output.rb +11 -0
  165. data/spec/support/factories/record.rb +17 -0
  166. data/spec/support/factories/xml_node.rb +33 -0
  167. data/spec/support/helpers/io.rb +11 -0
  168. data/spec/support/helpers/models.rb +13 -0
  169. data/spec/support/shared/action_builder.rb +47 -0
  170. data/spec/support/shared/decoder.rb +70 -0
  171. data/spec/support/shared/feeds.rb +218 -0
  172. data/spec/support/shared/fetcher.rb +48 -0
  173. data/spec/support/shared/filter.rb +14 -0
  174. data/spec/support/shared/io-like.rb +7 -0
  175. data/spec/support/shared/output.rb +120 -0
  176. data/spec/support/shared/parsers.rb +51 -0
  177. data/spec/support/shared/record.rb +111 -0
  178. data/spec/threatinator/actions/list/action_spec.rb +93 -0
  179. data/spec/threatinator/actions/run/action_spec.rb +89 -0
  180. data/spec/threatinator/actions/run/config_spec.rb +39 -0
  181. data/spec/threatinator/actions/run/coverage_observer_spec.rb +116 -0
  182. data/spec/threatinator/actions/run/output_config_spec.rb +89 -0
  183. data/spec/threatinator/cli/list_action_builder_spec.rb +57 -0
  184. data/spec/threatinator/cli/run_action_builder_spec.rb +133 -0
  185. data/spec/threatinator/cli_spec.rb +175 -0
  186. data/spec/threatinator/config/base_spec.rb +39 -0
  187. data/spec/threatinator/config/feed_search_spec.rb +76 -0
  188. data/spec/threatinator/decoders/gzip_spec.rb +75 -0
  189. data/spec/threatinator/event_builder_spec.rb +33 -0
  190. data/spec/threatinator/event_spec.rb +30 -0
  191. data/spec/threatinator/feed_builder_spec.rb +636 -0
  192. data/spec/threatinator/feed_registry_spec.rb +198 -0
  193. data/spec/threatinator/feed_runner_spec.rb +155 -0
  194. data/spec/threatinator/feed_spec.rb +169 -0
  195. data/spec/threatinator/fetcher_spec.rb +12 -0
  196. data/spec/threatinator/fetchers/http_spec.rb +32 -0
  197. data/spec/threatinator/filter_spec.rb +13 -0
  198. data/spec/threatinator/filters/block_spec.rb +16 -0
  199. data/spec/threatinator/filters/comments_spec.rb +13 -0
  200. data/spec/threatinator/filters/whitespace_spec.rb +12 -0
  201. data/spec/threatinator/parser_spec.rb +13 -0
  202. data/spec/threatinator/parsers/csv/parser_spec.rb +202 -0
  203. data/spec/threatinator/parsers/getline/parser_spec.rb +83 -0
  204. data/spec/threatinator/parsers/json/parser_spec.rb +106 -0
  205. data/spec/threatinator/parsers/json/record_spec.rb +30 -0
  206. data/spec/threatinator/parsers/xml/node_spec.rb +335 -0
  207. data/spec/threatinator/parsers/xml/parser_spec.rb +263 -0
  208. data/spec/threatinator/parsers/xml/path_spec.rb +209 -0
  209. data/spec/threatinator/parsers/xml/pattern_spec.rb +72 -0
  210. data/spec/threatinator/parsers/xml/record_spec.rb +27 -0
  211. data/spec/threatinator/plugin_loader_spec.rb +238 -0
  212. data/spec/threatinator/plugins/output/csv_spec.rb +46 -0
  213. data/spec/threatinator/plugins/output/null_spec.rb +17 -0
  214. data/spec/threatinator/plugins/output/rubydebug_spec.rb +37 -0
  215. data/spec/threatinator/property_definer_spec.rb +155 -0
  216. data/spec/threatinator/record_spec.rb +19 -0
  217. data/spec/threatinator/registry_spec.rb +97 -0
  218. data/spec/threatinator/runner_spec.rb +273 -0
  219. metadata +376 -0
@@ -0,0 +1,53 @@
1
+ require 'threatinator/parsers/xml/path'
2
+
3
+ module Threatinator
4
+ module Parsers
5
+ module XML
6
+ # Implements path matching behavior for use with the XML parser. Aims to support
7
+ # a small subset of XPath behaviors, specifically for matching elements.
8
+ class Pattern
9
+ # @param [String] pathspec A specification of a path match.
10
+ def initialize(pathspec)
11
+ parts = pathspec.split('/')
12
+ leader_count = 0
13
+ while parts[0] == ''
14
+ leader_count += 1
15
+ parts.shift
16
+ end
17
+ @path = Threatinator::Parsers::XML::Path.new(parts)
18
+ @anchored = true
19
+
20
+ if leader_count == 1
21
+ @anchored = true
22
+ elsif leader_count == 2
23
+ @anchored = false
24
+ else
25
+ raise ArgumentError.new('pathspec must begin with "/" or "//"')
26
+ end
27
+ end
28
+
29
+ def max_depth
30
+ @anchored == true ? @path.length : Float::INFINITY
31
+ end
32
+
33
+ # @param [Threatinator::Parsers::XML::Path] path
34
+ # @return [Boolean] true if the pattern matches, false otherwise.
35
+ def match?(path)
36
+ if @anchored == true
37
+ @path == path
38
+ else
39
+ path.end_with?(@path)
40
+ end
41
+ end
42
+
43
+ def _internal_data
44
+ [@path, @anchored]
45
+ end
46
+
47
+ def ==(other)
48
+ _internal_data == other._internal_data
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,14 @@
1
+ require 'threatinator/record'
2
+
3
+ module Threatinator
4
+ module Parsers
5
+ module XML
6
+ class Record < Threatinator::Record
7
+ alias_method :node, :data
8
+ def initialize(node, opts = {})
9
+ super(node, opts)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,64 @@
1
+ require 'threatinator/parsers/xml/node_builder'
2
+ require 'threatinator/parsers/xml/path'
3
+ require 'nokogiri'
4
+
5
+ module Threatinator
6
+ module Parsers
7
+ module XML
8
+ class SAXDocument < Nokogiri::XML::SAX::Document
9
+ def initialize(pattern, cb)
10
+ @pattern = pattern
11
+ @max_depth = @pattern.max_depth
12
+ @cb = cb
13
+ @element_stack = Threatinator::Parsers::XML::Path.new
14
+ @parsing_stack = []
15
+ @current_node = nil
16
+ super()
17
+ end
18
+
19
+ def start_parsing(name, attributes)
20
+ @current_node = Threatinator::Parsers::XML::NodeBuilder.new(name, attributes)
21
+ @parsing_stack.push(@current_node)
22
+ end
23
+
24
+ def characters(str)
25
+ return if @current_node.nil?
26
+ @current_node.append_text(str)
27
+ end
28
+
29
+ alias_method :cdata_block, :characters
30
+
31
+ def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = [])
32
+ @element_stack.push(name)
33
+
34
+ if @parsing_stack.empty?
35
+ if @element_stack.length > @max_depth
36
+ return
37
+ end
38
+
39
+ if @pattern.match?(@element_stack)
40
+ start_parsing(name, attrs)
41
+ end
42
+ else
43
+ start_parsing(name, attrs)
44
+ end
45
+ end
46
+
47
+ def end_element_namespace(name, prefix = nil, uri = nil)
48
+ name_sym = name.to_sym
49
+ @element_stack.pop
50
+ return if @parsing_stack.empty?
51
+ @parsing_stack.pop
52
+
53
+ if parent = @parsing_stack.last
54
+ parent.add_child(@current_node.build)
55
+ @current_node = parent
56
+ else
57
+ @cb.call(@current_node.build)
58
+ @current_node = nil
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,115 @@
1
+ require 'rubygems'
2
+ require 'threatinator/util'
3
+ require 'threatinator/registry'
4
+
5
+ module Threatinator
6
+ class PluginLoader
7
+ def initialize()
8
+ @plugin_types_registry = Threatinator::Registry.new
9
+ end
10
+
11
+ # Loads all plugins
12
+ # @return [Threatinator::PluginLoader] self
13
+ def load_all_plugins()
14
+ load_plugins(:*)
15
+ return self
16
+ end
17
+
18
+ # Loads all plugins of the specified type
19
+ # @param [#to_sym] type
20
+ # @return [Threatinator::PluginLoader] self
21
+ def load_plugins(type)
22
+ load_files(find_plugin_files(type.to_sym))
23
+ return self
24
+ end
25
+
26
+ # Retrieves a loaded plugin by type and name.
27
+ # @param [#to_sym] type
28
+ # @param [#to_sym] name
29
+ # @return [Object] plugin
30
+ def get(type, name)
31
+ type_registry = @plugin_types_registry.get(type.to_sym)
32
+ return nil if type_registry.nil?
33
+ return type_registry.get(name.to_sym)
34
+ end
35
+
36
+ # Enumerates through all plugins, optionally filtered by type.
37
+ # @yield [type, name, plugin]
38
+ # @yieldparam [Symbol] type
39
+ # @yieldparam [Symbol] name
40
+ # @yieldparam [Object] plugin
41
+ def each(type = nil)
42
+ return enum_for(:each, type) unless block_given?
43
+ @plugin_types_registry.each do |t, type_registry|
44
+ unless type.nil?
45
+ next unless type.to_sym == t
46
+ end
47
+ type_registry.each do |name, plugin|
48
+ yield(t, name, plugin)
49
+ end
50
+ end
51
+ end
52
+
53
+ # Returns an array of all the types of plugins that are loaded.
54
+ # @return [Array<Symbol>]
55
+ def types
56
+ @plugin_types_registry.keys
57
+ end
58
+
59
+ # Registers a plugin with the provided type and name.
60
+ # @param [#to_sym] type
61
+ # @param [#to_sym] name
62
+ # @param [Object] plugin
63
+ # @raise [Threatinator::Exceptions::AlreadyRegisteredError
64
+ def register_plugin(type, name, plugin)
65
+ type = type.to_sym
66
+ unless type_registry = @plugin_types_registry.get(type)
67
+ type_registry = @plugin_types_registry.register(type, Threatinator::Registry.new)
68
+ end
69
+ type_registry.register(name.to_sym, plugin)
70
+ end
71
+
72
+ private
73
+
74
+ def find_plugin_files(type)
75
+ Gem.find_files("threatinator/plugins/#{type}/*.rb")
76
+ end
77
+
78
+ def register_plugin_by_name(type, name)
79
+ plugin_name = "Threatinator::Plugins::#{Threatinator::Util.underscore2cc(type)}::#{Threatinator::Util.underscore2cc(name)}"
80
+ begin
81
+ type_obj = Threatinator::Plugins.const_get(Threatinator::Util.underscore2cc(type))
82
+ plugin = type_obj.const_get(Threatinator::Util.underscore2cc(name))
83
+ register_plugin(type, name, plugin)
84
+ rescue ::NameError => e
85
+ raise Threatinator::Exceptions::PluginLoadError.new("Failed to load plugin '#{plugin_name}'", e)
86
+ end
87
+ end
88
+
89
+ def load_files(file_names)
90
+ file_names.each do |file_name|
91
+ path, type, name = split_file_name(file_name)
92
+ next if path.nil?
93
+ # Don't try to load unit tests as plugins :)
94
+ next if name.end_with?("_spec")
95
+ begin
96
+ require path
97
+ rescue ::LoadError
98
+ # TODO: Handle plugins inside of gems a bit better. We should try
99
+ # using only the latest version of a given Gem.
100
+ next
101
+ end
102
+
103
+ register_plugin_by_name(type, name)
104
+ end
105
+ end
106
+
107
+ # @return [Array, nil] an array containing the path, type, and name of the
108
+ # plugin
109
+ def split_file_name(file_name)
110
+ m = file_name.match(/(?<=(\A|\/))(?<path>threatinator\/plugins\/(?<type>[^\/]+)\/(?<name>[^\/\.]+))\.rb$/)
111
+ return nil if m.nil?
112
+ [m[:path], m[:type], m[:name]]
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,47 @@
1
+ require 'threatinator/output'
2
+ require 'csv'
3
+ module Threatinator
4
+ module Plugins
5
+ module Output
6
+ class Csv < Threatinator::FileBasedOutput
7
+ class Config < superclass::Config
8
+ end
9
+
10
+ def initialize(config)
11
+ super(config)
12
+ @csv = ::CSV.new(self.output_io,
13
+ :write_headers => true,
14
+ :headers => [
15
+ :provider,
16
+ :feed_name,
17
+ :type,
18
+ :ipv4_1,
19
+ :ipv4_2,
20
+ :ipv4_3,
21
+ :ipv4_4,
22
+ :fqdn_1,
23
+ :fqdn_2,
24
+ :fqdn_3,
25
+ :fqdn_4
26
+ ])
27
+ end
28
+
29
+ def handle_event(event)
30
+ @csv.add_row([
31
+ event.feed_provider,
32
+ event.feed_name,
33
+ event.type,
34
+ event.ipv4s[0],
35
+ event.ipv4s[1],
36
+ event.ipv4s[2],
37
+ event.ipv4s[3],
38
+ event.fqdns[0],
39
+ event.fqdns[1],
40
+ event.fqdns[2],
41
+ event.fqdns[3]
42
+ ])
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ require 'threatinator/output'
2
+ module Threatinator
3
+ module Plugins
4
+ module Output
5
+ class Null < Threatinator::Output
6
+ class Config < superclass::Config
7
+ end
8
+
9
+ def handle_event(event)
10
+ end
11
+
12
+ def finish
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ require 'threatinator/output'
2
+ require 'pp'
3
+ module Threatinator
4
+ module Plugins
5
+ module Output
6
+ class Rubydebug < Threatinator::FileBasedOutput
7
+ class Config < superclass::Config
8
+ end
9
+
10
+ def handle_event(event)
11
+ ::PP.pp(event, self.output_io); nil
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,101 @@
1
+
2
+ module Threatinator
3
+ # A helper that lets us easily define properties within an object and
4
+ # validate them.
5
+ module PropertyDefiner
6
+ def self.included(base)
7
+ base.extend(Threatinator::PropertyDefiner::ClassMethods)
8
+ end
9
+
10
+ def _properties
11
+ @_properties ||= Hash.new
12
+ end
13
+
14
+ def _prop(name)
15
+ self.class._properties[name]
16
+ end
17
+
18
+ def _get(name)
19
+ if _properties.has_key?(name)
20
+ return _properties[name]
21
+ end
22
+ prop = _prop(name)
23
+ return nil if prop.nil?
24
+ val = prop.default_value
25
+ _set(name, val)
26
+ val
27
+ end
28
+
29
+ def _set(name, val)
30
+ prop = _prop(name)
31
+ return if prop.nil?
32
+ prop.validate!(self, val)
33
+ _properties[name] = val
34
+ end
35
+
36
+ def _parse_properties(opts = {})
37
+ opts.each { |k, v| _set(k, v) }
38
+ end
39
+
40
+ class Property
41
+ attr_reader :name, :opts
42
+ def initialize(name, opts = {})
43
+ @name = name.to_sym
44
+ @type = opts.delete(:type) || Object
45
+ if @validator = opts.delete(:validate)
46
+ unless @validator.kind_of?(Proc)
47
+ raise ArgumentError.new(":validate must be a proc")
48
+ end
49
+ end
50
+ @default_value = opts.delete(:default)
51
+ @opts = opts
52
+ end
53
+
54
+ def default_value
55
+ case @default_value
56
+ when Proc
57
+ return @default_value.call()
58
+ when nil
59
+ return nil
60
+ else
61
+ return @default_value
62
+ end
63
+ end
64
+
65
+ def valid?(obj, val)
66
+ return false unless val.kind_of?(@type)
67
+ unless @validator.nil?
68
+ return false unless @validator.call(obj, val)
69
+ end
70
+ true
71
+ end
72
+
73
+ def validate!(obj, val)
74
+ unless valid?(obj, val)
75
+ raise Threatinator::Exceptions::InvalidAttributeError.new(self.name, val)
76
+ end
77
+ end
78
+ end
79
+
80
+ module ClassMethods
81
+ def _properties
82
+ @@properties ||= {}
83
+ end
84
+
85
+ def _define_property(prop)
86
+ name = prop.name
87
+ _properties[name] = prop
88
+ define_method("#{prop.name}=".to_sym) do |newval|
89
+ _set(name, newval)
90
+ end
91
+ define_method(name) do
92
+ _get(name)
93
+ end
94
+ end
95
+
96
+ def property(name, opts = {})
97
+ _define_property(Property.new(name, opts))
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,22 @@
1
+ module Threatinator
2
+ class Record
3
+ attr_reader :data, :line_number, :pos_start, :pos_end
4
+ def initialize(data, opts = {})
5
+ @data = data
6
+ @line_number = opts[:line_number]
7
+ @pos_start = opts[:pos_start]
8
+ @pos_end = opts[:pos_end]
9
+ end
10
+
11
+ def ==(other)
12
+ @data == other.data &&
13
+ @line_number == other.line_number &&
14
+ @pos_start == other.pos_start &&
15
+ @pos_end == other.pos_end
16
+ end
17
+
18
+ def eql?(other)
19
+ other.kind_of?(self.class) && self == other
20
+ end
21
+ end
22
+ end