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,169 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/feed'
3
+
4
+ describe Threatinator::Feed do
5
+ let (:provider) { 'FakeSecureCo' }
6
+ let (:name) { 'MaliciousDataFeed' }
7
+ let(:fetcher_io) { double("io") }
8
+ let(:parser_block) { lambda {} }
9
+ let(:filter_builders) { [] }
10
+ let(:decoder_builders) { [] }
11
+ let(:fetcher_builder) { lambda { FeedSpec::Fetcher.new({}) } }
12
+ let(:parser_builder) { lambda { FeedSpec::Parser.new({}) { } } }
13
+
14
+ let(:feed_opts) {
15
+ {
16
+ :provider => provider,
17
+ :name => name,
18
+ :parser_block => parser_block,
19
+ :fetcher_builder => fetcher_builder,
20
+ :parser_builder => parser_builder,
21
+ :filter_builders => filter_builders,
22
+ :decoder_builders => filter_builders,
23
+ }
24
+ }
25
+
26
+ shared_examples_for "a field with an invalid value" do |value|
27
+ it "should raise InvalidAttributeError if it is a #{value.class}" do
28
+ expect {
29
+ described_class.new(feed_opts.merge(field => value))
30
+ }.to raise_error(Threatinator::Exceptions::InvalidAttributeError)
31
+ end
32
+ end
33
+
34
+ shared_examples_for "a field with a valid value" do |value|
35
+ it "should not raise any errors when set to a #{value.class}" do
36
+ expect {
37
+ described_class.new(feed_opts.merge(field => value))
38
+ }.not_to raise_error
39
+ end
40
+ end
41
+
42
+ shared_examples_for "a field that is required" do
43
+ it "is required" do
44
+ feed_opts.delete(field)
45
+ expect { described_class.new(feed_opts) }.to raise_error(Threatinator::Exceptions::InvalidAttributeError)
46
+ end
47
+ end
48
+
49
+ shared_examples_for "a field with a default" do |value|
50
+ it "should default to #{value.inspect}" do
51
+ feed_opts.delete(field)
52
+ feed = described_class.new(feed_opts)
53
+ expect(feed.send(field)).to eq(value)
54
+ end
55
+ end
56
+
57
+ shared_examples_for "a field that is immutable" do
58
+ it "should be immutable" do
59
+ feed = described_class.new(feed_opts)
60
+ expect(feed.send(field)).not_to be(feed.send(field))
61
+ end
62
+ end
63
+
64
+ describe ":provider" do
65
+ let(:field) { :provider }
66
+ include_examples "a field that is required"
67
+ include_examples "a field that is immutable"
68
+ include_examples "a field with a valid value", "asdf"
69
+ include_examples "a field with an invalid value", 1234
70
+ include_examples "a field with an invalid value", :asdf
71
+ include_examples "a field with an invalid value", []
72
+ include_examples "a field with an invalid value", {}
73
+ end
74
+
75
+ describe ":name" do
76
+ let(:field) { :name }
77
+ include_examples "a field that is required", :name
78
+ include_examples "a field that is immutable"
79
+ include_examples "a field with a valid value", "asdf"
80
+ include_examples "a field with an invalid value", 1234
81
+ include_examples "a field with an invalid value", :asdf
82
+ include_examples "a field with an invalid value", []
83
+ include_examples "a field with an invalid value", {}
84
+ end
85
+
86
+ describe ":fetcher_builder" do
87
+ let(:field) { :fetcher_builder}
88
+ include_examples "a field that is required", :fetcher_builder
89
+ include_examples "a field with a valid value", lambda { }
90
+ include_examples "a field with an invalid value", Class.new
91
+ include_examples "a field with an invalid value", 1234
92
+ include_examples "a field with an invalid value", :asdf
93
+ include_examples "a field with an invalid value", []
94
+ include_examples "a field with an invalid value", {}
95
+ end
96
+
97
+ describe ":parser_builder" do
98
+ let(:field) { :parser_builder }
99
+ include_examples "a field that is required", :parser_builder
100
+ include_examples "a field with a valid value", lambda { }
101
+ include_examples "a field with an invalid value", Class.new
102
+ include_examples "a field with an invalid value", 1234
103
+ include_examples "a field with an invalid value", :asdf
104
+ include_examples "a field with an invalid value", []
105
+ include_examples "a field with an invalid value", {}
106
+ end
107
+
108
+ describe ":filter_builders" do
109
+ let(:field) { :filter_builders}
110
+ include_examples "a field with a default", []
111
+ include_examples "a field with a valid value", []
112
+ include_examples "a field with a valid value", [ lambda { } ]
113
+ include_examples "a field that is immutable"
114
+ include_examples "a field with an invalid value", Class.new
115
+ include_examples "a field with an invalid value", 1234
116
+ include_examples "a field with an invalid value", :asdf
117
+ include_examples "a field with an invalid value", [1,2,3]
118
+ include_examples "a field with an invalid value", {}
119
+ end
120
+
121
+ describe ":decoder_builders" do
122
+ let(:field) { :decoder_builders}
123
+ include_examples "a field with a default", []
124
+ include_examples "a field with a valid value", []
125
+ include_examples "a field with a valid value", [ lambda { } ]
126
+ include_examples "a field that is immutable"
127
+ include_examples "a field with an invalid value", Class.new
128
+ include_examples "a field with an invalid value", 1234
129
+ include_examples "a field with an invalid value", :asdf
130
+ include_examples "a field with an invalid value", [1,2,3]
131
+ include_examples "a field with an invalid value", {}
132
+ end
133
+
134
+ describe ":parser_block" do
135
+ let(:field) { :parser_block }
136
+ include_examples "a field that is required", :parser_block
137
+ include_examples "a field with a valid value", lambda {}
138
+ include_examples "a field with an invalid value", 1234
139
+ include_examples "a field with an invalid value", :asdf
140
+ include_examples "a field with an invalid value", []
141
+ end
142
+
143
+ context "when initialized with required fields" do
144
+ let (:feed) do
145
+ described_class.new(feed_opts)
146
+ end
147
+
148
+ describe "#name" do
149
+ it "should return the name" do
150
+ expect(feed.name).to eq(name)
151
+ end
152
+ end
153
+
154
+ describe "#provider" do
155
+ it "should return the provider" do
156
+ expect(feed.provider).to eq(provider)
157
+ end
158
+ end
159
+
160
+ describe "#parser_block" do
161
+ it "should return the parser_block" do
162
+ expect(feed.parser_block).to eq(parser_block)
163
+ end
164
+ end
165
+
166
+ end
167
+ end
168
+
169
+
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/fetcher'
3
+
4
+ describe Threatinator::Fetcher do
5
+ let(:fetcher) { Threatinator::Fetcher.new }
6
+ describe "#fetch" do
7
+ it "should raise NotImplementedError because it's not implemented" do
8
+ expect {fetcher.fetch}.to raise_error(NotImplementedError)
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/fetchers/http'
3
+
4
+ describe Threatinator::Fetchers::Http do
5
+ let(:url) { "http://foobar.com/bla.json" }
6
+ let(:fetcher_builder) { lambda { described_class.new(url: url) } }
7
+ let(:fetcher_builder_different) { lambda { described_class.new(url: "http://foobar.com/sdf.json") } }
8
+ let(:fetcher) { fetcher_builder.call() }
9
+
10
+ it_should_behave_like "a fetcher" do
11
+ before :each do
12
+ stub_request(:get, url).to_return(:body => expected_data)
13
+ end
14
+ end
15
+
16
+ describe "#url" do
17
+ it "should return the value of the URL" do
18
+ expect(fetcher.url).to eq(url)
19
+ end
20
+ end
21
+
22
+ [404, 500].each do |status_code|
23
+ context "when an HTTP response has a status code of #{status_code}" do
24
+ it_should_behave_like "a #fetch call that failed" do
25
+ before :each do
26
+ stub_request(:get, url)
27
+ .to_return(:status => status_code)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/filter'
3
+
4
+ describe Threatinator::Filter do
5
+ let(:filter) { Threatinator::Filter.new }
6
+ describe "#filter?(record)" do
7
+ it "should raise NotImplementedError because it's not implemented" do
8
+ expect {filter.filter?(1234)}.to raise_error(NotImplementedError)
9
+ end
10
+ end
11
+ end
12
+
13
+
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/record'
3
+ require 'threatinator/filters/block'
4
+
5
+ describe Threatinator::Filters::Block do
6
+ it_should_behave_like "a filter" do
7
+ let(:filter_block) {
8
+ lambda do |record|
9
+ record.data =~ /^FILTERME$/
10
+ end
11
+ }
12
+ let(:filter) { described_class.new(filter_block) }
13
+ let(:should_filter) { Threatinator::Record.new("FILTERME") }
14
+ let(:shouldnt_filter) { Threatinator::Record.new("I'm OK!") }
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/record'
3
+ require 'threatinator/filters/comments'
4
+
5
+ describe Threatinator::Filters::Comments do
6
+ it_should_behave_like "a filter" do
7
+ let(:filter) { described_class.new() }
8
+ let(:should_filter) { Threatinator::Record.new("# Here's my comment") }
9
+ let(:shouldnt_filter) { Threatinator::Record.new("I'm OK # wooo!") }
10
+ end
11
+ end
12
+
13
+
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/record'
3
+ require 'threatinator/filters/whitespace'
4
+
5
+ describe Threatinator::Filters::Whitespace do
6
+ it_should_behave_like "a filter" do
7
+ let(:filter) { described_class.new() }
8
+ let(:should_filter) { Threatinator::Record.new(" ") }
9
+ let(:shouldnt_filter) { Threatinator::Record.new(" I'm OK!") }
10
+ end
11
+ end
12
+
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/logger'
3
+ require 'threatinator/config/logger'
4
+
5
+ describe Threatinator::Logger do
6
+ before :each do
7
+ @orig_level = Threatinator::Logger.level
8
+ end
9
+
10
+ after :each do
11
+ Threatinator::Logger.level = @orig_level
12
+ end
13
+
14
+ describe ".configure_logger(config)" do
15
+ let(:config) { Threatinator::Config::Logger.new }
16
+ it "sets the logging level to that specified by config.level" do
17
+ Threatinator::Logger.level = Threatinator::Logger::Levels::FATAL
18
+ config.level = "DEBUG"
19
+ Threatinator::Logger.configure_logger(config)
20
+ expect(Threatinator::Logger.level).to eq(Threatinator::Logger::Levels::DEBUG)
21
+ end
22
+
23
+ it "warns when an unknown logging level is provided" do
24
+ config.level = "FOO"
25
+ expect(Threatinator::Logger.default_logger).to receive(:warn).with(/Ignoring unknown logging level:/)
26
+ Threatinator::Logger.configure_logger(config)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/model/observables/fqdn_collection'
3
+
4
+ describe Threatinator::Model::Observables::FqdnCollection do
5
+ it_behaves_like "a model collection" do
6
+ def generate_ten_valid_members
7
+ ret = []
8
+ 1.upto(10) do |i|
9
+ ret << "domain#{i}.com"
10
+ end
11
+ ret
12
+ end
13
+
14
+ def generate_invalid_members
15
+ [1234, :foobar]
16
+ end
17
+ end
18
+
19
+ let(:collection) { described_class.new }
20
+
21
+ describe "#valid_member?(v)" do
22
+ context "when provided a valid FQDN string" do
23
+ it "returns true" do
24
+ expect(collection.valid_member?("yahoo.com")).to eq(true)
25
+ end
26
+ end
27
+
28
+ context "when provided an invalid FQDN string" do
29
+ it "returns false" do
30
+ expect(collection.valid_member?("yahoo..com")).to eq(false)
31
+ end
32
+ end
33
+
34
+ context "when provided something other than a string" do
35
+ it "returns false" do
36
+ expect(collection.valid_member?(:asdf)).to eq(false)
37
+ expect(collection.valid_member?(1234)).to eq(false)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/model/observables/ipv4_collection'
3
+ require 'threatinator/model/observables/ipv4'
4
+
5
+ describe Threatinator::Model::Observables::Ipv4Collection do
6
+ it_behaves_like "a model collection" do
7
+ def generate_ten_valid_members
8
+ ret = []
9
+ 1.upto(10) do |i|
10
+ ret << build(:ipv4, ipv4: "1.2.3.#{i}")
11
+ end
12
+ ret
13
+ end
14
+
15
+ def generate_invalid_members
16
+ [1234, :foobar]
17
+ end
18
+ end
19
+
20
+ let(:collection) { described_class.new }
21
+
22
+ describe "#valid_member?(v)" do
23
+ context "when provided an Ipv4 observable" do
24
+ it "returns true" do
25
+ ipv4 = build(:ipv4, ipv4: "1.2.3.4")
26
+ expect(collection.valid_member?(ipv4)).to eq(true)
27
+ end
28
+ end
29
+
30
+ context "when provided something other than an Ipv4 observable" do
31
+ it "returns false" do
32
+ expect(collection.valid_member?("1.2.3.257")).to eq(false)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/model/observables/ipv4'
3
+
4
+ describe Threatinator::Model::Observables::Ipv4 do
5
+ let(:ipv4_opts) { {} }
6
+
7
+ describe ":ipv4" do
8
+ it "is required" do
9
+ ipv4_opts.delete(:ipv4)
10
+ expect {
11
+ described_class.new(ipv4_opts)
12
+ }.to raise_error(Threatinator::Exceptions::InvalidAttributeError)
13
+ end
14
+
15
+ it "must be an IP::V4 object" do
16
+ opts1 = ipv4_opts.dup
17
+ opts1[:ipv4] = '1.2.3.4'
18
+ expect {
19
+ described_class.new(opts1)
20
+ }.to raise_error(Threatinator::Exceptions::InvalidAttributeError)
21
+
22
+ opts2 = ipv4_opts.dup
23
+ opts2[:ipv4] = IP::V4.parse('1.2.3.4')
24
+ expect {
25
+ described_class.new(opts2)
26
+ }.not_to raise_error
27
+ end
28
+
29
+ it "must have a 32 bit prefix" do
30
+ opts1 = ipv4_opts.dup
31
+ opts1[:ipv4] = IP::V4.parse('10.1.1.0/24')
32
+ expect {
33
+ described_class.new(opts1)
34
+ }.to raise_error(Threatinator::Exceptions::InvalidAttributeError)
35
+
36
+ opts2 = ipv4_opts.dup
37
+ opts2[:ipv4] = IP::V4.parse('10.1.1.0/32')
38
+ expect {
39
+ described_class.new(opts2)
40
+ }.not_to raise_error
41
+ end
42
+
43
+
44
+ it "sets the value of #ipv4" do
45
+ ipv4 = IP::V4.parse('1.2.3.4')
46
+ ipv4_opts[:ipv4] = ipv4
47
+ o = described_class.new(ipv4_opts)
48
+ expect(o.ipv4).to be(ipv4)
49
+ end
50
+ end
51
+
52
+ describe "#==(other)" do
53
+ it "returns true when compared to an identically configured event" do
54
+ opts1 = ipv4_opts.dup
55
+ opts1[:ipv4] = IP::V4.parse('1.2.3.4')
56
+ opts2 = ipv4_opts.dup
57
+ opts2[:ipv4] = IP::V4.parse('1.2.3.4')
58
+ o1 = described_class.new(opts1)
59
+ o2 = described_class.new(opts2)
60
+ expect(o1).to be == o2
61
+ end
62
+
63
+ it "returns false when compared to differently configured event" do
64
+ opts1 = ipv4_opts.dup
65
+ opts1[:ipv4] = IP::V4.parse('1.2.3.4')
66
+ opts2 = ipv4_opts.dup
67
+ opts2[:ipv4] = IP::V4.parse('8.8.8.8')
68
+ o1 = described_class.new(opts1)
69
+ o2 = described_class.new(opts2)
70
+ expect(o1).not_to be == o2
71
+ end
72
+ end
73
+
74
+ end
75
+
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/model/observables/url_collection'
3
+ require 'addressable/uri'
4
+
5
+ describe Threatinator::Model::Observables::UrlCollection do
6
+ it_behaves_like "a model collection" do
7
+ def generate_ten_valid_members
8
+ ret = []
9
+ 1.upto(10) do |i|
10
+ ret << ::Addressable::URI.parse("http://foobar#{i}.com")
11
+ end
12
+ ret
13
+ end
14
+
15
+ def generate_invalid_members
16
+ [
17
+ 1234,
18
+ :foobar,
19
+ 'http://yahoo.com',
20
+ ::Addressable::URI.parse('/foo/bar')
21
+ ]
22
+ end
23
+ end
24
+
25
+ let(:collection) { described_class.new }
26
+
27
+ describe "#valid_member?(v)" do
28
+ it "returns true when an absolute Addressable::URI" do
29
+ url = Addressable::URI.parse('http://yahoo.com')
30
+ expect(collection.valid_member?(url)).to eq(true)
31
+ end
32
+
33
+ it "returns false when the Addressable::URI is relative" do
34
+ url = Addressable::URI.parse('/foo/bar')
35
+ expect(collection.valid_member?(url)).to eq(false)
36
+ end
37
+
38
+ it "returns false when not an Addressable::URI" do
39
+ expect(collection.valid_member?('http://yahoo.com')).to eq(false)
40
+ expect(collection.valid_member?(:foobar)).to eq(false)
41
+ expect(collection.valid_member?(nil)).to eq(false)
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/model/validations/type'
3
+
4
+ describe Threatinator::Model::Validations::TypeValidator do
5
+ before :each do
6
+ module Examples
7
+ class Person
8
+ include ActiveModel::Validations
9
+ include Threatinator::Model::Validations
10
+ attr_accessor :name, :age
11
+ end
12
+ end
13
+ end
14
+
15
+ after :each do
16
+ Examples::Person.clear_validators!
17
+ end
18
+
19
+ it "validates that the value is an instance of the class specified by :type" do
20
+ Examples::Person.validates :name, type: String
21
+ person = Examples::Person.new
22
+ expect(person).not_to be_valid
23
+
24
+ person.name = :asdf
25
+ expect(person).not_to be_valid
26
+
27
+ person.name = "Mike"
28
+ expect(person).to be_valid
29
+
30
+ Examples::Person.validates :age, type: Integer
31
+ expect(person).not_to be_valid
32
+ person.age = :eight
33
+ expect(person).not_to be_valid
34
+ person.age = 8
35
+ expect(person).to be_valid
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ require 'threatinator/parser'
3
+
4
+ describe Threatinator::Parser do
5
+ let(:parser) { Threatinator::Parser.new() }
6
+ describe "#run" do
7
+ it "should raise NotImplementedError because it's not implemented" do
8
+ expect { |b| parser.run(double("io"), &b) }.to raise_error(NotImplementedError)
9
+ end
10
+ end
11
+ end
12
+
13
+