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,86 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/actions/run/status_observer'
3
+
4
+ describe Threatinator::Actions::Run::StatusObserver do
5
+ let(:observer) { described_class.new() }
6
+ let(:record) { build(:record, line_number: 23, pos_start: 99, pos_end: 105, data: "foobar\r\n") }
7
+
8
+ it_should_behave_like "a FeedRunner observer"
9
+
10
+ describe "#filtered" do
11
+ it "returns the number of records that have been filtered" do
12
+ expect(observer.filtered).to eq(0)
13
+ observer.update(:record_filtered, record)
14
+ expect(observer.filtered).to eq(1)
15
+ end
16
+ end
17
+
18
+ describe "#filtered?" do
19
+ it "returns true if any records were filtered, false otherwise" do
20
+ expect(observer.filtered?).to eq(false)
21
+ observer.update(:record_filtered, record)
22
+ expect(observer.filtered?).to eq(true)
23
+ end
24
+ end
25
+
26
+ describe "#missed" do
27
+ it "returns the number of records that have been missed" do
28
+ expect(observer.missed).to eq(0)
29
+ observer.update(:record_missed, record)
30
+ expect(observer.missed).to eq(1)
31
+ end
32
+ end
33
+
34
+ describe "#missed?" do
35
+ it "returns true if any records were missed, false otherwise" do
36
+ expect(observer.missed?).to eq(false)
37
+ observer.update(:record_missed, record)
38
+ expect(observer.missed?).to eq(true)
39
+ end
40
+ end
41
+
42
+ describe "#parsed" do
43
+ it "returns the number of records that have been parsed" do
44
+ expect(observer.parsed).to eq(0)
45
+ observer.update(:record_parsed, record)
46
+ expect(observer.parsed).to eq(1)
47
+ end
48
+ end
49
+
50
+ describe "#parsed?" do
51
+ it "returns true if any records were parsed, false otherwise" do
52
+ expect(observer.parsed?).to eq(false)
53
+ observer.update(:record_parsed, record)
54
+ expect(observer.parsed?).to eq(true)
55
+ end
56
+ end
57
+
58
+ describe "#errors" do
59
+ it "returns the number of records that had errors" do
60
+ expect(observer.errors).to eq(0)
61
+ observer.update(:record_error, record)
62
+ expect(observer.errors).to eq(1)
63
+ end
64
+ end
65
+
66
+ describe "#errors?" do
67
+ it "returns true if any records had errors, false otherwise" do
68
+ expect(observer.errors?).to eq(false)
69
+ observer.update(:record_error, record)
70
+ expect(observer.errors?).to eq(true)
71
+ end
72
+ end
73
+
74
+
75
+ describe "#total" do
76
+ it "returns the total number of records that were parsed, missed, filtered, and errored" do
77
+ expect(observer.total).to eq(0)
78
+ 10.times { observer.update(:record_parsed, record) }
79
+ 10.times { observer.update(:record_missed, record) }
80
+ 10.times { observer.update(:record_filtered, record) }
81
+ 10.times { observer.update(:record_error, record) }
82
+ expect(observer.total).to eq(40)
83
+ end
84
+ end
85
+ end
86
+
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/cli/list_action_builder'
3
+
4
+ describe Threatinator::CLI::ListActionBuilder do
5
+ describe 'an instance' do
6
+ let(:config_hash) { {} }
7
+ let(:extra_args) { [] }
8
+ let(:builder) { described_class.new(config_hash, extra_args) }
9
+
10
+ it_behaves_like "an action builder"
11
+
12
+ describe "#config" do
13
+ context "when config_hash['list'] is provided" do
14
+ let(:list_hash) { double('list hash') }
15
+ before :each do
16
+ config_hash['list'] = list_hash
17
+ end
18
+ it "builds a new Threatinator::Actions::List::Config using config_hash['list']" do
19
+ expect(Threatinator::Actions::List::Config).to receive(:new).with(list_hash)
20
+ builder.config
21
+ end
22
+ end
23
+ context "when config_hash['list'] does not exist" do
24
+ before :each do
25
+ config_hash.delete 'list'
26
+ end
27
+ it "builds a new Threatinator::Config::FeedSearch using an empty hash" do
28
+ expect(Threatinator::Actions::List::Config).to receive(:new).with({})
29
+ builder.config
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "#build" do
35
+ let(:action) { double('action') }
36
+ let(:config) { double('config') }
37
+ let(:feed_registry) { double('feed registry') }
38
+ before :each do
39
+ allow(Threatinator::Actions::List::Action).to receive(:new).and_return(action)
40
+ allow(builder).to receive(:config).and_return(config)
41
+ allow(builder).to receive(:feed_registry).and_return(feed_registry)
42
+ end
43
+
44
+ let(:result) { builder.build }
45
+
46
+ it "builds an instance of Threatinator::Actions::List::Action using #feed_registry and #config" do
47
+ expect(Threatinator::Actions::List::Action).to receive(:new).with(feed_registry, config)
48
+ builder.build
49
+ end
50
+
51
+ it "returns the instance of the action" do
52
+ expect(builder.build).to be(action)
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+ require 'threatinator/cli/run_action_builder'
4
+ require 'threatinator/plugin_loader'
5
+
6
+ describe Threatinator::CLI::RunActionBuilder do
7
+ describe 'an instance' do
8
+ let(:plugin_loader) { Threatinator::PluginLoader.new }
9
+ let(:config_class) { Threatinator::Actions::Run::Config.generate(plugin_loader) }
10
+ let(:config_hash) { { 'run' => {} } }
11
+ let(:extra_args) { [] }
12
+ let(:builder) { described_class.new(config_hash, extra_args, config_class) }
13
+
14
+ it_behaves_like "an action builder"
15
+
16
+ describe "#config" do
17
+ let(:config) { builder.config }
18
+ it "returns an instance of config_class" do
19
+ expect(config).to be_a(config_class)
20
+ end
21
+
22
+ describe "config_hash['run']['coverage_output']" do
23
+ context "when nil" do
24
+ before :each do
25
+ config_hash['run'].delete('coverage_output')
26
+ end
27
+
28
+ it "sets config.observers to []" do
29
+ config = builder.config
30
+ expect(config.observers).to contain_exactly()
31
+ end
32
+ end
33
+
34
+ context "when set to a string" do
35
+ let(:coverage_proc) { lambda { } }
36
+ before :each do
37
+ config_hash['run']['coverage_output'] = "asdf"
38
+ end
39
+ it "initializes a CoverageObserver with the string" do
40
+ expect(Threatinator::Actions::Run::CoverageObserver).to receive(:new).with('asdf')
41
+ builder.config
42
+ end
43
+ it "sets config.observers an array consisting of the CoverageObserver" do
44
+ observer = double('observer')
45
+ expect(Threatinator::Actions::Run::CoverageObserver).to receive(:new).and_return(observer)
46
+
47
+ config = builder.config
48
+ expect(config.observers).to contain_exactly(observer)
49
+ end
50
+ end
51
+ end
52
+
53
+ context "config_hash['run']['feed_provider']" do
54
+ context "when nil" do
55
+ before :each do
56
+ config_hash['run'].delete('feed_provider')
57
+ end
58
+ context "and there are no extra arguments" do
59
+ specify "#feed_provider is nil" do
60
+ expect(config.feed_provider).to be_nil
61
+ end
62
+ end
63
+
64
+ context "and there is at least one extra argument" do
65
+ before :each do
66
+ extra_args << "arg1"
67
+ extra_args << "arg2"
68
+ extra_args << "arg3"
69
+ end
70
+ specify "#feed_provider is the first extra argument" do
71
+ expect(config.feed_provider).to eq("arg1")
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ context "config_hash['run']['feed_name']" do
78
+ context "when nil" do
79
+ before :each do
80
+ config_hash['run'].delete('feed_name')
81
+ end
82
+ context "and there are no extra arguments" do
83
+ specify "#feed_name is nil" do
84
+ expect(config.feed_name).to be_nil
85
+ end
86
+ end
87
+
88
+ context "and there are extra arguments" do
89
+ before :each do
90
+ extra_args << "arg1"
91
+ extra_args << "arg2"
92
+ extra_args << "arg3"
93
+ end
94
+
95
+ specify "#feed_name is the first extra argument if feed_provider was configured" do
96
+ config_hash['run']['feed_provider'] = "foo"
97
+ expect(config.feed_name).to eq("arg1")
98
+ end
99
+
100
+ specify "#feed_name is the second extra argument if feed_provider was not configured" do
101
+ config_hash['run'].delete('feed_provider')
102
+ expect(config.feed_name).to eq("arg2")
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ describe "#build" do
110
+ let(:action) { double('action') }
111
+ let(:config) { double('config') }
112
+ let(:feed_registry) { double('feed registry') }
113
+ before :each do
114
+ allow(Threatinator::Actions::Run::Action).to receive(:new).and_return(action)
115
+ allow(builder).to receive(:config).and_return(config)
116
+ allow(builder).to receive(:feed_registry).and_return(feed_registry)
117
+ end
118
+
119
+ let(:result) { builder.build }
120
+
121
+ it "builds an instance of Threatinator::Actions::Run::Action using #feed_registry and #config" do
122
+ expect(Threatinator::Actions::Run::Action).to receive(:new).with(feed_registry, config)
123
+ builder.build
124
+ end
125
+
126
+ it "returns the instance of the action" do
127
+ expect(builder.build).to be(action)
128
+ end
129
+
130
+ end
131
+ end
132
+ end
133
+
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/cli'
3
+ require 'fileutils'
4
+
5
+ shared_context "threatinator commands" do
6
+ let(:action) { double('action') }
7
+ let(:builder) { double('builder') }
8
+
9
+ before :each do
10
+ allow(action_builder_class).to receive(:new).and_return(builder)
11
+ allow(builder).to receive(:build).and_return(action)
12
+ allow(action).to receive(:exec)
13
+ end
14
+
15
+ end
16
+ shared_examples_for "a threatinator command" do
17
+ context '--feed_search.path=foo/bar' do
18
+ before :each do
19
+ global_args << '--feed_search.path=foo/bar'
20
+ Threatinator::CLI.process!(args)
21
+ end
22
+
23
+ it "generates the proper config hash" do
24
+ expect(action_builder_class).to have_received(:new) do |opts, args, *extra|
25
+ expect(opts).to match(
26
+ {
27
+ 'feed_search' => {
28
+ 'exclude_default' => false,
29
+ 'path' => ['foo/bar']
30
+ }
31
+ }
32
+ )
33
+ expect(args).to eq([])
34
+ end
35
+ end
36
+ end
37
+
38
+ context '--feed_search.path=foo/bar,woof/bark' do
39
+ before :each do
40
+ global_args << '--feed_search.path=foo/bar,woof/bark'
41
+ Threatinator::CLI.process!(args)
42
+ end
43
+
44
+ it "generates the proper config hash" do
45
+ expect(action_builder_class).to have_received(:new) do |opts, args, *extra|
46
+ expect(opts).to match(
47
+ {
48
+ 'feed_search' => {
49
+ 'exclude_default' => false,
50
+ 'path' => ['foo/bar', 'woof/bark']
51
+ }
52
+ }
53
+ )
54
+ expect(args).to eq([])
55
+ end
56
+ end
57
+ end
58
+
59
+ context '--feed_search.exclude_default' do
60
+ before :each do
61
+ global_args << '--feed_search.exclude_default'
62
+ Threatinator::CLI.process!(args)
63
+ end
64
+
65
+ it "generates the proper config hash" do
66
+ expect(action_builder_class).to have_received(:new).with({
67
+ 'feed_search' => {
68
+ 'exclude_default' => true
69
+ }
70
+ }, [],
71
+ kind_of(Class)
72
+ )
73
+ end
74
+ end
75
+
76
+ context "--help" do
77
+ before :each do
78
+ global_args << '--help'
79
+ @exception = nil
80
+ @exit_code = nil
81
+
82
+ @captured_output = temp_stdout do
83
+ @exit_code = Threatinator::CLI.process!(args)
84
+ end
85
+ end
86
+
87
+ it "should have an exit code of 0" do
88
+ expect(@exit_code).to eq(0)
89
+ end
90
+
91
+ it "should print usage information" do
92
+ expect(@captured_output).to match(/^NAME/)
93
+ end
94
+
95
+ it "should not create an action builder" do
96
+ expect(action_builder_class).not_to have_received(:new)
97
+ end
98
+ end
99
+ end
100
+
101
+ describe Threatinator::CLI do
102
+ let(:global_args) { [] }
103
+ let(:command) { [] }
104
+ let(:command_args) { [] }
105
+ let(:args) { global_args + [ command ] + command_args }
106
+
107
+ describe "list command" do
108
+ let(:command) { 'list' }
109
+ let(:action) { double('action') }
110
+ let(:builder) { double('builder') }
111
+
112
+ before :each do
113
+ allow(Threatinator::CLI::ListActionBuilder).to receive(:new).and_return(builder)
114
+ allow(builder).to receive(:build).and_return(action)
115
+ allow(action).to receive(:exec)
116
+ end
117
+
118
+ it "should create a ListActionBuilder" do
119
+ Threatinator::CLI.process!(args)
120
+ expect(Threatinator::CLI::ListActionBuilder).to have_received(:new).with({"feed_search" => {"exclude_default" => false}}, [])
121
+ end
122
+
123
+ it "should build an action" do
124
+ Threatinator::CLI.process!(args)
125
+ expect(builder).to have_received(:build)
126
+ end
127
+
128
+ it "should execute a list action" do
129
+ Threatinator::CLI.process!(args)
130
+ expect(action).to have_received(:exec)
131
+ end
132
+ end
133
+
134
+ describe "run" do
135
+ let(:action_builder_class) { Threatinator::CLI::RunActionBuilder }
136
+ let(:command) { 'run' }
137
+ include_context "threatinator commands"
138
+
139
+ context "with no additional arguments" do
140
+ it "should create an action builder with no config or args" do
141
+ Threatinator::CLI.process!(args)
142
+ expect(action_builder_class).to have_received(:new).with(
143
+ {
144
+ "feed_search" => {
145
+ "exclude_default" => false
146
+ }
147
+ }, [], kind_of(Class))
148
+ end
149
+ end
150
+
151
+ context "feed_provider feed_name" do
152
+ before :each do
153
+ command_args << 'feed_provider'
154
+ command_args << 'feed_name'
155
+ end
156
+ it "should create an action builder with args feed_provider feed_name" do
157
+ Threatinator::CLI.process!(args)
158
+ expect(action_builder_class).to have_received(:new).with(
159
+ {
160
+ "feed_search" => {
161
+ "exclude_default" => false
162
+ },
163
+ "run" => {
164
+ "feed_provider" => "feed_provider",
165
+ "feed_name" => "feed_name"
166
+ }
167
+ }, [], kind_of(Class)
168
+ )
169
+ end
170
+ end
171
+
172
+ it_should_behave_like "a threatinator command"
173
+ end
174
+ end
175
+
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/config/base'
3
+
4
+ describe Threatinator::Config::Base do
5
+ describe '.properties' do
6
+ class Foobar3 < Threatinator::Config::Base
7
+ attribute :deep1, String, description: "deep prop1"
8
+ attribute :deep2, String, description: "deep prop2"
9
+ end
10
+
11
+ class Foobar2 < Threatinator::Config::Base
12
+ attribute :nested_prop1, String, description: "Nested prop1"
13
+ attribute :nested_prop2, String, description: "Nested prop2"
14
+ attribute :deep, Foobar3
15
+ end
16
+
17
+ class Foobar1 < Threatinator::Config::Base
18
+ attribute :prop1, String, description: "This is prop1"
19
+ attribute :prop2, Boolean, description: "This is prop2"
20
+ attribute :nested1, Foobar2
21
+ attribute :nested2, Foobar2
22
+ end
23
+
24
+ it "should return a hash of all properties and nested properties" do
25
+ expect(Foobar1.properties).to match({
26
+ "prop1" => ["This is prop1", Axiom::Types::String],
27
+ "prop2" => ["This is prop2", Axiom::Types::Boolean],
28
+ "nested1.nested_prop1" => ["Nested prop1", Axiom::Types::String],
29
+ "nested1.nested_prop2" => ["Nested prop2", Axiom::Types::String],
30
+ "nested1.deep.deep1" => ["deep prop1", Axiom::Types::String],
31
+ "nested1.deep.deep2" => ["deep prop2", Axiom::Types::String],
32
+ "nested2.nested_prop1" => ["Nested prop1", Axiom::Types::String],
33
+ "nested2.nested_prop2" => ["Nested prop2", Axiom::Types::String],
34
+ "nested2.deep.deep1" => ["deep prop1", Axiom::Types::String],
35
+ "nested2.deep.deep2" => ["deep prop2", Axiom::Types::String]
36
+ })
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/config/feed_search'
3
+
4
+ describe Threatinator::Config::FeedSearch do
5
+ describe "#path" do
6
+ context "when :path not specified" do
7
+ it "returns an empty array" do
8
+ x = described_class.new
9
+ expect(x.path).to eq([])
10
+ end
11
+ end
12
+ context "when :path is an array of strings" do
13
+ it "returns the array of strings" do
14
+ x = described_class.new(path: ['foo', 'bar'])
15
+ expect(x.path).to eq(['foo', 'bar'])
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "#exclude_default" do
21
+ context "when :exclude_default is not specified" do
22
+ it "returns false" do
23
+ expect(described_class.new.exclude_default).to eq(false)
24
+ end
25
+ end
26
+
27
+ context "when :exclude_default is set to true" do
28
+ it "returns true" do
29
+ x = described_class.new(exclude_default: true)
30
+ expect(x.exclude_default).to eq(true)
31
+ end
32
+ end
33
+
34
+ context "when :exclude_default is set to false" do
35
+ it "returns false" do
36
+ x = described_class.new(exclude_default: false)
37
+ expect(x.exclude_default).to eq(false)
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "#search_path" do
43
+ context "when neither :path nor :exclude_default are supplied" do
44
+ it "returns an array containing the default search path" do
45
+ x = described_class.new
46
+ expect(x.search_path).to eq([described_class::DEFAULT_FEED_PATH])
47
+ end
48
+ end
49
+
50
+ context "when :path is an array of paths" do
51
+ let(:paths) { ["foo", "bar"] }
52
+ let(:config) { described_class.new(path: paths) }
53
+ specify "the first search paths are those specified by :path" do
54
+ expect(config.search_path[0..1]).to eq(['foo', 'bar'])
55
+ end
56
+
57
+ context "when :exclude_default is not specified" do
58
+ specify "the default search path is appended" do
59
+ expect(config.search_path[-1]).to eq(described_class::DEFAULT_FEED_PATH)
60
+ end
61
+ end
62
+ context "when :exclude_default is false" do
63
+ let(:config) { described_class.new(path: paths, exclude_default: false) }
64
+ specify "the default search path is appended" do
65
+ expect(config.search_path[-1]).to eq(described_class::DEFAULT_FEED_PATH)
66
+ end
67
+ end
68
+ context "when :exclude_default is true" do
69
+ let(:config) { described_class.new(path: paths, exclude_default: true) }
70
+ specify "the default search path is not appended" do
71
+ expect(config.search_path[-1]).not_to eq(described_class::DEFAULT_FEED_PATH)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/decoders/gzip'
3
+ require 'stringio'
4
+ require 'zlib'
5
+
6
+ describe Threatinator::Decoders::Gzip do
7
+ let(:encode_data_proc) {
8
+ lambda do |data|
9
+ sio = StringIO.new
10
+ sio.set_encoding("binary")
11
+ gz = Zlib::GzipWriter.new(sio)
12
+ gz.write(data)
13
+ gz.close
14
+ sio.string
15
+ end
16
+ }
17
+
18
+ it_should_behave_like "a decoder" do
19
+ let(:decoder_opts) { {} }
20
+ end
21
+
22
+ let(:uncompressed_data) {
23
+ ret = "".encode("binary")
24
+ '!'.upto('~') { |a| '!'.upto('~') { |b| ret << "#{a}#{b}" } }
25
+ ret
26
+ }
27
+
28
+ let(:compressed_data) {
29
+ encode_data_proc.call(uncompressed_data)
30
+ }
31
+
32
+ let(:decoder) { Threatinator::Decoders::Gzip.new }
33
+
34
+
35
+ context "normal operation" do
36
+ it "should decompress a Gzip compressed stream" do
37
+ encoded_io = StringIO.new(compressed_data)
38
+ expect(decoder.decode(encoded_io).read).to eq(uncompressed_data)
39
+ end
40
+ end
41
+
42
+ context "handling truncated data" do
43
+ let(:truncated_data) {
44
+ data = compressed_data
45
+ data_len = data.length / 2
46
+ data[0..(data_len - 1)]
47
+ }
48
+
49
+ it_should_behave_like "a decoder encountering an error during decoding" do
50
+ let(:input_io) {StringIO.new(truncated_data)}
51
+ end
52
+ end
53
+
54
+ context "handling a gzip stream with no footer" do
55
+ let(:missing_footer_data) {
56
+ compressed_data[0..-9] # knock off the footer, which is 8 bytes long
57
+ }
58
+
59
+ it_should_behave_like "a decoder encountering an error during decoding" do
60
+ let(:input_io) {StringIO.new(missing_footer_data)}
61
+ end
62
+ end
63
+
64
+ context "handling a gzip with an invalid footer" do
65
+ let(:missing_footer_data) {
66
+ ret = compressed_data
67
+ ret[-9..-1] = "\0\0\0\0\0\0\0\0"
68
+ ret
69
+ }
70
+
71
+ it_should_behave_like "a decoder encountering an error during decoding" do
72
+ let(:input_io) { StringIO.new(missing_footer_data) }
73
+ end
74
+ end
75
+ end