active_stix 0.1.21

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 (289) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/config/active_stix_manifest.js +2 -0
  6. data/app/assets/javascripts/active_stix/application.js +15 -0
  7. data/app/assets/javascripts/active_stix/artifacts.js +2 -0
  8. data/app/assets/javascripts/active_stix/attack_patterns.js +2 -0
  9. data/app/assets/javascripts/active_stix/bcc_refs.js +2 -0
  10. data/app/assets/javascripts/active_stix/bundled_objects.js +2 -0
  11. data/app/assets/javascripts/active_stix/bundles.js +2 -0
  12. data/app/assets/javascripts/active_stix/campaigns.js +2 -0
  13. data/app/assets/javascripts/active_stix/course_of_actions.js +2 -0
  14. data/app/assets/javascripts/active_stix/cyber_observables.js +2 -0
  15. data/app/assets/javascripts/active_stix/email_messages.js +2 -0
  16. data/app/assets/javascripts/active_stix/external_references.js +2 -0
  17. data/app/assets/javascripts/active_stix/files.js +2 -0
  18. data/app/assets/javascripts/active_stix/identities.js +2 -0
  19. data/app/assets/javascripts/active_stix/indicator_labels.js +2 -0
  20. data/app/assets/javascripts/active_stix/indicators.js +2 -0
  21. data/app/assets/javascripts/active_stix/intrusion_sets.js +2 -0
  22. data/app/assets/javascripts/active_stix/kill_chain_phases.js +2 -0
  23. data/app/assets/javascripts/active_stix/kill_chains.js +2 -0
  24. data/app/assets/javascripts/active_stix/malwares.js +2 -0
  25. data/app/assets/javascripts/active_stix/marking_definitions.js +2 -0
  26. data/app/assets/javascripts/active_stix/observed_data.js +2 -0
  27. data/app/assets/javascripts/active_stix/open_vocabularies.js +2 -0
  28. data/app/assets/javascripts/active_stix/phases.js +2 -0
  29. data/app/assets/javascripts/active_stix/recipients.js +2 -0
  30. data/app/assets/javascripts/active_stix/relationships.js +2 -0
  31. data/app/assets/javascripts/active_stix/reports.js +2 -0
  32. data/app/assets/javascripts/active_stix/threat_actors.js +2 -0
  33. data/app/assets/javascripts/active_stix/tools.js +2 -0
  34. data/app/assets/javascripts/active_stix/urls.js +2 -0
  35. data/app/assets/javascripts/active_stix/users.js +2 -0
  36. data/app/assets/stylesheets/active_stix/application.css +15 -0
  37. data/app/assets/stylesheets/active_stix/artifacts.css +4 -0
  38. data/app/assets/stylesheets/active_stix/attack_patterns.css +4 -0
  39. data/app/assets/stylesheets/active_stix/bcc_refs.css +4 -0
  40. data/app/assets/stylesheets/active_stix/bundled_objects.css +4 -0
  41. data/app/assets/stylesheets/active_stix/bundles.css +4 -0
  42. data/app/assets/stylesheets/active_stix/campaigns.css +4 -0
  43. data/app/assets/stylesheets/active_stix/course_of_actions.css +4 -0
  44. data/app/assets/stylesheets/active_stix/cyber_observables.css +4 -0
  45. data/app/assets/stylesheets/active_stix/email_messages.css +4 -0
  46. data/app/assets/stylesheets/active_stix/external_references.css +4 -0
  47. data/app/assets/stylesheets/active_stix/files.css +4 -0
  48. data/app/assets/stylesheets/active_stix/identities.css +4 -0
  49. data/app/assets/stylesheets/active_stix/indicator_labels.css +4 -0
  50. data/app/assets/stylesheets/active_stix/indicators.css +4 -0
  51. data/app/assets/stylesheets/active_stix/intrusion_sets.css +4 -0
  52. data/app/assets/stylesheets/active_stix/kill_chain_phases.css +4 -0
  53. data/app/assets/stylesheets/active_stix/kill_chains.css +4 -0
  54. data/app/assets/stylesheets/active_stix/malwares.css +4 -0
  55. data/app/assets/stylesheets/active_stix/marking_definitions.css +4 -0
  56. data/app/assets/stylesheets/active_stix/observed_data.css +4 -0
  57. data/app/assets/stylesheets/active_stix/open_vocabularies.css +4 -0
  58. data/app/assets/stylesheets/active_stix/phases.css +4 -0
  59. data/app/assets/stylesheets/active_stix/recipients.css +4 -0
  60. data/app/assets/stylesheets/active_stix/relationships.css +4 -0
  61. data/app/assets/stylesheets/active_stix/reports.css +4 -0
  62. data/app/assets/stylesheets/active_stix/threat_actors.css +4 -0
  63. data/app/assets/stylesheets/active_stix/tools.css +4 -0
  64. data/app/assets/stylesheets/active_stix/urls.css +4 -0
  65. data/app/assets/stylesheets/active_stix/users.css +4 -0
  66. data/app/assets/stylesheets/scaffold.css +80 -0
  67. data/app/controllers/active_stix/application_controller.rb +5 -0
  68. data/app/controllers/active_stix/artifacts_controller.rb +62 -0
  69. data/app/controllers/active_stix/attack_patterns_controller.rb +27 -0
  70. data/app/controllers/active_stix/bcc_refs_controller.rb +62 -0
  71. data/app/controllers/active_stix/bundled_objects_controller.rb +62 -0
  72. data/app/controllers/active_stix/bundles_controller.rb +11 -0
  73. data/app/controllers/active_stix/campaigns_controller.rb +74 -0
  74. data/app/controllers/active_stix/course_of_actions_controller.rb +62 -0
  75. data/app/controllers/active_stix/cyber_observables_controller.rb +62 -0
  76. data/app/controllers/active_stix/email_addresses_controller.rb +74 -0
  77. data/app/controllers/active_stix/email_messages_controller.rb +26 -0
  78. data/app/controllers/active_stix/external_references_controller.rb +62 -0
  79. data/app/controllers/active_stix/files_controller.rb +74 -0
  80. data/app/controllers/active_stix/identities_controller.rb +128 -0
  81. data/app/controllers/active_stix/indicator_labels_controller.rb +62 -0
  82. data/app/controllers/active_stix/indicators_controller.rb +62 -0
  83. data/app/controllers/active_stix/intrusion_sets_controller.rb +62 -0
  84. data/app/controllers/active_stix/kill_chain_phases_controller.rb +62 -0
  85. data/app/controllers/active_stix/kill_chains_controller.rb +62 -0
  86. data/app/controllers/active_stix/malwares_controller.rb +62 -0
  87. data/app/controllers/active_stix/marking_definitions_controller.rb +62 -0
  88. data/app/controllers/active_stix/observed_data_controller.rb +62 -0
  89. data/app/controllers/active_stix/open_vocabularies_controller.rb +62 -0
  90. data/app/controllers/active_stix/phases_controller.rb +62 -0
  91. data/app/controllers/active_stix/recipients_controller.rb +62 -0
  92. data/app/controllers/active_stix/relationships_controller.rb +62 -0
  93. data/app/controllers/active_stix/reports_controller.rb +62 -0
  94. data/app/controllers/active_stix/threat_actors_controller.rb +75 -0
  95. data/app/controllers/active_stix/tools_controller.rb +62 -0
  96. data/app/controllers/active_stix/urls_controller.rb +62 -0
  97. data/app/controllers/active_stix/user_accounts_controller.rb +74 -0
  98. data/app/controllers/active_stix/users_controller.rb +62 -0
  99. data/app/helpers/active_stix/application_helper.rb +4 -0
  100. data/app/helpers/active_stix/artifacts_helper.rb +4 -0
  101. data/app/helpers/active_stix/attack_patterns_helper.rb +4 -0
  102. data/app/helpers/active_stix/bcc_refs_helper.rb +4 -0
  103. data/app/helpers/active_stix/bundled_objects_helper.rb +4 -0
  104. data/app/helpers/active_stix/bundles_helper.rb +4 -0
  105. data/app/helpers/active_stix/campaigns_helper.rb +4 -0
  106. data/app/helpers/active_stix/course_of_actions_helper.rb +4 -0
  107. data/app/helpers/active_stix/cyber_observables_helper.rb +4 -0
  108. data/app/helpers/active_stix/email_messages_helper.rb +4 -0
  109. data/app/helpers/active_stix/external_references_helper.rb +4 -0
  110. data/app/helpers/active_stix/files_helper.rb +4 -0
  111. data/app/helpers/active_stix/identities_helper.rb +4 -0
  112. data/app/helpers/active_stix/indicator_labels_helper.rb +4 -0
  113. data/app/helpers/active_stix/indicators_helper.rb +4 -0
  114. data/app/helpers/active_stix/intrusion_sets_helper.rb +4 -0
  115. data/app/helpers/active_stix/kill_chain_phases_helper.rb +4 -0
  116. data/app/helpers/active_stix/kill_chains_helper.rb +4 -0
  117. data/app/helpers/active_stix/malwares_helper.rb +4 -0
  118. data/app/helpers/active_stix/marking_definitions_helper.rb +4 -0
  119. data/app/helpers/active_stix/observed_data_helper.rb +4 -0
  120. data/app/helpers/active_stix/open_vocabularies_helper.rb +4 -0
  121. data/app/helpers/active_stix/phases_helper.rb +4 -0
  122. data/app/helpers/active_stix/recipients_helper.rb +4 -0
  123. data/app/helpers/active_stix/relationships_helper.rb +4 -0
  124. data/app/helpers/active_stix/reports_helper.rb +4 -0
  125. data/app/helpers/active_stix/threat_actors_helper.rb +4 -0
  126. data/app/helpers/active_stix/tools_helper.rb +4 -0
  127. data/app/helpers/active_stix/urls_helper.rb +4 -0
  128. data/app/helpers/active_stix/users_helper.rb +4 -0
  129. data/app/jobs/active_stix/application_job.rb +4 -0
  130. data/app/mailers/active_stix/application_mailer.rb +6 -0
  131. data/app/models/active_stix/application_record.rb +5 -0
  132. data/app/models/active_stix/artifact.rb +23 -0
  133. data/app/models/active_stix/attack_pattern.rb +150 -0
  134. data/app/models/active_stix/bcc_ref.rb +6 -0
  135. data/app/models/active_stix/bundle.rb +108 -0
  136. data/app/models/active_stix/bundled_object.rb +4 -0
  137. data/app/models/active_stix/campaign.rb +65 -0
  138. data/app/models/active_stix/cc_ref.rb +6 -0
  139. data/app/models/active_stix/course_of_action.rb +54 -0
  140. data/app/models/active_stix/cyber_observable.rb +4 -0
  141. data/app/models/active_stix/email_address.rb +27 -0
  142. data/app/models/active_stix/email_message.rb +339 -0
  143. data/app/models/active_stix/external_reference.rb +48 -0
  144. data/app/models/active_stix/file.rb +2 -0
  145. data/app/models/active_stix/identity.rb +141 -0
  146. data/app/models/active_stix/indicator.rb +58 -0
  147. data/app/models/active_stix/indicator_label.rb +4 -0
  148. data/app/models/active_stix/intrusion_set.rb +69 -0
  149. data/app/models/active_stix/kill_chain.rb +7 -0
  150. data/app/models/active_stix/kill_chain_phase.rb +6 -0
  151. data/app/models/active_stix/label.rb +17 -0
  152. data/app/models/active_stix/label_malware.rb +4 -0
  153. data/app/models/active_stix/label_report.rb +4 -0
  154. data/app/models/active_stix/label_tool.rb +4 -0
  155. data/app/models/active_stix/malware.rb +98 -0
  156. data/app/models/active_stix/marking_definition.rb +21 -0
  157. data/app/models/active_stix/markup.rb +6 -0
  158. data/app/models/active_stix/object_marking.rb +11 -0
  159. data/app/models/active_stix/observed_datum.rb +67 -0
  160. data/app/models/active_stix/open_vocabulary.rb +8 -0
  161. data/app/models/active_stix/phase.rb +41 -0
  162. data/app/models/active_stix/recipient.rb +4 -0
  163. data/app/models/active_stix/reference_item.rb +4 -0
  164. data/app/models/active_stix/relationship.rb +95 -0
  165. data/app/models/active_stix/report.rb +93 -0
  166. data/app/models/active_stix/report_object.rb +9 -0
  167. data/app/models/active_stix/threat_actor.rb +139 -0
  168. data/app/models/active_stix/to_ref.rb +6 -0
  169. data/app/models/active_stix/tool.rb +112 -0
  170. data/app/models/active_stix/url.rb +15 -0
  171. data/app/models/active_stix/user.rb +4 -0
  172. data/app/models/active_stix/user_account.rb +3 -0
  173. data/app/views/active_stix/artifacts/_form.html.erb +57 -0
  174. data/app/views/active_stix/artifacts/edit.html.erb +6 -0
  175. data/app/views/active_stix/artifacts/index.html.erb +41 -0
  176. data/app/views/active_stix/artifacts/new.html.erb +5 -0
  177. data/app/views/active_stix/artifacts/show.html.erb +44 -0
  178. data/app/views/active_stix/attack_patterns/_form.html.erb +37 -0
  179. data/app/views/active_stix/attack_patterns/edit.html.erb +2 -0
  180. data/app/views/active_stix/attack_patterns/index.html.erb +2 -0
  181. data/app/views/active_stix/attack_patterns/new.html.erb +2 -0
  182. data/app/views/active_stix/attack_patterns/show.html.erb +140 -0
  183. data/app/views/active_stix/bcc_refs/_form.html.erb +27 -0
  184. data/app/views/active_stix/bcc_refs/edit.html.erb +6 -0
  185. data/app/views/active_stix/bcc_refs/index.html.erb +29 -0
  186. data/app/views/active_stix/bcc_refs/new.html.erb +5 -0
  187. data/app/views/active_stix/bcc_refs/show.html.erb +14 -0
  188. data/app/views/active_stix/bundles/index.html.erb +1 -0
  189. data/app/views/active_stix/bundles/show.html.erb +7 -0
  190. data/app/views/active_stix/campaigns/_form.html.erb +42 -0
  191. data/app/views/active_stix/campaigns/_stix_campaign.json.jbuilder +2 -0
  192. data/app/views/active_stix/campaigns/edit.html.erb +6 -0
  193. data/app/views/active_stix/campaigns/index.html.erb +35 -0
  194. data/app/views/active_stix/campaigns/index.json.jbuilder +1 -0
  195. data/app/views/active_stix/campaigns/new.html.erb +5 -0
  196. data/app/views/active_stix/campaigns/show.html.erb +29 -0
  197. data/app/views/active_stix/campaigns/show.json.jbuilder +1 -0
  198. data/app/views/active_stix/email_messages/_form.html.erb +62 -0
  199. data/app/views/active_stix/email_messages/_stix_email_message.json.jbuilder +2 -0
  200. data/app/views/active_stix/email_messages/edit.html.erb +6 -0
  201. data/app/views/active_stix/email_messages/index.html.erb +43 -0
  202. data/app/views/active_stix/email_messages/index.json.jbuilder +1 -0
  203. data/app/views/active_stix/email_messages/new.html.erb +5 -0
  204. data/app/views/active_stix/email_messages/show.html.erb +165 -0
  205. data/app/views/active_stix/email_messages/show.json.jbuilder +1 -0
  206. data/app/views/active_stix/files/_form.html.erb +92 -0
  207. data/app/views/active_stix/files/_stix_file.json.jbuilder +2 -0
  208. data/app/views/active_stix/files/edit.html.erb +6 -0
  209. data/app/views/active_stix/files/index.html.erb +55 -0
  210. data/app/views/active_stix/files/index.json.jbuilder +1 -0
  211. data/app/views/active_stix/files/new.html.erb +5 -0
  212. data/app/views/active_stix/files/show.html.erb +79 -0
  213. data/app/views/active_stix/files/show.json.jbuilder +1 -0
  214. data/app/views/active_stix/identities/_form.html.erb +27 -0
  215. data/app/views/active_stix/identities/_individual.html.erb +100 -0
  216. data/app/views/active_stix/identities/_organization.html.erb +72 -0
  217. data/app/views/active_stix/identities/_received_email_messages.html.erb +27 -0
  218. data/app/views/active_stix/identities/_sent_email_messages.html.erb +27 -0
  219. data/app/views/active_stix/identities/_threat_icons.html.erb +3 -0
  220. data/app/views/active_stix/identities/edit.html.erb +2 -0
  221. data/app/views/active_stix/identities/index.html.erb +37 -0
  222. data/app/views/active_stix/identities/new.html.erb +5 -0
  223. data/app/views/active_stix/identities/show.html.erb +15 -0
  224. data/app/views/active_stix/layouts/active_stix/application.html.erb +16 -0
  225. data/app/views/active_stix/recipients/_form.html.erb +27 -0
  226. data/app/views/active_stix/recipients/edit.html.erb +6 -0
  227. data/app/views/active_stix/recipients/index.html.erb +29 -0
  228. data/app/views/active_stix/recipients/new.html.erb +5 -0
  229. data/app/views/active_stix/recipients/show.html.erb +14 -0
  230. data/app/views/active_stix/threat_actors/_form.html.erb +32 -0
  231. data/app/views/active_stix/threat_actors/_stix_threat_actor.json.jbuilder +2 -0
  232. data/app/views/active_stix/threat_actors/edit.html.erb +6 -0
  233. data/app/views/active_stix/threat_actors/flags.html.erb +184 -0
  234. data/app/views/active_stix/threat_actors/index.html.erb +26 -0
  235. data/app/views/active_stix/threat_actors/index.json.jbuilder +1 -0
  236. data/app/views/active_stix/threat_actors/new.html.erb +5 -0
  237. data/app/views/active_stix/threat_actors/show.html.erb +4 -0
  238. data/app/views/active_stix/threat_actors/show.json.jbuilder +1 -0
  239. data/app/views/layouts/active_stix/application.html.erb +16 -0
  240. data/config/routes.rb +39 -0
  241. data/db/migrate/20191204200025_create_active_stix_bundled_objects.rb +11 -0
  242. data/db/migrate/20191204213707_create_active_stix_bundles.rb +10 -0
  243. data/db/migrate/20191204213802_create_active_stix_campaigns.rb +15 -0
  244. data/db/migrate/20191204213926_create_active_stix_course_of_actions.rb +12 -0
  245. data/db/migrate/20191204214020_create_active_stix_cyber_observables.rb +11 -0
  246. data/db/migrate/20191204214955_create_active_stix_email_messages.rb +20 -0
  247. data/db/migrate/20191204215029_create_active_stix_external_references.rb +12 -0
  248. data/db/migrate/20191204215302_create_active_stix_files.rb +23 -0
  249. data/db/migrate/20191204215419_create_active_stix_identities.rb +13 -0
  250. data/db/migrate/20191204215542_create_active_stix_indicator_labels.rb +10 -0
  251. data/db/migrate/20191204215637_create_active_stix_indicators.rb +16 -0
  252. data/db/migrate/20191204215849_create_active_stix_intrusion_sets.rb +15 -0
  253. data/db/migrate/20191204215929_create_active_stix_kill_chain_phases.rb +10 -0
  254. data/db/migrate/20191204215951_create_active_stix_kill_chains.rb +9 -0
  255. data/db/migrate/20191204220149_create_active_stix_malwares.rb +12 -0
  256. data/db/migrate/20191204220539_create_active_stix_marking_definitions.rb +12 -0
  257. data/db/migrate/20191204220853_create_active_stix_observed_data.rb +12 -0
  258. data/db/migrate/20191204220917_create_active_stix_open_vocabularies.rb +9 -0
  259. data/db/migrate/20191204220952_create_active_stix_phases.rb +11 -0
  260. data/db/migrate/20191204221129_create_active_stix_recipients.rb +10 -0
  261. data/db/migrate/20191204221227_create_active_stix_relationships.rb +16 -0
  262. data/db/migrate/20191204221323_create_active_stix_report_objects.rb +11 -0
  263. data/db/migrate/20191204221359_create_active_stix_reports.rb +14 -0
  264. data/db/migrate/20191204221425_create_active_stix_threat_actors.rb +11 -0
  265. data/db/migrate/20191204221454_create_active_stix_tools.rb +12 -0
  266. data/db/migrate/20191204221639_create_active_stix_urls.rb +9 -0
  267. data/db/migrate/20191204221849_create_active_stix_users.rb +22 -0
  268. data/db/migrate/20191205182234_create_active_stix_bcc_refs.rb +10 -0
  269. data/db/migrate/20191205182255_create_active_stix_cc_refs.rb +10 -0
  270. data/db/migrate/20191205182316_create_active_stix_to_refs.rb +10 -0
  271. data/db/migrate/20191212203611_add_spec_version_to_bundles.rb +5 -0
  272. data/db/migrate/20191212215136_create_active_stix_attack_patterns.rb +12 -0
  273. data/db/migrate/20191212220222_create_active_stix_reference_items.rb +11 -0
  274. data/db/migrate/20191213135204_create_active_stix_labels.rb +10 -0
  275. data/db/migrate/20191213140951_create_active_stix_markups.rb +11 -0
  276. data/db/migrate/20191221210537_fix_observed_data.rb +6 -0
  277. data/db/migrate/20191221223602_create_active_stix_artifacts.rb +16 -0
  278. data/db/migrate/20191223075550_change_artifact_ref_to_string.rb +5 -0
  279. data/db/migrate/20191223154000_add_stix_id_to_email_messages.rb +5 -0
  280. data/db/migrate/20200114162245_add_labels_to_active_stix_identities.rb +5 -0
  281. data/db/migrate/20200404223006_add_aliases_to_tools.rb +5 -0
  282. data/db/migrate/20200404223047_add_aliases_to_attack_patterns.rb +5 -0
  283. data/db/migrate/20200404223158_add_aliases_to_malwares.rb +5 -0
  284. data/db/migrate/20200404223210_add_aliases_to_threat_actors.rb +5 -0
  285. data/lib/active_stix.rb +8 -0
  286. data/lib/active_stix/engine.rb +13 -0
  287. data/lib/active_stix/version.rb +3 -0
  288. data/lib/tasks/active_stix_tasks.rake +4 -0
  289. metadata +358 -0
@@ -0,0 +1,4 @@
1
+ class ActiveStix::BundledObject < ApplicationRecord
2
+ belongs_to :bundle, foreign_key: "bundle_ref", primary_key: "stix_id"
3
+ belongs_to :stix_object, polymorphic: true, foreign_key: "object_ref", primary_key: "stix_id", foreign_type: :object_type
4
+ end
@@ -0,0 +1,65 @@
1
+ class ActiveStix::Campaign < ApplicationRecord
2
+ has_many :source_relationships, class_name: 'ActiveStix::Relationship', primary_key: 'stix_id', foreign_key: 'source_ref' #relationships where this class is the source
3
+ has_many :target_relationships, class_name: 'ActiveStix::Relationship', primary_key: 'stix_id', foreign_key: 'target_ref' #relationships where this class is the target
4
+
5
+ def self.ingest_json(obj)
6
+ camp = find_or_create_by(stix_id: obj['id'], name: obj['name'], description: obj['description'], first_seen: obj['first_seen'], last_seen: obj['last_seen'])
7
+ camp
8
+ end
9
+
10
+ before_create do
11
+ self.stix_id = "#{type}--#{SecureRandom.uuid}" if stix_id.blank?
12
+ end
13
+
14
+
15
+ def type
16
+ 'campaign'
17
+ end
18
+
19
+
20
+ def attack_patterns
21
+ attack_pattern_relationships.map(&:target)
22
+ end
23
+
24
+ def attack_pattern_relationships
25
+ relationships = []
26
+ ActiveStix::Relationship.where(source: self, relationship_type: "uses", target_type: "ActiveStix::AttackPattern").each do |rel|
27
+ relationships << rel
28
+ end
29
+ relationships
30
+ end
31
+
32
+ def indicator_relationships
33
+ relationships = []
34
+ ActiveStix::Relationship.where(source_type: "ActiveStix::Indicator", relationship_type: "indicates", target: self).each do |rel|
35
+ relationships << rel
36
+ end
37
+ relationships
38
+ end
39
+
40
+ def as_stix
41
+ as_json(only: []).tap do |hash|
42
+ hash["id"] = stix_id
43
+ hash["type"] = type
44
+ hash["created"] = created_at.rfc3339(3)
45
+ hash["modified"] = updated_at.rfc3339(3)
46
+ hash["first_seen"] = created_at.rfc3339(3)
47
+ hash["last_seen"] = updated_at.rfc3339(3)
48
+ hash["name"] = name
49
+ hash["description"] = description
50
+ end
51
+ end
52
+
53
+ def convert_to_json
54
+ {
55
+ :type => "campaign",
56
+ :id => stix_id,
57
+ :created => created_at.to_s,
58
+ :modified => updated_at.to_s,
59
+ :name => name,
60
+ :description => description,
61
+ :first_seen => first_seen,
62
+ :last_seen => last_seen
63
+ }
64
+ end
65
+ end
@@ -0,0 +1,6 @@
1
+ module ActiveStix
2
+ class CcRef < ActiveStix::Recipient
3
+ belongs_to :email_message
4
+ belongs_to :email_address
5
+ end
6
+ end
@@ -0,0 +1,54 @@
1
+ module ActiveStix
2
+ class CourseOfAction < ApplicationRecord
3
+ has_many :reference_items, as: 'referrer'
4
+ has_many :external_references, class_name: 'ActiveStix::ExternalReference', through: :reference_items
5
+
6
+ has_many :reference_object_marking_courses, class_name: 'ActiveStix::ReferenceObjectMarkingCourse', foreign_key: 'stix_course_of_action_id'
7
+ has_many :marking_definitions, class_name: 'ActiveStix::MarkingDefinition', through: :reference_object_marking_courses, primary_key: 'id'
8
+
9
+ has_many :source_relationships, class_name: 'ActiveStix::Relationship', primary_key: 'stix_id', foreign_key: 'source_ref' #relationships where this class is the source
10
+ has_many :target_relationships, class_name: 'ActiveStix::Relationship', primary_key: 'stix_id', foreign_key: 'target_ref' #relationships where this class is the target
11
+
12
+ def self.ingest_json(obj)
13
+ course_of_action = find_or_create_by(stix_id: obj['id'], name: obj['name'], description: obj['description'])
14
+ if obj.has_key?('external_references')
15
+ obj['external_references'].each do |er|
16
+ external_reference = ExternalReference.ingest_json(er, obj['id'])
17
+ course_of_action.external_references << external_reference unless ActiveStix::ReferenceItem.find_by(external_reference:external_reference, referrer: course_of_action)
18
+ end
19
+ end
20
+ if obj.has_key?('object_marking_refs')
21
+ # TODO
22
+ # obj['object_marking_refs'].each do |mr|
23
+ # marking_definition = MarkingDefinition.create_by_id(mr)
24
+ # course_of_action.marking_definitions << marking_definition unless ActiveStix::ReferenceObjectMarkingCourse.find_by(stix_marking_definition_id:marking_definition.id, stix_course_of_action_id:course_of_action.id)
25
+ # end
26
+ end
27
+ course_of_action.save
28
+ course_of_action
29
+ end
30
+
31
+ def convert_to_json
32
+ external_refs_arr = []
33
+ external_references.each do | x |
34
+ external_refs_arr << x.convert_to_json
35
+ end
36
+
37
+ marking_def_arr = []
38
+ marking_definitions.each do | x |
39
+ marking_def_arr << x.convert_to_json
40
+ end
41
+
42
+ {
43
+ :external_references => external_refs_arr,
44
+ :object_marking_refs => marking_def_arr,
45
+ :id => stix_id,
46
+ :name => name,
47
+ :type => "course-of-action",
48
+ :modified => updated_at.to_s,
49
+ :created => created_at.to_s,
50
+ :description => description
51
+ }
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,4 @@
1
+ class ActiveStix::CyberObservable < ApplicationRecord
2
+ belongs_to :observed_datum, :class_name => 'ActiveStix::ObservedDatum', foreign_key: :observed_datum_ref, primary_key: :stix_id
3
+ belongs_to :cyber_observable_object, polymorphic: true, foreign_key: :observable_object_id
4
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveStix
2
+ class EmailAddress < ApplicationRecord
3
+
4
+ has_many :to_refs, foreign_key: 'stix_email_address_id'
5
+ has_many :email_messages, foreign_key: :from_ref
6
+ belongs_to :identity, class_name: 'ActiveStix::Identity'
7
+
8
+ # after_create_commit do
9
+ # assign_iddentity_to_group
10
+ # end
11
+
12
+ def self.from_eml(eml)
13
+ eml.correspondences.all.collect do |c|
14
+ {
15
+ "type": "email-address",
16
+ "value": c.email.address,
17
+ "display_name": c.email.alias,
18
+ "from_ref": c.agent.id
19
+ }
20
+ end
21
+ end
22
+
23
+ def assign_identity_to_group
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,339 @@
1
+ module ActiveStix
2
+ class EmailMessage < ApplicationRecord
3
+ has_many :to_refs, foreign_key: 'email_message_id'
4
+ has_many :cc_refs, foreign_key: 'email_message_id'
5
+ has_many :bcc_refs, foreign_key: 'email_message_id'
6
+ has_many :recipients, foreign_key: 'email_message_id'
7
+ has_many :cyber_observables, :class_name => 'ActiveStix::CyberObservable', foreign_key: :observable_object_id, as: :cyber_observable_object
8
+ has_many :observed_data, through: :cyber_observables
9
+ belongs_to :from, class_name: 'ActiveStix::EmailAddress', foreign_key: 'from_ref'
10
+ belongs_to :raw_email_artifact, foreign_key: :raw_email_ref, class_name: 'ActiveStix::Artifact', primary_key: :stix_id
11
+
12
+
13
+ before_create do
14
+ self.stix_id = "#{type}--#{SecureRandom.uuid}" if stix_id.blank?
15
+ end
16
+
17
+ after_create do
18
+ ActiveStix::ObservedDatum.wrap_object(self)
19
+ end
20
+
21
+ def primary_observed_datum
22
+ observed_data.first
23
+ end
24
+
25
+ def from_identity
26
+ from.identity
27
+ end
28
+
29
+ def identities
30
+ ids = [from.identity]
31
+ to_refs.each do |tr|
32
+ ids << tr.email_address.identity
33
+ end
34
+
35
+ cc_refs.each do |ccr|
36
+ ids << ccr.email_address.identity
37
+ end
38
+
39
+ bcc_refs.each do |bccr|
40
+ ids << bccr.email_address.identity
41
+ end
42
+ ids.uniq
43
+ end
44
+
45
+ def mail_server
46
+ Mail.new(raw_email_artifact.payload_bin).message_id.split(/[@\.]/)[-3..-1]
47
+ end
48
+
49
+ def readable
50
+ eml.readable
51
+ end
52
+
53
+ def self.from_eml(eml)
54
+ eml = eml.encode(Encoding.find('UTF-8'), {invalid: :replace, undef: :replace, replace: ''}).sub("\xEF\xBB\xBF".force_encoding('UTF-8'), "").gsub("\r", "").unicode_normalize(:nfkc)
55
+ mail = Mail.new(eml)
56
+
57
+ #TODO Add details for cc_refs, bcc_refs etc. from the email message object
58
+
59
+ is_multipart = mail.multipart?
60
+ date = mail.date
61
+ content_type = mail.content_type
62
+ from = create_from(mail, eml)
63
+ sender_ref = create_sender(mail, eml)
64
+ subject = mail.header["Subject"] ? mail.header["Subject"].value : ""
65
+ received_lines = mail.header["Received"]
66
+
67
+ #TODO add the appropriate details here later
68
+ #TODO late make additional header fields more specific, check stix spec
69
+ email_message = EmailMessage.create(
70
+ "is_multipart": is_multipart,
71
+ "date": date,
72
+ "content_type": content_type,
73
+ "from": from,
74
+ "sender_ref": sender_ref,
75
+ "subject": subject,
76
+ "received_lines": received_lines,
77
+ "additional_header_fields": mail.header,
78
+ "body": mail.body,
79
+ "body_multipart": body_multipart(mail),
80
+ "raw_email_ref": raw_email_artifact(mail).stix_id
81
+ )
82
+ create_recipients(mail, eml, email_message)
83
+
84
+ email_message
85
+ end
86
+
87
+ def self.raw_email_artifact(eml)
88
+ artifact = Artifact.create_from_eml(eml)
89
+ end
90
+
91
+ def self.body_multipart(mail)
92
+ if mail.multipart?
93
+ mail.parts.collect {|part| part.mime_type}
94
+ else
95
+ nil
96
+ end
97
+ end
98
+
99
+ def type
100
+ return "email-message"
101
+ end
102
+
103
+ def self.extract_info_from_address_header(descriptive_name)
104
+ descriptive_name = descriptive_name.to_s
105
+ descriptive_name.gsub!('\"', '')
106
+ temp = descriptive_name.split(' via ')
107
+ fullname = temp[0].to_s
108
+ if temp.size > 1
109
+ medium = temp[1]
110
+ end
111
+ if not fullname.lstrip().start_with?('<')
112
+ name_parts = fullname.split(',')
113
+ if name_parts.size > 1
114
+ last_name = name_parts[0]
115
+ first_name = name_parts[1].lstrip()
116
+ else
117
+ name_parts = fullname.split(' ')
118
+ if name_parts.size > 1
119
+ first_name = name_parts[0]
120
+ last_name = name_parts[1]
121
+ end
122
+ end
123
+ end
124
+ return first_name, last_name, medium
125
+ end
126
+
127
+ def self.create_recipients(mail, eml, email_message)
128
+ if mail.header["To"]
129
+ get_recipients_by_type("To", mail, eml, email_message)
130
+ end
131
+
132
+ if mail.header["CC"]
133
+ get_recipients_by_type("CC", mail, eml, email_message)
134
+ end
135
+
136
+ if mail.header["BCC"]
137
+ get_recipients_by_type("BCC", mail, eml, email_message)
138
+ end
139
+ end
140
+
141
+ #TODO The two methods below can definitely be consolidated to one. Make sure to do so.
142
+ def self.create_from(mail, eml)
143
+ if mail.header["From"]
144
+ mail.header["From"].address_list.addresses.each do |address|
145
+ user_account = UserAccount.where("lower(user_id) = ?", address.address.downcase).first
146
+ fname, lname, medium = extract_info_from_address_header(address.display_name)
147
+ #TODO Create an identity here so it can be linked to the user account and email address
148
+ if user_account.nil?
149
+ identity = create_identity(address.address.downcase, address.name)
150
+ user_account = UserAccount.create(user_id: address.address.downcase, account_login: get_name_from_address(address.address), display_name: address.name, is_service_account: false, is_privileged: false, can_escalate_privs: false, is_disabled: false, identity_id: identity.id)
151
+ identity.user_accounts << user_account
152
+ else
153
+ identity = user_account.identity
154
+ end
155
+ email_address = EmailAddress.where("lower(value) = ?", address.address.downcase).first
156
+ if email_address.nil?
157
+ email_address = EmailAddress.create(value: address.address.downcase, display_name: address.name, belongs_to_ref: user_account.id, identity_id: identity.id)
158
+ end
159
+
160
+ return email_address
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ def self.create_sender(mail, eml)
167
+ if mail.from.any?
168
+ address = mail.from.first
169
+ user_account = UserAccount.where("lower(user_id) = ?", address.downcase).first
170
+ #TODO Create an identity here so it can be linked to the user account and email address
171
+ if user_account.nil?
172
+ identity = create_identity(address, address)
173
+ user_account = UserAccount.create(user_id: address, account_login: get_name_from_address(address), display_name: address, is_service_account: false, is_privileged: false, can_escalate_privs: false, is_disabled: false, identity_id: identity.id)
174
+ identity.users_accounts << user_account
175
+ else
176
+ identity = user_account.identity
177
+ end
178
+ email_address = EmailAddress.where("lower(value) = ?", address.downcase).first
179
+ if email_address.nil?
180
+ email_address = EmailAddress.create(value: address, display_name: address, belongs_to_ref: user_account.id, identity_id: identity.id)
181
+ end
182
+ return email_address
183
+ end
184
+ end
185
+
186
+ def self.get_recipients_by_type(recipient_type, mail, eml, email_message)
187
+ return if mail.header[recipient_type].errors.any? # todo we should throw and catch an exception here
188
+ mail.header[recipient_type].each do |address|
189
+ # TODO this will be the user account
190
+ user_account = UserAccount.where("lower(user_id) = ?", address.address.downcase).first
191
+
192
+ fname, lname, medium = extract_info_from_address_header(address.display_name)
193
+
194
+ #TODO Create an identity here so it can be linked to the user account and email address
195
+ if user_account.nil?
196
+ identity = create_identity(address.address.downcase, address.name)
197
+ user_account = identity.user_accounts.create(user_id: address.address, account_login: get_name_from_address(address.address), display_name: address.name, is_service_account: false, is_privileged: false, can_escalate_privs: false, is_disabled: false)
198
+ else
199
+ identity = user_account.identity
200
+ end
201
+
202
+ # TODO this will be the email address
203
+ email_address = EmailAddress.where("lower(value) = ?", address.address.downcase).first
204
+ if email_address.nil?
205
+ email_address = EmailAddress.create(value: address.address.downcase, display_name: address.name, belongs_to_ref: user_account.id, identity_id: identity.id)
206
+ end
207
+
208
+ # Create header specific refs
209
+ create_recipient_type_ref(recipient_type, email_message, email_address)
210
+ end
211
+ end
212
+
213
+ def self.create_recipient_type_ref(recipient_type, email_message, email_address)
214
+
215
+ case recipient_type
216
+ when "To"
217
+ ToRef.create(email_message: email_message, email_address: email_address)
218
+ when "CC"
219
+ CcRef.create(email_message: email_message, email_address: email_address)
220
+ when "BCC"
221
+ BccRef.create(email_message: email_message, email_address: email_address)
222
+ end
223
+ end
224
+
225
+ def self.create_identity(address, display_name)
226
+ #TODO figure out where to get the details for whether for identity_class, description etc.
227
+ identity = Identity.create(name: display_name || Mail::Address.new(address).local, contact_information: {email_addresses: [address]}, identity_class: 'individual')
228
+
229
+ organization = from_domain_identity(address)
230
+ ActiveStix::Identity.employ(identity, organization)
231
+
232
+ return identity
233
+ end
234
+
235
+ #NOTE Instance method created for the class to use
236
+ def self.from_domain_identity(address)
237
+ org_name = Organization.company_from_email_address(address)
238
+ public_suffix = Organization.public_suffix_from_email_address(address)
239
+
240
+ organization = ActiveStix::Identity.find_or_create_by(name: org_name + public_suffix, identity_class: "organization")
241
+
242
+ if organization.contact_information.nil?
243
+ organization.update_attribute("contact_information", {domain: org_name, public_suffix: public_suffix})
244
+ else
245
+ contact_information = organization.contact_information
246
+ contact_information["public_suffix"] = public_suffix
247
+ organization.contact_information = contact_information
248
+ organization.save
249
+ end
250
+
251
+ freemail = ActiveStix::AttackPattern.find_by(name: "Free email")
252
+ if freemail and freemail.targets?(organization)
253
+ personal_organization = ActiveStix::Identity.find_or_create_by(name: address, identity_class: "organization")
254
+ ActiveStix::Identity.employ(identity, personal_organization)
255
+ end
256
+ organization
257
+ end
258
+
259
+ def from_domain_identity
260
+ ActiveStix::EmailMessage.from_domain_identity(from.value)
261
+ end
262
+
263
+ def self.get_name_from_address(address)
264
+ return address.split('@')[0]
265
+ end
266
+
267
+ def self.find_or_create_user_account(email, aliasname)
268
+ if email.agent.nil?
269
+ agent = Agent.create
270
+ agent.emails << email
271
+ else
272
+ agent = email.agent
273
+ unless agent.emails.where(alias: aliasname).any?
274
+ agent.emails << email
275
+ end
276
+ end
277
+ return agent
278
+ end
279
+
280
+ def stix_references
281
+ object_refs = {}
282
+ object_index = 1
283
+ [to_refs, cc_refs, bcc_refs].each do |field|
284
+ field.each do |ref|
285
+ object_refs[{
286
+
287
+ "type": "email-addr",
288
+ "value": ref.email_address.value.to_s,
289
+ "display_name": ref.email_address.display_name.to_s
290
+ }] = object_index.to_s
291
+ object_index += 1
292
+ end
293
+ end
294
+ object_refs[{
295
+
296
+ "type": "email-addr",
297
+ "value": from.value.to_s,
298
+ "display_name": from.display_name.to_s
299
+ }] = object_index.to_s
300
+ object_refs
301
+ end
302
+
303
+
304
+ def mail
305
+ Mail.new(eml.raw_source)
306
+ end
307
+
308
+ def as_stix
309
+
310
+ as_json(only: []).tap do |hash|
311
+ # hash["x_panacea_id"] = "<#{id}>".force_encoding("utf-8")
312
+ hash["type"] = "email-message"
313
+
314
+ mail = Mail.new(raw_email_artifact.payload_bin)
315
+ hash["date"] = mail.date.utc.iso8601(3)
316
+
317
+ # todo fix this when jpl turns on stix
318
+ hash["is_multipart"] = false
319
+
320
+ # if mail.multipart?
321
+ # stix_parts = mail.parts.collect do |part|
322
+ # {
323
+ # "content_type" => part.content_type.to_s,
324
+ # "content_disposition" => part.content_transfer_encoding.to_s,
325
+ # "body" => Digest::SHA1.hexdigest(part.to_s)
326
+ # }
327
+ # end.to_a
328
+ # hash["body_multipart"] = stix_parts
329
+ # else
330
+ # hash["body"] = eml.readable
331
+ # end
332
+
333
+ hash
334
+ end
335
+ end
336
+
337
+
338
+ end
339
+ end