shadowbq-threatinator 0.5.0

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 (389) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +66 -0
  3. data/CONTRIBUTING.md +119 -0
  4. data/Gemfile +38 -0
  5. data/LICENSE +165 -0
  6. data/README.md +101 -0
  7. data/Rakefile +47 -0
  8. data/VERSION +1 -0
  9. data/bin/threatinator +5 -0
  10. data/bin/threatinator_loader +21 -0
  11. data/feeds/ET_block-ip_reputation.feed +27 -0
  12. data/feeds/ET_compromised-ip_reputation.feed +20 -0
  13. data/feeds/ET_openbadlist-ip_reputation.feed +36 -0
  14. data/feeds/alienvault-ip_reputation.feed +39 -0
  15. data/feeds/arbor_fastflux-domain_reputation.feed +19 -0
  16. data/feeds/arbor_ssh-ip_reputation.feed +24 -0
  17. data/feeds/autoshun_shunlist.feed +17 -0
  18. data/feeds/bambenek_c2_masterlist-domain_reputation.feed +16 -0
  19. data/feeds/bambenek_c2_masterlist-ip_reputation.feed +16 -0
  20. data/feeds/bambenek_dga_feed-domain_reputation.feed +16 -0
  21. data/feeds/berkeley-ip_reputation.feed +25 -0
  22. data/feeds/bitcash_cz_blacklist.feed +22 -0
  23. data/feeds/blocklist_de_apache-ip_reputation.feed +26 -0
  24. data/feeds/blocklist_de_bots-ip_reputation.feed +26 -0
  25. data/feeds/blocklist_de_ftp-ip_reputation.feed +25 -0
  26. data/feeds/blocklist_de_imap-ip_reputation.feed +25 -0
  27. data/feeds/blocklist_de_pop3-ip_reputation.feed +26 -0
  28. data/feeds/blocklist_de_proftpd-ip_reputation.feed +26 -0
  29. data/feeds/blocklist_de_sip-ip_reputation.feed +25 -0
  30. data/feeds/blocklist_de_ssh-ip_reputation.feed +25 -0
  31. data/feeds/blocklist_de_strongips-ip_reputation.feed +25 -0
  32. data/feeds/botscout-ip_reputation.feed +25 -0
  33. data/feeds/cert_mxpoison-ip_reputation.feed +22 -0
  34. data/feeds/chaosreigns-ip_reputation.feed +37 -0
  35. data/feeds/ciarmy-ip_reputation.feed +20 -0
  36. data/feeds/cruzit-ip_reputation.feed +30 -0
  37. data/feeds/cydef_torexit-ip_reputation.feed +25 -0
  38. data/feeds/dan_me_uk_torlist-ip_reputation.feed +25 -0
  39. data/feeds/danger_bruteforce-ip_reputation.feed +24 -0
  40. data/feeds/dshield_attackers-top1000.feed +34 -0
  41. data/feeds/falconcrest-ip_reputation.feed +19 -0
  42. data/feeds/feodo-domain_reputation.feed +19 -0
  43. data/feeds/feodo-ip_reputation.feed +20 -0
  44. data/feeds/h3x_asprox.feed +18 -0
  45. data/feeds/hosts-file_hphostspartial-domain_reputation.feed +19 -0
  46. data/feeds/infiltrated-ip_reputation.feed +26 -0
  47. data/feeds/infiltrated_vabl-ip_reputation.feed +30 -0
  48. data/feeds/isc_suspicious_high-domain_reputation.feed +26 -0
  49. data/feeds/isc_suspicious_low-domain_reputation.feed +26 -0
  50. data/feeds/isc_suspicious_medium-domain_reputation.feed +26 -0
  51. data/feeds/malc0de-domain_reputation.feed +24 -0
  52. data/feeds/malc0de-ip_reputation.feed +26 -0
  53. data/feeds/malwaredomainlist-url_reputation.feed +18 -0
  54. data/feeds/malwaredomains-domain_reputation.feed +29 -0
  55. data/feeds/malwaredomains_dyndns-domain_reputation.feed +29 -0
  56. data/feeds/malwaredomains_justdomains-domain_reputation.feed +20 -0
  57. data/feeds/mirc-domain_reputation.feed +30 -0
  58. data/feeds/multiproxy-ip_reputation.feed +22 -0
  59. data/feeds/nothink_irc-ip_reputation.feed +23 -0
  60. data/feeds/nothink_ssh-ip_reputation.feed +21 -0
  61. data/feeds/openbl-ip_reputation.feed +21 -0
  62. data/feeds/openphish-url_reputation.feed +24 -0
  63. data/feeds/packetmail_perimeterbad-ip_reputation.feed +28 -0
  64. data/feeds/palevo-domain_reputation.feed +22 -0
  65. data/feeds/palevo-ip_reputation.feed +23 -0
  66. data/feeds/phishtank.feed +22 -0
  67. data/feeds/sigmaproject_atma.feed +27 -0
  68. data/feeds/sigmaproject_spyware.feed +28 -0
  69. data/feeds/sigmaproject_webexploit.feed +26 -0
  70. data/feeds/snort_bpf-ip_reputation.feed +19 -0
  71. data/feeds/spyeye-domain_reputation.feed +18 -0
  72. data/feeds/spyeye-ip_reputation.feed +19 -0
  73. data/feeds/steeman-ip_reputation.feed +20 -0
  74. data/feeds/t-arend-de_ssh-ip_reputation.feed +20 -0
  75. data/feeds/the_haleys_ssh-ip_reputation.feed +20 -0
  76. data/feeds/trustedsec-ip_reputation.feed +18 -0
  77. data/feeds/virbl-ip_reputation.feed +25 -0
  78. data/feeds/vxvault-url_reputation.feed +23 -0
  79. data/feeds/yourcmc_ssh-ip_reputation.feed +20 -0
  80. data/feeds/yoyo_adservers-domain_reputation.feed +17 -0
  81. data/feeds/zeus-domain_reputation.feed +19 -0
  82. data/feeds/zeus-ip_reputation.feed +21 -0
  83. data/lib/threatinator/action.rb +14 -0
  84. data/lib/threatinator/actions/list/action.rb +97 -0
  85. data/lib/threatinator/actions/list/config.rb +12 -0
  86. data/lib/threatinator/actions/list.rb +2 -0
  87. data/lib/threatinator/actions/run/action.rb +57 -0
  88. data/lib/threatinator/actions/run/config.rb +32 -0
  89. data/lib/threatinator/actions/run/coverage_observer.rb +59 -0
  90. data/lib/threatinator/actions/run/output_config.rb +59 -0
  91. data/lib/threatinator/actions/run/status_observer.rb +37 -0
  92. data/lib/threatinator/actions/run.rb +2 -0
  93. data/lib/threatinator/cli/action_builder.rb +33 -0
  94. data/lib/threatinator/cli/list_action_builder.rb +19 -0
  95. data/lib/threatinator/cli/parser.rb +123 -0
  96. data/lib/threatinator/cli/run_action_builder.rb +41 -0
  97. data/lib/threatinator/cli.rb +19 -0
  98. data/lib/threatinator/config/base.rb +35 -0
  99. data/lib/threatinator/config/feed_search.rb +25 -0
  100. data/lib/threatinator/config/logger.rb +14 -0
  101. data/lib/threatinator/config.rb +7 -0
  102. data/lib/threatinator/decoder.rb +24 -0
  103. data/lib/threatinator/decoders/gzip.rb +30 -0
  104. data/lib/threatinator/event.rb +63 -0
  105. data/lib/threatinator/event_builder.rb +70 -0
  106. data/lib/threatinator/exceptions.rb +58 -0
  107. data/lib/threatinator/feed.rb +88 -0
  108. data/lib/threatinator/feed_builder.rb +161 -0
  109. data/lib/threatinator/feed_registry.rb +47 -0
  110. data/lib/threatinator/feed_runner.rb +177 -0
  111. data/lib/threatinator/fetcher.rb +22 -0
  112. data/lib/threatinator/fetchers/http.rb +50 -0
  113. data/lib/threatinator/filter.rb +12 -0
  114. data/lib/threatinator/filters/block.rb +18 -0
  115. data/lib/threatinator/filters/comments.rb +16 -0
  116. data/lib/threatinator/filters/whitespace.rb +19 -0
  117. data/lib/threatinator/logger.rb +66 -0
  118. data/lib/threatinator/logging.rb +20 -0
  119. data/lib/threatinator/model/base.rb +23 -0
  120. data/lib/threatinator/model/collection.rb +89 -0
  121. data/lib/threatinator/model/observables/fqdn_collection.rb +15 -0
  122. data/lib/threatinator/model/observables/ipv4.rb +33 -0
  123. data/lib/threatinator/model/observables/ipv4_collection.rb +14 -0
  124. data/lib/threatinator/model/observables/url_collection.rb +16 -0
  125. data/lib/threatinator/model/validations/type.rb +21 -0
  126. data/lib/threatinator/model/validations.rb +1 -0
  127. data/lib/threatinator/output.rb +50 -0
  128. data/lib/threatinator/parser.rb +23 -0
  129. data/lib/threatinator/parsers/csv/parser.rb +77 -0
  130. data/lib/threatinator/parsers/csv.rb +7 -0
  131. data/lib/threatinator/parsers/getline/parser.rb +45 -0
  132. data/lib/threatinator/parsers/getline.rb +8 -0
  133. data/lib/threatinator/parsers/json/adapters/oj.rb +65 -0
  134. data/lib/threatinator/parsers/json/parser.rb +45 -0
  135. data/lib/threatinator/parsers/json/record.rb +20 -0
  136. data/lib/threatinator/parsers/json.rb +8 -0
  137. data/lib/threatinator/parsers/xml/node.rb +79 -0
  138. data/lib/threatinator/parsers/xml/node_builder.rb +39 -0
  139. data/lib/threatinator/parsers/xml/parser.rb +44 -0
  140. data/lib/threatinator/parsers/xml/path.rb +70 -0
  141. data/lib/threatinator/parsers/xml/pattern.rb +53 -0
  142. data/lib/threatinator/parsers/xml/record.rb +14 -0
  143. data/lib/threatinator/parsers/xml/sax_document.rb +64 -0
  144. data/lib/threatinator/parsers/xml.rb +8 -0
  145. data/lib/threatinator/plugin_loader.rb +115 -0
  146. data/lib/threatinator/plugins/output/amqp/config.rb +18 -0
  147. data/lib/threatinator/plugins/output/amqp.rb +41 -0
  148. data/lib/threatinator/plugins/output/csv.rb +58 -0
  149. data/lib/threatinator/plugins/output/json/config.rb +14 -0
  150. data/lib/threatinator/plugins/output/json.rb +53 -0
  151. data/lib/threatinator/plugins/output/null.rb +17 -0
  152. data/lib/threatinator/plugins/output/rubydebug.rb +16 -0
  153. data/lib/threatinator/record.rb +22 -0
  154. data/lib/threatinator/registry.rb +53 -0
  155. data/lib/threatinator/util.rb +15 -0
  156. data/lib/threatinator.rb +3 -0
  157. data/spec/feeds/ET_block-ip_reputation_spec.rb +50 -0
  158. data/spec/feeds/ET_compromised-ip_reputation_spec.rb +47 -0
  159. data/spec/feeds/ET_openbadlist-ip_reputation_spec.rb +56 -0
  160. data/spec/feeds/alienvault-ip_reputation_spec.rb +46 -0
  161. data/spec/feeds/arbor_fastflux-domain_reputation_spec.rb +46 -0
  162. data/spec/feeds/arbor_ssh-ip_reputation_spec.rb +46 -0
  163. data/spec/feeds/autoshun_shunlist_spec.rb +38 -0
  164. data/spec/feeds/bambenek_c2_masterlist-domain_reputation_spec.rb +38 -0
  165. data/spec/feeds/bambenek_c2_masterlist-ip_reputation_spec.rb +39 -0
  166. data/spec/feeds/bambenek_dga_feed-domain_reputation_spec.rb +39 -0
  167. data/spec/feeds/berkeley-ip_reputation_spec.rb +47 -0
  168. data/spec/feeds/bitcash_cz_blacklist-ip_reputation_spec.rb +50 -0
  169. data/spec/feeds/blocklist_de_apache-ip_reputation_spec.rb +47 -0
  170. data/spec/feeds/blocklist_de_bots-ip_reputation_spec.rb +47 -0
  171. data/spec/feeds/blocklist_de_ftp-ip_reputation_spec.rb +47 -0
  172. data/spec/feeds/blocklist_de_imap-ip_reputation_spec.rb +47 -0
  173. data/spec/feeds/blocklist_de_pop3-ip_reputation_spec.rb +47 -0
  174. data/spec/feeds/blocklist_de_proftpd-ip_reputation_spec.rb +47 -0
  175. data/spec/feeds/blocklist_de_sip-ip_reputation_spec.rb +47 -0
  176. data/spec/feeds/blocklist_de_ssh-ip_reputation_spec.rb +47 -0
  177. data/spec/feeds/blocklist_de_strongips-ip_reputation_spec.rb +47 -0
  178. data/spec/feeds/botscout-ip_reputation_spec.rb +50 -0
  179. data/spec/feeds/cert_mxpoison-ip_reputation_spec.rb +47 -0
  180. data/spec/feeds/chaosreigns-ip_reputation_spec.rb +50 -0
  181. data/spec/feeds/ciarmy-ip_reputation_spec.rb +47 -0
  182. data/spec/feeds/cruzit-ip_reputation_spec.rb +47 -0
  183. data/spec/feeds/cydef_torexit-ip_reputation_spec.rb +47 -0
  184. data/spec/feeds/dan_me_uk_torlist-ip_reputation_spec.rb +47 -0
  185. data/spec/feeds/danger_bruteforce-ip_reputation_spec.rb +47 -0
  186. data/spec/feeds/data/ET_block-ip_reputation.txt +80 -0
  187. data/spec/feeds/data/ET_compromised-ip_reputation.txt +11 -0
  188. data/spec/feeds/data/ET_openbadlist-ip_reputation.txt +62 -0
  189. data/spec/feeds/data/alienvault-ip_reputation.txt +18 -0
  190. data/spec/feeds/data/arbor_domainlist.txt +11 -0
  191. data/spec/feeds/data/arbor_ssh.txt +16 -0
  192. data/spec/feeds/data/autoshun_shunlist.csv +20 -0
  193. data/spec/feeds/data/bambenek_c2-dommasterlist.csv +30 -0
  194. data/spec/feeds/data/bambenek_c2-ipmasterlist.csv +27 -0
  195. data/spec/feeds/data/bambenek_dga_feed.csv +42 -0
  196. data/spec/feeds/data/berkeley.txt +29 -0
  197. data/spec/feeds/data/bitcash_cz_blacklist.txt +7 -0
  198. data/spec/feeds/data/blocklist_de_apache-ip-reputation.txt +17 -0
  199. data/spec/feeds/data/blocklist_de_bots-ip-reputation.txt +15 -0
  200. data/spec/feeds/data/blocklist_de_ftp-ip-reputation.txt +7 -0
  201. data/spec/feeds/data/blocklist_de_imap-ip-reputation.txt +8 -0
  202. data/spec/feeds/data/blocklist_de_pop3-ip-reputation.txt +11 -0
  203. data/spec/feeds/data/blocklist_de_proftpd-ip-reputation.txt +12 -0
  204. data/spec/feeds/data/blocklist_de_sip-ip-reputation.txt +9 -0
  205. data/spec/feeds/data/blocklist_de_ssh-ip-reputation.txt +10 -0
  206. data/spec/feeds/data/blocklist_de_strongips-ip-reputation.txt +11 -0
  207. data/spec/feeds/data/botscout-ip-reputation.txt +713 -0
  208. data/spec/feeds/data/cert_mxpoison-ip_reputation.txt +17 -0
  209. data/spec/feeds/data/chaosreigns-ip-reputation.txt +26 -0
  210. data/spec/feeds/data/ciarmy-ip-reputation.txt +11 -0
  211. data/spec/feeds/data/cruzit-ip-reputation.txt +14 -0
  212. data/spec/feeds/data/cydef_torexit-ip_reputation.txt +27 -0
  213. data/spec/feeds/data/dan_me_uk_torlist-ip-reputation.txt +11 -0
  214. data/spec/feeds/data/danger_bruteforce-ip_reputation.txt +12 -0
  215. data/spec/feeds/data/dshield_topattackers.xml +4 -0
  216. data/spec/feeds/data/falconcrest_iplist.txt +345 -0
  217. data/spec/feeds/data/feodo_domainlist.txt +18 -0
  218. data/spec/feeds/data/feodo_iplist.txt +20 -0
  219. data/spec/feeds/data/h3x_asprox.txt +20 -0
  220. data/spec/feeds/data/hosts-file_hphostspartial_domainlist.txt +24 -0
  221. data/spec/feeds/data/infiltrated_iplist.txt +16 -0
  222. data/spec/feeds/data/infiltrated_vabl_iplist.txt +33 -0
  223. data/spec/feeds/data/isc_suspicious_high_domainlist.txt +26 -0
  224. data/spec/feeds/data/isc_suspicious_low_domainlist.txt +34 -0
  225. data/spec/feeds/data/isc_suspicious_medium_domainlist.txt +32 -0
  226. data/spec/feeds/data/malc0de_domainlist.txt +18 -0
  227. data/spec/feeds/data/malc0de_iplist.txt +14 -0
  228. data/spec/feeds/data/malwaredomainlist-url-reputation.txt +8 -0
  229. data/spec/feeds/data/malwaredomains_domainlist.txt +24 -0
  230. data/spec/feeds/data/malwaredomains_dyndns_domainlist.txt +34 -0
  231. data/spec/feeds/data/malwaredomains_justdomains_domainlist.txt +18 -0
  232. data/spec/feeds/data/mirc_domainlist.txt +31 -0
  233. data/spec/feeds/data/multiproxy_iplist.txt +15 -0
  234. data/spec/feeds/data/nothink_irc_iplist.txt +14 -0
  235. data/spec/feeds/data/nothink_ssh_iplist.txt +10 -0
  236. data/spec/feeds/data/openbl_iplist.txt +12 -0
  237. data/spec/feeds/data/openphish-url-reputation.txt +16 -0
  238. data/spec/feeds/data/packetmail_perimeterbad-ip_reputation.txt +44 -0
  239. data/spec/feeds/data/palevo_domainlist.txt +25 -0
  240. data/spec/feeds/data/palevo_iplist.txt +24 -0
  241. data/spec/feeds/data/phishtank-sample.json.gz +0 -0
  242. data/spec/feeds/data/sigmaproject_atma.return.gz +0 -0
  243. data/spec/feeds/data/sigmaproject_spyware.return.gz +0 -0
  244. data/spec/feeds/data/sigmaproject_webexploit.return.gz +0 -0
  245. data/spec/feeds/data/snort_bpf-ip_reputation.txt +16 -0
  246. data/spec/feeds/data/spyeye_domainlist.txt +16 -0
  247. data/spec/feeds/data/spyeye_iplist.txt +19 -0
  248. data/spec/feeds/data/steeman-ip-reputation.txt +13 -0
  249. data/spec/feeds/data/t-arend-de_ssh_iplist.txt +17 -0
  250. data/spec/feeds/data/the_haleys_ssh_iplist.txt +12 -0
  251. data/spec/feeds/data/trustedsec-ip-reputation.txt +12 -0
  252. data/spec/feeds/data/valid.json +2908 -0
  253. data/spec/feeds/data/virbl-ip_reputation.txt +14 -0
  254. data/spec/feeds/data/vxvault-url-reputation.txt +15 -0
  255. data/spec/feeds/data/yourcmc_ssh-ip_reputation.txt +27 -0
  256. data/spec/feeds/data/yoyo_adservers.txt +25 -0
  257. data/spec/feeds/data/zeus-ip_reputation.txt +285 -0
  258. data/spec/feeds/data/zeus_domainlist.txt +27 -0
  259. data/spec/feeds/dshield_attackers-top1000_spec.rb +39 -0
  260. data/spec/feeds/falconcrest-ip_reputation_spec.rb +39 -0
  261. data/spec/feeds/feodo-domain_reputation_spec.rb +47 -0
  262. data/spec/feeds/feodo-ip_reputation_spec.rb +47 -0
  263. data/spec/feeds/h3x_asprox-ip_reputation_spec.rb +50 -0
  264. data/spec/feeds/hosts-file_hphostspartial-domain_reputation_spec.rb +47 -0
  265. data/spec/feeds/infiltrated-ip_reputation_spec.rb +47 -0
  266. data/spec/feeds/infiltrated_vabl-ip_reputation_spec.rb +47 -0
  267. data/spec/feeds/isc_suspicious_high-domain_reputation_spec.rb +47 -0
  268. data/spec/feeds/isc_suspicious_low-domain_reputation_spec.rb +47 -0
  269. data/spec/feeds/isc_suspicious_medium-domain_reputation_spec.rb +47 -0
  270. data/spec/feeds/malc0de-domain_reputation_spec.rb +47 -0
  271. data/spec/feeds/malc0de-ip_reputation_spec.rb +47 -0
  272. data/spec/feeds/malwaredomainlist_url_reputation_spec.rb +50 -0
  273. data/spec/feeds/malwaredomains-domain_reputation_spec.rb +47 -0
  274. data/spec/feeds/malwaredomains_dyndns-domain_reputation_spec.rb +47 -0
  275. data/spec/feeds/malwaredomains_justdomains-domain_reputation_spec.rb +47 -0
  276. data/spec/feeds/mirc-domain_reputation_spec.rb +47 -0
  277. data/spec/feeds/multiproxy-ip_reputation_spec.rb +47 -0
  278. data/spec/feeds/nothink_irc-ip_reputation_spec.rb +47 -0
  279. data/spec/feeds/nothink_ssh-ip_reputation_spec.rb +47 -0
  280. data/spec/feeds/openbl-ip_reputation_spec.rb +47 -0
  281. data/spec/feeds/openphish_url_reputation_spec.rb +50 -0
  282. data/spec/feeds/packetmail_perimeterbad-ip_reputation_spec.rb +47 -0
  283. data/spec/feeds/palevo-domain_reputation_spec.rb +47 -0
  284. data/spec/feeds/palevo-ip_reputation_spec.rb +47 -0
  285. data/spec/feeds/phishtank_spec.rb +41 -0
  286. data/spec/feeds/sigmaproject_atma_spec.rb +62 -0
  287. data/spec/feeds/sigmaproject_spyware_spec.rb +63 -0
  288. data/spec/feeds/sigmaproject_webexploit_spec.rb +62 -0
  289. data/spec/feeds/snort_bpf-ip_reputation_spec.rb +47 -0
  290. data/spec/feeds/spyeye-domain_reputation_spec.rb +47 -0
  291. data/spec/feeds/spyeye-ip_reputation_spec.rb +47 -0
  292. data/spec/feeds/steeman-ip_reputation_spec.rb +50 -0
  293. data/spec/feeds/t-arend-de_ssh-ip_reputation_spec.rb +47 -0
  294. data/spec/feeds/the_haleys_ssh-ip_reputation_spec.rb +47 -0
  295. data/spec/feeds/trustedsec-ip_reputation_spec.rb +47 -0
  296. data/spec/feeds/virbl-ip_reputation_spec.rb +47 -0
  297. data/spec/feeds/vxvault_url_reputation_spec.rb +50 -0
  298. data/spec/feeds/yourcmc_ssh-ip_reputation_spec.rb +47 -0
  299. data/spec/feeds/yoyo_adservers_spec.rb +47 -0
  300. data/spec/feeds/zeus-domain_reputation_spec.rb +47 -0
  301. data/spec/feeds/zeus-ip_reputation_spec.rb +47 -0
  302. data/spec/fixtures/feed/provider1/feed1.feed +6 -0
  303. data/spec/fixtures/parsers/test.xml +13 -0
  304. data/spec/fixtures/parsers/test_self_closing.xml +20 -0
  305. data/spec/fixtures/plugins/bad/threatinator/plugins/test_error1/plugin.rb +1 -0
  306. data/spec/fixtures/plugins/bad/threatinator/plugins/test_missing1/plugin.rb +0 -0
  307. data/spec/fixtures/plugins/fake.rb +19 -0
  308. data/spec/fixtures/plugins/good/threatinator/plugins/test_type1/plugin_a.rb +8 -0
  309. data/spec/fixtures/plugins/good/threatinator/plugins/test_type1/plugin_b.rb +8 -0
  310. data/spec/fixtures/plugins/good/threatinator/plugins/test_type2/plugin_c.rb +8 -0
  311. data/spec/fixtures/plugins/good/threatinator/plugins/test_type2/plugin_d.rb +8 -0
  312. data/spec/fixtures/plugins/good/threatinator/plugins/test_type3/plugin_e.rb +8 -0
  313. data/spec/fixtures/plugins/good/threatinator/plugins/test_type3/plugin_f.rb +8 -0
  314. data/spec/spec_helper.rb +54 -0
  315. data/spec/support/bad_feeds/missing_fetcher.feed +7 -0
  316. data/spec/support/bad_feeds/missing_name.feed +6 -0
  317. data/spec/support/bad_feeds/missing_parser.feed +3 -0
  318. data/spec/support/bad_feeds/missing_provider.feed +5 -0
  319. data/spec/support/factories/event.rb +31 -0
  320. data/spec/support/factories/feed.rb +59 -0
  321. data/spec/support/factories/feed_builder.rb +65 -0
  322. data/spec/support/factories/feed_registry.rb +8 -0
  323. data/spec/support/factories/ipv4.rb +36 -0
  324. data/spec/support/factories/output.rb +11 -0
  325. data/spec/support/factories/record.rb +17 -0
  326. data/spec/support/factories/url.rb +34 -0
  327. data/spec/support/factories/xml_node.rb +33 -0
  328. data/spec/support/helpers/io.rb +11 -0
  329. data/spec/support/helpers/models.rb +13 -0
  330. data/spec/support/shared/action_builder.rb +47 -0
  331. data/spec/support/shared/decoder.rb +70 -0
  332. data/spec/support/shared/feed_runner_observer.rb +136 -0
  333. data/spec/support/shared/feeds.rb +233 -0
  334. data/spec/support/shared/fetcher.rb +48 -0
  335. data/spec/support/shared/filter.rb +14 -0
  336. data/spec/support/shared/io-like.rb +7 -0
  337. data/spec/support/shared/model/collection.rb +164 -0
  338. data/spec/support/shared/output.rb +120 -0
  339. data/spec/support/shared/parsers.rb +51 -0
  340. data/spec/support/shared/record.rb +111 -0
  341. data/spec/threatinator/actions/list/action_spec.rb +148 -0
  342. data/spec/threatinator/actions/run/action_spec.rb +106 -0
  343. data/spec/threatinator/actions/run/config_spec.rb +39 -0
  344. data/spec/threatinator/actions/run/coverage_observer_spec.rb +151 -0
  345. data/spec/threatinator/actions/run/output_config_spec.rb +89 -0
  346. data/spec/threatinator/actions/run/status_observer_spec.rb +86 -0
  347. data/spec/threatinator/cli/list_action_builder_spec.rb +57 -0
  348. data/spec/threatinator/cli/run_action_builder_spec.rb +133 -0
  349. data/spec/threatinator/cli_spec.rb +175 -0
  350. data/spec/threatinator/config/base_spec.rb +39 -0
  351. data/spec/threatinator/config/feed_search_spec.rb +76 -0
  352. data/spec/threatinator/decoders/gzip_spec.rb +75 -0
  353. data/spec/threatinator/event_builder_spec.rb +123 -0
  354. data/spec/threatinator/event_spec.rb +254 -0
  355. data/spec/threatinator/event_spec.rb.new +319 -0
  356. data/spec/threatinator/feed_builder_spec.rb +633 -0
  357. data/spec/threatinator/feed_registry_spec.rb +198 -0
  358. data/spec/threatinator/feed_runner_spec.rb +372 -0
  359. data/spec/threatinator/feed_spec.rb +169 -0
  360. data/spec/threatinator/fetcher_spec.rb +12 -0
  361. data/spec/threatinator/fetchers/http_spec.rb +32 -0
  362. data/spec/threatinator/filter_spec.rb +13 -0
  363. data/spec/threatinator/filters/block_spec.rb +16 -0
  364. data/spec/threatinator/filters/comments_spec.rb +13 -0
  365. data/spec/threatinator/filters/whitespace_spec.rb +12 -0
  366. data/spec/threatinator/logger_spec.rb +29 -0
  367. data/spec/threatinator/model/observables/fqdn_collection_spec.rb +41 -0
  368. data/spec/threatinator/model/observables/ipv4_collection_spec.rb +36 -0
  369. data/spec/threatinator/model/observables/ipv4_spec.rb +75 -0
  370. data/spec/threatinator/model/observables/url_collection_spec.rb +45 -0
  371. data/spec/threatinator/model/validations/type_spec.rb +37 -0
  372. data/spec/threatinator/parser_spec.rb +13 -0
  373. data/spec/threatinator/parsers/csv/parser_spec.rb +202 -0
  374. data/spec/threatinator/parsers/getline/parser_spec.rb +83 -0
  375. data/spec/threatinator/parsers/json/parser_spec.rb +106 -0
  376. data/spec/threatinator/parsers/json/record_spec.rb +30 -0
  377. data/spec/threatinator/parsers/xml/node_spec.rb +335 -0
  378. data/spec/threatinator/parsers/xml/parser_spec.rb +263 -0
  379. data/spec/threatinator/parsers/xml/path_spec.rb +209 -0
  380. data/spec/threatinator/parsers/xml/pattern_spec.rb +72 -0
  381. data/spec/threatinator/parsers/xml/record_spec.rb +27 -0
  382. data/spec/threatinator/plugin_loader_spec.rb +238 -0
  383. data/spec/threatinator/plugins/output/csv_spec.rb +47 -0
  384. data/spec/threatinator/plugins/output/null_spec.rb +17 -0
  385. data/spec/threatinator/plugins/output/rubydebug_spec.rb +37 -0
  386. data/spec/threatinator/record_spec.rb +19 -0
  387. data/spec/threatinator/registry_spec.rb +97 -0
  388. data/spec/threatinator/runner_spec.rb +273 -0
  389. metadata +674 -0
@@ -0,0 +1,88 @@
1
+ require 'threatinator/exceptions'
2
+
3
+ module Threatinator
4
+ class Feed
5
+ # @param [Hash] opts Options hash
6
+ # @option opts [String] :provider The name of the provider
7
+ # @option opts [String] :name The name of the feed
8
+ # @option opts [Proc] :parser_block A block that will be called by the
9
+ # parser each time it processes a record.
10
+ # @option opts [Proc] :parser_builder A proc that, when called, will
11
+ # return a brand new instance of a Threatinator::Parser.
12
+ # @option opts [Proc] :fetcher_builder A proc that, when called, will
13
+ # return a brand new instance of a Threatinator::Fetcher.
14
+ # @option opts [Array<Proc>] :filter_builders An array of procs that,
15
+ # when called, will each return an instance of a filter (something that
16
+ # responds to :filter?)
17
+ # @option opts [Array<Proc>] :decoder_builders An array of procs that,
18
+ # when called, will each return an instance of a Threatinator::Decoder
19
+ def initialize(opts = {})
20
+ @provider = opts.delete(:provider)
21
+ @name = opts.delete(:name)
22
+ @event_types = opts.delete(:event_types) || [:uknown]
23
+ @parser_block = opts.delete(:parser_block)
24
+
25
+ @parser_builder = opts.delete(:parser_builder)
26
+ @fetcher_builder = opts.delete(:fetcher_builder)
27
+ @filter_builders = opts.delete(:filter_builders) || []
28
+ @decoder_builders = opts.delete(:decoder_builders) || []
29
+ validate!
30
+ end
31
+
32
+ def provider
33
+ @provider.dup
34
+ end
35
+
36
+ def name
37
+ @name.dup
38
+ end
39
+
40
+ def event_types
41
+ @event_types.dup
42
+ end
43
+
44
+ def parser_block
45
+ @parser_block
46
+ end
47
+
48
+ def fetcher_builder
49
+ @fetcher_builder
50
+ end
51
+
52
+ def parser_builder
53
+ @parser_builder
54
+ end
55
+
56
+ def filter_builders
57
+ @filter_builders.dup
58
+ end
59
+
60
+ def decoder_builders
61
+ @decoder_builders.dup
62
+ end
63
+
64
+ def validate!
65
+ validate_attribute!(:provider, @provider) { |x| x.kind_of?(::String) }
66
+ validate_attribute!(:name, @name) { |x| x.kind_of?(::String) }
67
+ validate_attribute!(:event_types, @event_types) { |x| x.kind_of?(::Array) }
68
+ validate_attribute!(:parser_block, @parser_block) { |x| x.kind_of?(::Proc) }
69
+ validate_attribute!(:fetcher_builder, @fetcher_builder) { |x| x.kind_of?(::Proc) }
70
+ validate_attribute!(:parser_builder, @parser_builder) { |x| x.kind_of?(::Proc) }
71
+ validate_attribute!(:filter_builders, @filter_builders) do |x|
72
+ x.kind_of?(::Array) &&
73
+ x.all? { |e| e.kind_of?(::Proc) }
74
+ end
75
+
76
+ validate_attribute!(:decoder_builders, @decoder_builders) do |x|
77
+ x.kind_of?(::Array) &&
78
+ x.all? { |e| e.kind_of?(::Proc) }
79
+ end
80
+ end
81
+
82
+ def validate_attribute!(name, val, &block)
83
+ unless block.call(val) == true
84
+ raise Threatinator::Exceptions::InvalidAttributeError.new("Invalid attribute (#{name}). Got: #{val.inspect}")
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,161 @@
1
+ require 'docile'
2
+ require 'threatinator/feed'
3
+ require 'threatinator/exceptions'
4
+ require 'threatinator/decoders/gzip'
5
+ require 'threatinator/fetchers/http'
6
+ require 'threatinator/parsers/getline'
7
+ require 'threatinator/parsers/csv'
8
+ require 'threatinator/parsers/json'
9
+ require 'threatinator/parsers/xml'
10
+ require 'threatinator/filters/block'
11
+ require 'threatinator/filters/whitespace'
12
+ require 'threatinator/filters/comments'
13
+
14
+ module Threatinator
15
+ class FeedBuilder
16
+ def provider(provider_name)
17
+ @provider = provider_name
18
+ self
19
+ end
20
+
21
+ def name(name)
22
+ @name = name
23
+ self
24
+ end
25
+
26
+ def event_types(event_types=[:notlabeled])
27
+ @event_types ||= event_types
28
+ self
29
+ end
30
+
31
+ def fetch_http(url, opts = {})
32
+ opts[:url] = url
33
+ @fetcher_builder = lambda do
34
+ opts_dup = Marshal.load(Marshal.dump(opts))
35
+ Threatinator::Fetchers::Http.new(opts_dup)
36
+ end
37
+ self
38
+ end
39
+
40
+ def parse_xml(pattern_string, opts = {}, &block)
41
+ @parser_builder = lambda do
42
+ pattern = Threatinator::Parsers::XML::Pattern.new(pattern_string)
43
+ opts_dup = Marshal.load(Marshal.dump(opts))
44
+ opts_dup[:pattern] = pattern
45
+ Threatinator::Parsers::XML::Parser.new(opts_dup, &block)
46
+ end
47
+ @parser_block = block
48
+ self
49
+ end
50
+
51
+ def parse_json(opts = {}, &block)
52
+ @parser_builder = lambda do
53
+ opts_dup = Marshal.load(Marshal.dump(opts))
54
+ Threatinator::Parsers::JSON::Parser.new(opts_dup, &block)
55
+ end
56
+ @parser_block = block
57
+ self
58
+ end
59
+
60
+ def parse_eachline(opts = {}, &block)
61
+ @parser_builder = lambda do
62
+ opts_dup = Marshal.load(Marshal.dump(opts))
63
+ Threatinator::Parsers::Getline::Parser.new(opts_dup, &block)
64
+ end
65
+ @parser_block = block
66
+ self
67
+ end
68
+
69
+ def parse_csv(opts = {}, &block)
70
+ @parser_builder = lambda do
71
+ opts_dup = Marshal.load(Marshal.dump(opts))
72
+ Threatinator::Parsers::CSV::Parser.new(opts_dup, &block)
73
+ end
74
+ @parser_block = block
75
+ self
76
+ end
77
+
78
+ # Specify a block filter for the parser
79
+ def filter(&block)
80
+ @filter_builders ||= []
81
+ @filter_builders << lambda { Threatinator::Filters::Block.new(block) }
82
+ self
83
+ end
84
+
85
+ # Filter out whitespace lines. Only works on line-based text.
86
+ def filter_whitespace
87
+ @filter_builders ||= []
88
+ @filter_builders << lambda { Threatinator::Filters::Whitespace.new }
89
+ self
90
+ end
91
+
92
+ # Filter out whitespace lines. Only works on line-based text.
93
+ def filter_comments
94
+ @filter_builders ||= []
95
+ @filter_builders << lambda { Threatinator::Filters::Comments.new }
96
+ self
97
+ end
98
+
99
+ # Add the Gzip decoder
100
+ def decode_gzip
101
+ decoder_builders << lambda { Threatinator::Decoders::Gzip.new }
102
+ self
103
+ end
104
+ alias_method :extract_gzip, :decode_gzip
105
+ alias_method :gunzip, :decode_gzip
106
+
107
+ def decoder_builders
108
+ @decoder_builders ||= []
109
+ end
110
+ private :decoder_builders
111
+
112
+ def build
113
+ Feed.new(
114
+ :provider => @provider,
115
+ :name => @name,
116
+ :event_types => @event_types || [:unknown],
117
+ :parser_block => @parser_block,
118
+ :fetcher_builder => @fetcher_builder,
119
+ :parser_builder => @parser_builder,
120
+ :filter_builders => @filter_builders,
121
+ :decoder_builders => decoder_builders
122
+ )
123
+ end
124
+
125
+ # Loads the provided file, and generates a builder from it.
126
+ # @param [String] filename The name of the file to read the feed from
127
+ # @raise [FeedFileNotFoundError] if the file is not found
128
+ def self.from_file(filename)
129
+ begin
130
+ filedata = File.read(filename)
131
+ rescue Errno::ENOENT
132
+ raise Threatinator::Exceptions::FeedFileNotFoundError.new(filename)
133
+ end
134
+ from_string(filedata, filename, 0)
135
+ end
136
+
137
+ # Generates a builder from a string via eval.
138
+ # @param [String] str The DSL code that specifies the feed.
139
+ # @param [String] filename (nil) Passed to eval.
140
+ # @param [String] lineno (nil) Passed to eval.
141
+ # @raise [FeedFileNotFoundError] if the file is not found
142
+ # @see Kernel#eval for details on filename and lineno
143
+ def self.from_string(str, filename = nil, lineno = nil)
144
+ from_dsl do
145
+ args = [str, binding]
146
+ unless filename.nil?
147
+ args << filename
148
+ unless lineno.nil?
149
+ args << lineno
150
+ end
151
+ end
152
+ eval(*args)
153
+ end
154
+ end
155
+
156
+ # Executes the block parameter within DSL scope
157
+ def self.from_dsl(&block)
158
+ Docile.dsl_eval(self.new, &block)
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,47 @@
1
+ require 'threatinator/registry'
2
+ require 'threatinator/feed_builder'
3
+
4
+ module Threatinator
5
+ class FeedRegistry < Registry
6
+ # @param [Threatinator::Feed] feed The feed to register
7
+ # @raise [Threatinator::Exceptions::AlreadyRegisteredError] if a feed
8
+ # with the same name and provider is already registered.
9
+ def register(feed)
10
+ super([feed.provider, feed.name], feed)
11
+ end
12
+
13
+ # @param [String] provider
14
+ # @param [String] name
15
+ # @return [Threatinator::Feed]
16
+ def get(provider, name)
17
+ super([provider, name])
18
+ end
19
+
20
+ def each
21
+ return enum_for(:each) unless block_given?
22
+ super do |key, feed|
23
+ yield(feed)
24
+ end
25
+ end
26
+
27
+ def register_from_file(filename)
28
+ builder = Threatinator::FeedBuilder.from_file(filename)
29
+ feed = builder.build
30
+ register(feed)
31
+ feed
32
+ end
33
+
34
+ # Builds a new FeedRegistry based on the provided config
35
+ # @param [Threatinator::Config::FeedSearch] config The configuration
36
+ def self.build(config)
37
+ ret = self.new
38
+ config.search_path.each do |path|
39
+ pattern = File.join(path, "**", "*.feed")
40
+ Dir.glob(pattern).each do |filename|
41
+ ret.register_from_file(filename)
42
+ end
43
+ end
44
+ ret
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,177 @@
1
+ require 'threatinator/event_builder'
2
+ require 'threatinator/logging'
3
+ require 'observer'
4
+
5
+ module Threatinator
6
+ # Runs those feeds!
7
+ #
8
+ # Has the following observations:
9
+ # :start - start of feed parsing
10
+ #
11
+ # :start_fetch - start of fetching
12
+ # :end_fetch - end of fetching
13
+ #
14
+ # :start_decode - start of decoding
15
+ # :end_decode - end of decoding
16
+ #
17
+ # :start_parse_record - start of record parse
18
+ # - record - The record
19
+ #
20
+ # :record_filtered - Indicates that the record was filtered.
21
+ # - record - The record
22
+ #
23
+ # :record_missed - Indicates that the record was not parsed
24
+ # - record - The record
25
+ #
26
+ # :record_parsed - Indicates that the record WAS parsed
27
+ # - record - The record
28
+ # - events - The events that were parsed out of the
29
+ # record
30
+ #
31
+ # :record_error - Indicates that the record WAS parsed
32
+ # - record - The record
33
+ # - errors - An array of exceptions that caused the error
34
+ #
35
+ # :end_parse_record - when a record has been parsed
36
+ # - record - The record
37
+ #
38
+ # :end - completion of feed parsing
39
+ #
40
+ class FeedRunner
41
+ include Observable
42
+ include Logging
43
+
44
+ # @param [Threatinator::Feed] feed The feed that we want to run.
45
+ # @param [Threatinator::Output] output_formatter
46
+ def initialize(feed, output_formatter, opts = {})
47
+ @feed = feed
48
+ @output_formatter = output_formatter
49
+ @feed_filters = @feed.filter_builders.map { |x| x.call }
50
+ @decoders = @feed.decoder_builders.map { |x| x.call }
51
+ @parser_block = @feed.parser_block
52
+ @create_event_proc = self.method(:create_event).to_proc
53
+
54
+ @event_builder = Threatinator::EventBuilder.new(@feed.provider, @feed.name)
55
+
56
+ @total_events_built = 0
57
+ @event_errors = []
58
+ @built_events = []
59
+ end
60
+
61
+ # @param [Hash] opts The options hash
62
+ # @option opts [IO-like] :io Override the fetcher by providing
63
+ # an IO directly.
64
+ # @option opts [Boolean] :skip_decoding (false) Skip all decoding if set
65
+ # to true. Useful for testing.
66
+ def run(opts = {})
67
+ ios = [ ]
68
+ logger.debug("#run starting #{@feed.provider}:#{@feed.name}") if logger.debug?
69
+ start = Time.now
70
+ changed(true); notify_observers(:start)
71
+ skip_decoding = !!opts.delete(:skip_decoding)
72
+
73
+
74
+ unless io = opts.delete(:io)
75
+ fetcher = @feed.fetcher_builder.call()
76
+ changed(true); notify_observers(:start_fetch)
77
+ io = fetcher.fetch()
78
+ changed(true); notify_observers(:end_fetch)
79
+ else
80
+ logger.debug('#run Skipping fetch. IO object was provided')
81
+ end
82
+
83
+ ios << io
84
+
85
+ unless skip_decoding == true
86
+ changed(true); notify_observers(:start_decode)
87
+ @decoders.each do |decoder|
88
+ new_io = decoder.decode(io)
89
+ ios << new_io
90
+ io = new_io
91
+ end
92
+ changed(true); notify_observers(:end_decode)
93
+ end
94
+
95
+ parser = @feed.parser_builder.call()
96
+
97
+ parser.run(io) do |record|
98
+ rr = parse_record(record)
99
+ end
100
+
101
+ changed(true); notify_observers(:end)
102
+
103
+ logger.debug("#run finished #{@feed.provider}:#{@feed.name} in #{Time.now - start} seconds") if logger.debug?
104
+ nil
105
+ ensure
106
+ # Close all IO objects that we've seen.
107
+ while some_io = ios.pop
108
+ unless some_io.closed?
109
+ begin
110
+ some_io.close
111
+ rescue => e
112
+ #:nocov:
113
+ logger.warn("Failed to close IO: #{e} #{e.message}")
114
+ #:nocov:
115
+ end
116
+ end
117
+ end
118
+
119
+ @output_formatter.finish
120
+ end
121
+
122
+ def create_event
123
+ @event_builder.reset
124
+ @event_errors.clear
125
+ yield(@event_builder)
126
+ begin
127
+ event = @event_builder.build
128
+ @total_events_built += 1
129
+ @built_events << event
130
+ rescue Threatinator::Exceptions::EventBuildError => e
131
+ @event_errors << e
132
+ end
133
+ end
134
+
135
+ def parse_record(record)
136
+ @built_events.clear
137
+ events = []
138
+ changed(true); notify_observers(:start_parse_record, record)
139
+
140
+ if @feed_filters.any? { |filter| filter.filter?(record) }
141
+ changed(true); notify_observers(:record_filtered, record)
142
+ return
143
+ end
144
+
145
+ @parser_block.call(@create_event_proc, record)
146
+
147
+ if @event_errors.count > 0
148
+ changed(true); notify_observers(:record_error, record, @event_errors)
149
+ position = "line: #{record.line_number}, start: #{record.pos_start}, end: #{record.pos_end}"
150
+ messages = @event_errors.map { |e| e.to_s }.join(', ')
151
+ logger.debug("Error generating event from record (#{position}): #{messages}")
152
+ elsif @built_events.count == 0
153
+ changed(true); notify_observers(:record_missed, record)
154
+ position = "line: #{record.line_number}, start: #{record.pos_start}, end: #{record.pos_end}"
155
+ logger.debug("Expected event to be generated, but got none from record (#{position})")
156
+ else
157
+ @built_events.each do |event|
158
+ events << event
159
+ @output_formatter.handle_event(event)
160
+ end
161
+ changed(true); notify_observers(:record_parsed, record, events)
162
+ end
163
+ return
164
+ ensure
165
+ changed(true); notify_observers(:end_parse_record, record)
166
+ end
167
+
168
+ # Runs a feed
169
+ # @param [Threatinator::Feed] feed The feed to run
170
+ # @param [Threatinator::Output] output The output instance
171
+ # @param [Hash] run_opts Options passed to #run. See #run .
172
+ def self.run(feed, output, run_opts = {})
173
+ self.new(feed, output).run(run_opts)
174
+ end
175
+
176
+ end
177
+ end
@@ -0,0 +1,22 @@
1
+ module Threatinator
2
+ class Fetcher
3
+
4
+ # @param [Hash] opts An options hash. See subclasses for details.
5
+ def initialize(opts = {})
6
+ end
7
+
8
+ # @return [IO] an IO object
9
+ def fetch
10
+ raise NotImplementedError.new("#{self.class}#fetch not implemented!")
11
+ end
12
+
13
+ def ==(other)
14
+ true
15
+ end
16
+
17
+ def eql?(other)
18
+ self.class == other.class &&
19
+ self == other
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ require 'threatinator/fetcher'
2
+ require 'threatinator/exceptions'
3
+ require 'typhoeus'
4
+ require 'tempfile'
5
+
6
+ module Threatinator
7
+ module Fetchers
8
+ class Http < Threatinator::Fetcher
9
+ attr_reader :url
10
+ # @param [Hash] opts An options hash.
11
+ # @option opts [Addressable::URI] :url The URL that is to be fetched
12
+ # (required)
13
+ #
14
+ def initialize(opts = {})
15
+ @url = opts.delete(:url) or raise ArgumentError.new("Missing :url")
16
+ super(opts)
17
+ end
18
+
19
+ def ==(other)
20
+ @url == other.url && super(other)
21
+ end
22
+
23
+ # @return [IO] an IO-style object.
24
+ # @raise [Threatinator::Exceptions::FetchFailed] if the fetch fails
25
+ def fetch
26
+ tempfile = Tempfile.new("threatinator_http")
27
+ request = Typhoeus::Request.new(@url,
28
+ ssl_verifypeer: false,
29
+ followlocation: true,
30
+ forbid_reuse: true
31
+ )
32
+ request.on_headers do |response|
33
+ if response.response_code != 200
34
+
35
+ raise Threatinator::Exceptions::FetchFailed.new("Request failed!")
36
+ end
37
+ end
38
+ request.on_body do |chunk|
39
+ tempfile.write(chunk)
40
+ end
41
+ # Run it
42
+ request.run
43
+ # Reset the IO to the beginning of the file
44
+ tempfile.rewind
45
+ tempfile
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ module Threatinator
2
+ # Acts as a filter for parser data.
3
+ class Filter
4
+ # What is passed in as arguments depends upon the parser.
5
+ #
6
+ # @param [Threatinator::Record] record The record to filter
7
+ # @return [Boolean] true if filtered, false otherwise.
8
+ def filter?(record)
9
+ raise NotImplementedError.new("#{self.class}.filter?(record) not implemented")
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ require 'threatinator/filter'
2
+
3
+ module Threatinator
4
+ module Filters
5
+ # Basic filter that allows for arbitrary filtering.
6
+ class Block < Threatinator::Filter
7
+ def initialize(block)
8
+ @block = block
9
+ end
10
+
11
+ # @param [Threatinator::Record] record The record to filter
12
+ # @return [Boolean] true if filtered, false otherwise.
13
+ def filter?(record)
14
+ !! @block.call(record)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ require 'threatinator/filter'
2
+
3
+ module Threatinator
4
+ module Filters
5
+ # Filters out any lines of text that begin with a comment '#'
6
+ class Comments < Threatinator::Filter
7
+ # @param [Threatinator::Record] record The record to filter
8
+ # @return [Boolean] true if filtered, false otherwise.
9
+ def filter?(record)
10
+ record.data[0] == '#'
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+
@@ -0,0 +1,19 @@
1
+ require 'threatinator/filter'
2
+
3
+ module Threatinator
4
+ module Filters
5
+ # Filters on any lines of text that consist entirely of whitespace
6
+ class Whitespace < Threatinator::Filter
7
+ def initialize()
8
+ @re = /^\s*$/
9
+ end
10
+
11
+ # @param [Threatinator::Record] record The record to filter
12
+ # @return [Boolean] true if filtered, false otherwise.
13
+ def filter?(record)
14
+ !! @re.match(record.data)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,66 @@
1
+ require 'log4r'
2
+
3
+ module Threatinator
4
+ module Logger
5
+ # The log levels don't get defined until the first time a logger is
6
+ # initialized. So, we call the root logger once just to get this to happen.
7
+ Log4r::RootLogger.instance
8
+
9
+ def self.logger_for(name)
10
+ ::Log4r::Logger[name] || ::Log4r::Logger.new(name)
11
+ end
12
+
13
+ def self.default_logger
14
+ return @logger unless @logger.nil?
15
+
16
+ @logger = logger_for('Threatinator')
17
+ formatter = ::Log4r::PatternFormatter.new(:pattern => '[%d] %l %C: %M')
18
+
19
+ console_outputter = ::Log4r::StderrOutputter.new('console', formatter: formatter)
20
+ @logger.add console_outputter
21
+
22
+ @logger.level = ::Log4r::INFO
23
+ @logger
24
+ end
25
+
26
+ # @param [Threatinator::Config::Logger] config Logging configuration object
27
+ def self.configure_logger(config)
28
+ if config.level
29
+ if l = self.levels.index(config.level)
30
+ default_logger.level = l
31
+ else
32
+ default_logger.warn("Ignoring unknown logging level: #{config.level.inspect}.")
33
+ end
34
+ end
35
+ end
36
+
37
+ def self.level
38
+ default_logger.level
39
+ end
40
+
41
+ def self.level=(l)
42
+ default_logger.level = l
43
+ end
44
+
45
+ def self.level_string
46
+ levels[level]
47
+ end
48
+
49
+ def self.levels
50
+ default_logger.levels
51
+ end
52
+
53
+ # Initializes the default logger. This allows us to pull the logger levels.
54
+ self.default_logger()
55
+
56
+ module Levels
57
+ ALL = ::Log4r::ALL
58
+ DEBUG = ::Log4r::DEBUG
59
+ INFO = ::Log4r::INFO
60
+ WARN = ::Log4r::WARN
61
+ ERROR = ::Log4r::ERROR
62
+ FATAL = ::Log4r::FATAL
63
+ OFF = ::Log4r::OFF
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,20 @@
1
+ require 'threatinator/logger'
2
+
3
+ module Threatinator
4
+ # Mixin for mixing logging facilities into classes.
5
+ module Logging
6
+ def self.included(base)
7
+ base.extend(LoggingClassMethods)
8
+ end
9
+
10
+ def logger
11
+ @logger ||= self.class.logger
12
+ end
13
+ end
14
+
15
+ module LoggingClassMethods
16
+ def logger
17
+ @logger ||= Threatinator::Logger.logger_for(self.name)
18
+ end
19
+ end
20
+ end