mihari 5.4.3 → 5.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/frontend/package-lock.json +2399 -1504
  3. data/frontend/package.json +22 -22
  4. data/lib/mihari/analyzers/base.rb +25 -10
  5. data/lib/mihari/analyzers/binaryedge.rb +1 -7
  6. data/lib/mihari/analyzers/circl.rb +1 -1
  7. data/lib/mihari/analyzers/dnstwister.rb +1 -1
  8. data/lib/mihari/analyzers/otx.rb +1 -1
  9. data/lib/mihari/analyzers/passivetotal.rb +1 -1
  10. data/lib/mihari/analyzers/pulsedive.rb +1 -1
  11. data/lib/mihari/analyzers/rule.rb +18 -13
  12. data/lib/mihari/analyzers/securitytrails.rb +1 -1
  13. data/lib/mihari/analyzers/urlscan.rb +1 -1
  14. data/lib/mihari/analyzers/virustotal.rb +1 -1
  15. data/lib/mihari/analyzers/zoomeye.rb +1 -1
  16. data/lib/mihari/clients/binaryedge.rb +4 -7
  17. data/lib/mihari/clients/crtsh.rb +1 -3
  18. data/lib/mihari/clients/publsedive.rb +1 -1
  19. data/lib/mihari/clients/shodan.rb +2 -2
  20. data/lib/mihari/commands/alert.rb +42 -13
  21. data/lib/mihari/commands/rule.rb +11 -7
  22. data/lib/mihari/commands/search.rb +54 -22
  23. data/lib/mihari/config.rb +5 -0
  24. data/lib/mihari/emitters/base.rb +9 -3
  25. data/lib/mihari/emitters/slack.rb +1 -1
  26. data/lib/mihari/enrichers/base.rb +13 -0
  27. data/lib/mihari/enrichers/google_public_dns.rb +16 -1
  28. data/lib/mihari/enrichers/ipinfo.rb +9 -13
  29. data/lib/mihari/enrichers/shodan.rb +1 -2
  30. data/lib/mihari/enrichers/whois.rb +2 -2
  31. data/lib/mihari/errors.rb +16 -10
  32. data/lib/mihari/feed/parser.rb +2 -2
  33. data/lib/mihari/models/artifact.rb +1 -1
  34. data/lib/mihari/models/autonomous_system.rb +11 -5
  35. data/lib/mihari/models/cpe.rb +10 -4
  36. data/lib/mihari/models/dns.rb +11 -16
  37. data/lib/mihari/models/geolocation.rb +11 -5
  38. data/lib/mihari/models/port.rb +10 -4
  39. data/lib/mihari/models/reverse_dns.rb +10 -4
  40. data/lib/mihari/models/whois.rb +4 -1
  41. data/lib/mihari/schemas/analyzer.rb +1 -0
  42. data/lib/mihari/services/alert_builder.rb +43 -0
  43. data/lib/mihari/services/alert_proxy.rb +7 -25
  44. data/lib/mihari/services/alert_runner.rb +9 -0
  45. data/lib/mihari/services/rule_builder.rb +47 -0
  46. data/lib/mihari/services/rule_proxy.rb +5 -61
  47. data/lib/mihari/services/rule_runner.rb +9 -4
  48. data/lib/mihari/structs/binaryedge.rb +89 -0
  49. data/lib/mihari/structs/shodan.rb +2 -1
  50. data/lib/mihari/structs/urlscan.rb +1 -3
  51. data/lib/mihari/structs/virustotal_intelligence.rb +1 -3
  52. data/lib/mihari/type_checker.rb +1 -1
  53. data/lib/mihari/version.rb +1 -1
  54. data/lib/mihari/web/endpoints/alerts.rb +33 -15
  55. data/lib/mihari/web/endpoints/artifacts.rb +53 -25
  56. data/lib/mihari/web/endpoints/configs.rb +2 -2
  57. data/lib/mihari/web/endpoints/ip_addresses.rb +3 -5
  58. data/lib/mihari/web/endpoints/rules.rb +97 -71
  59. data/lib/mihari/web/endpoints/tags.rb +15 -5
  60. data/lib/mihari/web/public/assets/index-ef33a6cd.js +1738 -0
  61. data/lib/mihari/web/public/index.html +1 -1
  62. data/lib/mihari/web/public/redoc-static.html +419 -382
  63. data/lib/mihari.rb +4 -0
  64. data/mihari.gemspec +5 -4
  65. metadata +28 -11
  66. data/lib/mihari/web/public/assets/index-4d7eda9f.js +0 -1738
@@ -61,15 +61,23 @@ module Mihari
61
61
  requires :id, type: String
62
62
  end
63
63
  get "/:id" do
64
+ extend Dry::Monads[:result, :try]
65
+
64
66
  id = params["id"].to_s
65
67
 
66
- begin
67
- rule = Mihari::Rule.find(id)
68
- rescue ActiveRecord::RecordNotFound
68
+ result = Try do
69
+ Mihari::Rule.find(id)
70
+ end.to_result
71
+
72
+ return present(result.value!, with: Entities::Rule) if result.success?
73
+
74
+ failure = result.failure
75
+ case failure
76
+ when ActiveRecord::RecordNotFound
69
77
  error!({ message: "ID:#{id} is not found" }, 404)
78
+ else
79
+ raise failure
70
80
  end
71
-
72
- present rule, with: Entities::Rule
73
81
  end
74
82
 
75
83
  desc "Run a rule", {
@@ -80,19 +88,27 @@ module Mihari
80
88
  requires :id, type: String
81
89
  end
82
90
  get "/:id/run" do
91
+ extend Dry::Monads[:result, :try]
92
+
83
93
  id = params["id"].to_s
84
94
 
85
- begin
86
- rule = Mihari::Services::RuleProxy.from_model(Mihari::Rule.find(id))
87
- rescue ActiveRecord::RecordNotFound
88
- error!({ message: "ID:#{id} is not found" }, 404)
89
- end
95
+ result = Try do
96
+ Mihari::Services::RuleProxy.from_model(Mihari::Rule.find(id))
97
+ end.to_result
90
98
 
91
- analyzer = rule.analyzer
92
- analyzer.run
99
+ if result.success?
100
+ result.value!.analyzer.run
101
+ status 201
102
+ return present({ message: "ID:#{id} is ran successfully" }, with: Entities::Message)
103
+ end
93
104
 
94
- status 201
95
- present({ message: "ID:#{id} is ran successfully" }, with: Entities::Message)
105
+ failure = result.failure
106
+ case failure
107
+ when ActiveRecord::RecordNotFound
108
+ error!({ message: "ID:#{id} is not found" }, 404)
109
+ else
110
+ raise failure
111
+ end
96
112
  end
97
113
 
98
114
  desc "Create a rule", {
@@ -103,39 +119,38 @@ module Mihari
103
119
  requires :yaml, type: String, documentation: { param_type: "body" }
104
120
  end
105
121
  post "/" do
106
- yaml = params[:yaml]
122
+ extend Dry::Monads[:result, :try]
107
123
 
108
- begin
109
- rule = Services::RuleProxy.from_yaml(yaml)
110
- rescue YAMLSyntaxError => e
111
- error!({ message: e.message }, 400)
124
+ yaml = params[:yaml]
125
+ result = Try do
126
+ Services::RuleProxy.from_yaml(yaml)
127
+ end.to_result.bind do |rule|
128
+ Try do
129
+ found = Mihari::Rule.find_by_id(rule.id)
130
+ error!({ message: "ID:#{rule.id} is already registered" }, 400) unless found.nil?
131
+ rule
132
+ end.to_result
133
+ end.bind do |rule|
134
+ Try do
135
+ rule.model.save
136
+ rule
137
+ end.to_result
112
138
  end
113
139
 
114
- # check ID duplication
115
- begin
116
- Mihari::Rule.find(rule.id)
117
- error!({ message: "ID:#{rule.id} is already registered" }, 400)
118
- rescue ActiveRecord::RecordNotFound
119
- # do nothing
140
+ if result.success?
141
+ status 201
142
+ return present(result.value!.model, with: Entities::Rule)
120
143
  end
121
144
 
122
- begin
123
- rule.validate!
124
- rescue RuleValidationError
125
- error!({ message: "Data format is invalid", details: rule.errors.to_h }, 400) if rule.errors?
126
-
127
- # when NoMethodError occurs
128
- error!({ message: "Data format is invalid" }, 400)
145
+ failure = result.failure
146
+ case failure
147
+ when Psych::SyntaxError
148
+ error!({ message: failure.message }, 400)
149
+ when ValidationError
150
+ error!({ message: "Data format is invalid", details: failure.errors.to_h }, 400)
151
+ else
152
+ raise failure
129
153
  end
130
-
131
- begin
132
- rule.model.save
133
- rescue ActiveRecord::RecordNotUnique
134
- error!({ message: "ID:#{rule.id} is already registered" }, 400)
135
- end
136
-
137
- status 201
138
- present rule.model, with: Entities::Rule
139
154
  end
140
155
 
141
156
  desc "Update a rule", {
@@ -147,38 +162,40 @@ module Mihari
147
162
  requires :yaml, type: String, documentation: { param_type: "body" }
148
163
  end
149
164
  put "/" do
165
+ extend Dry::Monads[:result, :try]
166
+
150
167
  id = params[:id]
151
168
  yaml = params[:yaml]
152
169
 
153
- begin
170
+ result = Try do
154
171
  Mihari::Rule.find(id)
155
- rescue ActiveRecord::RecordNotFound
156
- error!({ message: "ID:#{id} is not found" }, 404)
172
+ end.to_result.bind do |_|
173
+ Try do
174
+ Services::RuleProxy.from_yaml(yaml)
175
+ end.to_result
176
+ end.bind do |rule|
177
+ Try do
178
+ rule.model.save
179
+ rule
180
+ end.to_result
157
181
  end
158
182
 
159
- begin
160
- rule = Services::RuleProxy.from_yaml(yaml)
161
- rescue YAMLSyntaxError => e
162
- error!({ message: e.message }, 400)
183
+ if result.success?
184
+ status 201
185
+ return present(result.value!.model, with: Entities::Rule)
163
186
  end
164
187
 
165
- begin
166
- rule.validate!
167
- rescue RuleValidationError
168
- error!({ message: "Data format is invalid", details: rule.errors.to_h }, 400) if rule.errors?
169
-
170
- # when NoMethodError occurs
171
- error!({ message: "Data format is invalid" }, 400)
172
- end
173
-
174
- begin
175
- rule.model.save
176
- rescue ActiveRecord::RecordNotUnique
177
- error!({ message: "ID:#{id} is already registered" }, 400)
188
+ failure = result.failure
189
+ case failure
190
+ when ActiveRecord::RecordNotFound
191
+ error!({ message: "ID:#{id} is not found" }, 404)
192
+ when Psych::SyntaxError
193
+ error!({ message: failure.message }, 400)
194
+ when ValidationError
195
+ error!({ message: "Data format is invalid", details: failure.errors.to_h }, 400)
196
+ else
197
+ raise failure
178
198
  end
179
-
180
- status 201
181
- present rule.model, with: Entities::Rule
182
199
  end
183
200
 
184
201
  desc "Delete a rule", {
@@ -190,18 +207,27 @@ module Mihari
190
207
  requires :id, type: String
191
208
  end
192
209
  delete "/:id" do
210
+ extend Dry::Monads[:result, :try]
211
+
193
212
  id = params["id"].to_s
194
213
 
195
- begin
214
+ result = Try do
196
215
  rule = Mihari::Rule.find(id)
197
- rescue ActiveRecord::RecordNotFound
198
- error!({ message: "ID:#{id} is not found" }, 404)
199
- end
216
+ rule.destroy
217
+ end.to_result
200
218
 
201
- rule.destroy
219
+ if result.success?
220
+ status 204
221
+ return present({ message: "ID:#{id} is deleted" }, with: Entities::Message)
222
+ end
202
223
 
203
- status 204
204
- present({ message: "ID:#{id} is deleted" }, with: Entities::Message)
224
+ failure = result.failure
225
+ case failure
226
+ when ActiveRecord::RecordNotFound
227
+ error!({ message: "ID:#{id} is not found" }, 404)
228
+ else
229
+ raise failure
230
+ end
205
231
  end
206
232
  end
207
233
  end
@@ -23,16 +23,26 @@ module Mihari
23
23
  requires :name, type: String
24
24
  end
25
25
  delete "/:name" do
26
+ extend Dry::Monads[:result, :try]
27
+
26
28
  name = params[:name].to_s
27
29
 
28
- begin
30
+ result = Try do
29
31
  Mihari::Tag.where(name: name).destroy_all
30
- rescue ActiveRecord::RecordNotFound
31
- error!({ message: "Name:#{name} is not found" }, 404)
32
+ end.to_result
33
+
34
+ if result.success?
35
+ status 204
36
+ return present({ message: "" }, with: Entities::Message)
32
37
  end
33
38
 
34
- status 204
35
- present({ message: "" }, with: Entities::Message)
39
+ failure = result.failure
40
+ case failure
41
+ when ActiveRecord::RecordNotFound
42
+ error!({ message: "Name:#{name} is not found" }, 404)
43
+ else
44
+ raise failure
45
+ end
36
46
  end
37
47
  end
38
48
  end