mihari 5.7.1 → 6.0.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/config.ru +2 -0
  3. data/lib/mihari/analyzers/dnstwister.rb +2 -4
  4. data/lib/mihari/analyzers/urlscan.rb +1 -4
  5. data/lib/mihari/cli/main.rb +4 -12
  6. data/lib/mihari/clients/base.rb +23 -1
  7. data/lib/mihari/clients/binaryedge.rb +1 -3
  8. data/lib/mihari/clients/censys.rb +1 -2
  9. data/lib/mihari/clients/crtsh.rb +2 -3
  10. data/lib/mihari/clients/dnstwister.rb +1 -2
  11. data/lib/mihari/clients/fofa.rb +1 -3
  12. data/lib/mihari/clients/greynoise.rb +1 -2
  13. data/lib/mihari/clients/hunterhow.rb +1 -2
  14. data/lib/mihari/clients/misp.rb +1 -2
  15. data/lib/mihari/clients/onyphe.rb +1 -2
  16. data/lib/mihari/clients/otx.rb +2 -14
  17. data/lib/mihari/clients/passivetotal.rb +3 -16
  18. data/lib/mihari/clients/publsedive.rb +2 -17
  19. data/lib/mihari/clients/securitytrails.rb +3 -25
  20. data/lib/mihari/clients/shodan.rb +1 -2
  21. data/lib/mihari/clients/the_hive.rb +1 -2
  22. data/lib/mihari/clients/urlscan.rb +1 -2
  23. data/lib/mihari/clients/virustotal.rb +3 -17
  24. data/lib/mihari/clients/zoomeye.rb +9 -19
  25. data/lib/mihari/commands/alert.rb +11 -11
  26. data/lib/mihari/commands/database.rb +4 -2
  27. data/lib/mihari/commands/mixins.rb +11 -0
  28. data/lib/mihari/commands/search.rb +15 -15
  29. data/lib/mihari/constants.rb +1 -1
  30. data/lib/mihari/database.rb +3 -5
  31. data/lib/mihari/emitters/slack.rb +3 -6
  32. data/lib/mihari/emitters/the_hive.rb +3 -7
  33. data/lib/mihari/enrichers/google_public_dns.rb +2 -7
  34. data/lib/mihari/enrichers/ipinfo.rb +1 -3
  35. data/lib/mihari/enrichers/shodan.rb +1 -3
  36. data/lib/mihari/enrichers/whois.rb +0 -4
  37. data/lib/mihari/http.rb +13 -11
  38. data/lib/mihari/mixins/refang.rb +1 -4
  39. data/lib/mihari/mixins/unwrap_error.rb +27 -0
  40. data/lib/mihari/models/alert.rb +1 -3
  41. data/lib/mihari/models/artifact.rb +5 -7
  42. data/lib/mihari/models/rule.rb +1 -2
  43. data/lib/mihari/rule.rb +14 -10
  44. data/lib/mihari/service.rb +2 -0
  45. data/lib/mihari/services/rule_builder.rb +2 -4
  46. data/lib/mihari/structs/fofa.rb +2 -0
  47. data/lib/mihari/version.rb +1 -1
  48. data/lib/mihari/web/app.rb +3 -1
  49. data/lib/mihari/web/endpoints/alerts.rb +14 -18
  50. data/lib/mihari/web/endpoints/artifacts.rb +17 -22
  51. data/lib/mihari/web/endpoints/configs.rb +0 -1
  52. data/lib/mihari/web/endpoints/ip_addresses.rb +1 -1
  53. data/lib/mihari/web/endpoints/rules.rb +27 -32
  54. data/lib/mihari/web/endpoints/tags.rb +7 -9
  55. data/lib/mihari/web/middleware/connection_adapter.rb +3 -5
  56. data/lib/mihari/web/middleware/error_notification_adapter.rb +15 -6
  57. data/lib/mihari/web/public/assets/{index-07fafab5.js → index-07cddfcd.js} +44 -44
  58. data/lib/mihari/web/public/index.html +1 -1
  59. data/lib/mihari/web/public/redoc-static.html +381 -401
  60. data/lib/mihari.rb +1 -2
  61. data/mihari.gemspec +14 -16
  62. data/mkdocs.yml +14 -8
  63. data/requirements.txt +1 -1
  64. metadata +81 -39
  65. data/lib/mihari/mixins/error_notification.rb +0 -21
  66. data/lib/mihari/services/rule_runner.rb +0 -19
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Make possible to use upper case acronyms in class names
4
- ActiveSupport::Inflector.inflections(:en) do |inflect|
5
- inflect.acronym "CPE"
6
- end
4
+ ActiveSupport::Inflector.inflections(:en) { |inflect| inflect.acronym "CPE" }
7
5
 
8
6
  def env
9
7
  ENV["APP_ENV"] || ENV["RACK_ENV"]
@@ -134,7 +132,7 @@ module Mihari
134
132
  class Database
135
133
  class << self
136
134
  #
137
- # DB migraration
135
+ # DB migration
138
136
  #
139
137
  # @param [Symbol] direction
140
138
  #
@@ -175,7 +173,7 @@ module Mihari
175
173
  Mihari::Database.connect
176
174
  yield
177
175
  rescue ActiveRecord::StatementInvalid
178
- Mihari.logger.error("You haven't finished the DB migration! Please run 'mihari db migrate'.")
176
+ Mihari.logger.error("The DB migration is not yet complete. Please run 'mihari db migrate'.")
179
177
  ensure
180
178
  Mihari::Database.close
181
179
  end
@@ -192,9 +192,7 @@ module Mihari
192
192
  # @return [Array<Mihari::Emitters::Attachment>]
193
193
  #
194
194
  def attachments
195
- artifacts.map do |artifact|
196
- Attachment.new(data: artifact.data, data_type: artifact.data_type).to_a
197
- end.flatten
195
+ artifacts.map { |artifact| Attachment.new(data: artifact.data, data_type: artifact.data_type).to_a }.flatten
198
196
  end
199
197
 
200
198
  #
@@ -205,7 +203,6 @@ module Mihari
205
203
  def text
206
204
  tags = rule.tags
207
205
  tags = ["N/A"] if tags.empty?
208
-
209
206
  [
210
207
  "*#{rule.title}*",
211
208
  "*Desc.*: #{rule.description}",
@@ -217,10 +214,10 @@ module Mihari
217
214
  # @param [Array<Mihari::Models::Artifact>] artifacts
218
215
  #
219
216
  def call(artifacts)
220
- return if artifacts.empty?
221
-
222
217
  @artifacts = artifacts
223
218
 
219
+ return if artifacts.empty?
220
+
224
221
  notifier.post(text: text, attachments: attachments, mrkdwn: true)
225
222
  end
226
223
 
@@ -43,10 +43,10 @@ module Mihari
43
43
  # @param [Array<Mihari::Models::Artifact>] artifacts
44
44
  #
45
45
  def call(artifacts)
46
- return if artifacts.empty?
47
-
48
46
  @artifacts = artifacts
49
47
 
48
+ return if artifacts.empty?
49
+
50
50
  client.alert payload
51
51
  end
52
52
 
@@ -61,11 +61,7 @@ module Mihari
61
61
  @normalized_api_version ||= [].tap do |out|
62
62
  # v4 does not have version prefix in path (/api/)
63
63
  # v5 has version prefix in path (/api/v1/)
64
- table = {
65
- "" => nil,
66
- "v4" => nil,
67
- "v5" => "v1"
68
- }
64
+ table = { "" => nil, "v4" => nil, "v5" => "v1" }
69
65
  out << table[api_version.to_s.downcase]
70
66
  end.first
71
67
  end
@@ -14,9 +14,7 @@ module Mihari
14
14
  # @return [Array<Mihari::Structs::GooglePublicDNS::Response>]
15
15
  #
16
16
  def call(name)
17
- %w[A AAAA CNAME TXT NS].filter_map do |resource_type|
18
- query_by_type(name, resource_type)
19
- end
17
+ %w[A AAAA CNAME TXT NS].filter_map { |resource_type| query_by_type(name, resource_type) }
20
18
  end
21
19
 
22
20
  #
@@ -31,10 +29,7 @@ module Mihari
31
29
  url = "https://dns.google/resolve"
32
30
  params = { name: name, type: resource_type }
33
31
  res = http.get(url, params: params)
34
-
35
- data = JSON.parse(res.body.to_s)
36
-
37
- Structs::GooglePublicDNS::Response.from_dynamic! data
32
+ Structs::GooglePublicDNS::Response.from_dynamic! JSON.parse(res.body.to_s)
38
33
  rescue HTTPError
39
34
  nil
40
35
  end
@@ -33,9 +33,7 @@ module Mihari
33
33
  def call(ip)
34
34
  url = "https://ipinfo.io/#{ip}/json"
35
35
  res = http.get(url)
36
- data = JSON.parse(res.body.to_s)
37
-
38
- Structs::IPInfo::Response.from_dynamic! data
36
+ Structs::IPInfo::Response.from_dynamic! JSON.parse(res.body.to_s)
39
37
  end
40
38
 
41
39
  private
@@ -16,9 +16,7 @@ module Mihari
16
16
  def call(ip)
17
17
  url = "https://internetdb.shodan.io/#{ip}"
18
18
  res = http.get(url)
19
- data = JSON.parse(res.body.to_s)
20
-
21
- Structs::Shodan::InternetDBResponse.from_dynamic! data
19
+ Structs::Shodan::InternetDBResponse.from_dynamic! JSON.parse(res.body.to_s)
22
20
  end
23
21
 
24
22
  private
@@ -52,10 +52,6 @@ module Mihari
52
52
  whois_record
53
53
  end
54
54
 
55
- def reset_cache
56
- @memo = {}
57
- end
58
-
59
55
  private
60
56
 
61
57
  #
data/lib/mihari/http.rb CHANGED
@@ -9,14 +9,13 @@ module Mihari
9
9
  #
10
10
  class BetterError < ::HTTP::Feature
11
11
  def wrap_response(response)
12
- unless response.status.success?
13
- raise StatusCodeError.new(
14
- "Unsuccessful response code returned: #{response.code}",
15
- response.code,
16
- response.body.to_s
17
- )
18
- end
19
- response
12
+ return response if response.status.success?
13
+
14
+ raise StatusCodeError.new(
15
+ "Unsuccessful response code returned: #{response.code}",
16
+ response.code,
17
+ response.body.to_s
18
+ )
20
19
  end
21
20
 
22
21
  def on_error(_request, error)
@@ -35,12 +34,15 @@ module Mihari
35
34
  #
36
35
  # @param [Integer, nil] timeout
37
36
  # @param [Hash] headers
37
+ # @param [Boolean] raise_exception
38
38
  #
39
39
  # @return [::HTTP::Client]
40
40
  #
41
- def build(headers: {}, timeout: nil)
42
- client = ::HTTP.use(:better_error).headers(headers)
43
- client.timeout(timeout) unless timeout.nil?
41
+ # @param [Object] raise_exception
42
+ def build(headers: {}, timeout: nil, raise_exception: true)
43
+ client = raise_exception ? ::HTTP.use(:better_error) : ::HTTP
44
+ client = client.headers(headers)
45
+ client = client.timeout(timeout) unless timeout.nil?
44
46
  client
45
47
  end
46
48
  end
@@ -14,10 +14,7 @@ module Mihari
14
14
  # @return [String]
15
15
  #
16
16
  def refang(indicator)
17
- return indicator.gsub("[.]", ".").gsub("(.)", ".") if indicator.is_a?(String)
18
-
19
- # for RSpec & Ruby 2.7
20
- indicator
17
+ indicator.gsub("[.]", ".").gsub("(.)", ".")
21
18
  end
22
19
  end
23
20
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mihari
4
+ module Mixins
5
+ #
6
+ # Unwrap error mixins
7
+ #
8
+ module UnwrapError
9
+ def unwrap_error(err)
10
+ return err unless err.is_a?(Dry::Monads::UnwrapError)
11
+
12
+ # NOTE: UnwrapError's receiver can be either of:
13
+ # - Dry::Monads::Try::Error
14
+ # - Dry::Monads::Result::Failure
15
+ receiver = err.receiver
16
+ case receiver
17
+ when Dry::Monads::Try::Error
18
+ receiver.exception
19
+ when Dry::Monads::Failure
20
+ receiver.failure
21
+ else
22
+ err
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -30,7 +30,6 @@ module Mihari
30
30
  offset = (page - 1) * limit
31
31
 
32
32
  relation = build_relation(filter.without_pagination)
33
-
34
33
  alert_ids = relation.limit(limit).offset(offset).order(id: :desc).pluck(:id).uniq
35
34
  eager_load(:artifacts, :tags).where(id: [alert_ids]).order(id: :desc)
36
35
  end
@@ -75,8 +74,7 @@ module Mihari
75
74
  def build_relation(filter)
76
75
  artifact_ids = get_artifact_ids_by_filter(filter)
77
76
 
78
- relation = self
79
- relation = relation.includes(:artifacts, :tags)
77
+ relation = includes(:artifacts, :tags)
80
78
 
81
79
  relation = relation.where(artifacts: { id: artifact_ids }) unless artifact_ids.empty?
82
80
  relation = relation.where(tags: { name: filter.tag_name }) if filter.tag_name
@@ -78,7 +78,7 @@ module Mihari
78
78
  end
79
79
 
80
80
  #
81
- # Enrich(add) whois record
81
+ # Enrich whois record
82
82
  #
83
83
  # @param [Mihari::Enrichers::Whois] enricher
84
84
  #
@@ -89,7 +89,7 @@ module Mihari
89
89
  end
90
90
 
91
91
  #
92
- # Enrich(add) DNS records
92
+ # Enrich DNS records
93
93
  #
94
94
  # @param [Mihari::Enrichers::GooglePublicDNS] enricher
95
95
  #
@@ -100,7 +100,7 @@ module Mihari
100
100
  end
101
101
 
102
102
  #
103
- # Enrich(add) reverse DNS names
103
+ # Enrich reverse DNS names
104
104
  #
105
105
  # @param [Mihari::Enrichers::Shodan] enricher
106
106
  #
@@ -111,7 +111,7 @@ module Mihari
111
111
  end
112
112
 
113
113
  #
114
- # Enrich(add) geolocation
114
+ # Enrich geolocation
115
115
  #
116
116
  # @param [Mihari::Enrichers::IPInfo] enricher
117
117
  #
@@ -192,9 +192,7 @@ module Mihari
192
192
  #
193
193
  def enrich_by_enricher(enricher)
194
194
  methods = ENRICH_METHODS_BY_ENRICHER[enricher.class] || []
195
- methods.each do |method|
196
- send(method, enricher) if respond_to?(method)
197
- end
195
+ methods.each { |method| send(method, enricher) if respond_to?(method) }
198
196
  end
199
197
 
200
198
  private
@@ -66,8 +66,7 @@ module Mihari
66
66
  # @return [Mihari::Models::Rule]
67
67
  #
68
68
  def build_relation(filter)
69
- relation = self
70
- relation = relation.includes(alerts: :tags)
69
+ relation = includes(alerts: :tags)
71
70
 
72
71
  relation = relation.where(alerts: { tags: { name: filter.tag_name } }) if filter.tag_name
73
72
 
data/lib/mihari/rule.rb CHANGED
@@ -113,15 +113,15 @@ module Mihari
113
113
  analyzers.flat_map do |analyzer|
114
114
  # @type [Dry::Monads::Result::Success<Array<Mihari::Models::Artifact>>, Dry::Monads::Result::Failure]
115
115
  result = analyzer.result
116
-
117
- if result.failure?
118
- raise result.failure unless analyzer.ignore_error?
119
- else
116
+ case result
117
+ when Success
120
118
  artifacts = result.value!
121
119
  artifacts.map do |artifact|
122
120
  artifact.rule_id = id
123
121
  artifact
124
122
  end
123
+ else
124
+ raise result.failure unless analyzer.ignore_error?
125
125
  end
126
126
  end.compact
127
127
  end
@@ -177,8 +177,14 @@ module Mihari
177
177
  results = Parallel.map(emitters) { |emitter| emitter.result enriched_artifacts }
178
178
  results.zip(emitters).map do |result_and_emitter|
179
179
  result, emitter = result_and_emitter
180
- Mihari.logger.info "Emission by #{emitter.class} is failed: #{result.failure}" if result.failure?
181
- Mihari.logger.info "Emission by #{emitter.class} is succeeded" if result.success?
180
+
181
+ case result
182
+ when Success
183
+ Mihari.logger.info "Emission by #{emitter.class} succeed"
184
+ else
185
+ Mihari.logger.info "Emission by #{emitter.class} failed: #{result.failure}"
186
+ end
187
+
182
188
  result.value_or nil
183
189
  end.compact
184
190
  end
@@ -289,8 +295,7 @@ module Mihari
289
295
  @analyzers ||= queries.map do |query_params|
290
296
  analyzer_name = query_params[:analyzer]
291
297
  klass = get_analyzer_class(analyzer_name)
292
- klass.from_query(query_params)
293
- end.map do |analyzer|
298
+ analyzer = klass.from_query(query_params)
294
299
  analyzer.validate_configuration!
295
300
  analyzer
296
301
  end
@@ -320,8 +325,7 @@ module Mihari
320
325
  %i[emitter options].each { |key| params.delete key }
321
326
 
322
327
  klass = get_emitter_class(name)
323
- klass.new(rule: self, options: options, **params)
324
- end.map do |emitter|
328
+ emitter = klass.new(rule: self, options: options, **params)
325
329
  emitter.validate_configuration!
326
330
  emitter
327
331
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mihari
2
4
  #
3
5
  # Base class for services
@@ -20,10 +20,8 @@ module Mihari
20
20
  # @return [Hash]
21
21
  #
22
22
  def data
23
- if Mihari::Models::Rule.exists?(path_or_id)
24
- rule = Mihari::Models::Rule.find(path_or_id)
25
- return rule.data
26
- end
23
+ result = Try { Mihari::Models::Rule.find path_or_id }.to_result
24
+ return result.value! if result.success?
27
25
 
28
26
  raise ArgumentError, "#{path_or_id} does not exist" unless Pathname(path_or_id).exist?
29
27
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mihari
2
4
  module Structs
3
5
  module Fofa
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "5.7.1"
4
+ VERSION = "6.0.0"
5
5
  end
@@ -39,7 +39,7 @@ module Mihari
39
39
 
40
40
  def call(env)
41
41
  status, headers, body = API.call(env)
42
- return [status, headers, body] unless headers["X-Cascade"] == "pass"
42
+ return [status, headers, body] unless headers["x-cascade"] == "pass"
43
43
 
44
44
  # Check if the App wants us to pass the response along to others
45
45
  request_path = env["PATH_INFO"]
@@ -64,6 +64,8 @@ module Mihari
64
64
  use Middleware::ConnectionAdapter
65
65
  use Middleware::ErrorNotificationAdapter
66
66
 
67
+ use BetterErrors::Middleware if ENV["RACK_ENV"] == "development" && defined?(BetterErrors::Middleware)
68
+
67
69
  run App.new
68
70
  end.to_app
69
71
  end
@@ -77,7 +77,6 @@ module Mihari
77
77
  desc "Search alerts", {
78
78
  is_array: true,
79
79
  success: Entities::AlertsWithPagination,
80
- failure: [{ code: 404, message: "Not found", model: Entities::Message }],
81
80
  summary: "Search alerts"
82
81
  }
83
82
  params do
@@ -103,31 +102,30 @@ module Mihari
103
102
  end
104
103
 
105
104
  desc "Delete an alert", {
106
- success: Entities::Message,
107
- failure: [{ code: 404, message: "Not found", model: Entities::Message }],
105
+ success: { code: 204, model: Entities::Message },
106
+ failure: [{ code: 404, model: Entities::Message }],
108
107
  summary: "Delete an alert"
109
108
  }
110
109
  params do
111
110
  requires :id, type: Integer
112
111
  end
113
112
  delete "/:id" do
113
+ status 204
114
+
114
115
  id = params["id"].to_i
115
116
  result = AlertDestroyer.result(id)
116
- if result.success?
117
- status 204
118
- return present({ message: "" }, with: Entities::Message)
119
- end
117
+ return present({ message: "" }, with: Entities::Message) if result.success?
120
118
 
121
- failure = result.failure
122
- case failure
119
+ case result.failure
123
120
  when ActiveRecord::RecordNotFound
124
121
  error!({ message: "ID:#{id} is not found" }, 404)
125
122
  end
126
- raise failure
123
+ raise result.failure
127
124
  end
128
125
 
129
126
  desc "Create an alert", {
130
- success: Entities::Alert,
127
+ success: { code: 201, model: Entities::Alert },
128
+ failure: [{ code: 404, model: Entities::Message }],
131
129
  summary: "Create an alert"
132
130
  }
133
131
  params do
@@ -135,18 +133,16 @@ module Mihari
135
133
  requires :artifacts, type: Array, documentation: { type: String, is_array: true, param_type: "body" }
136
134
  end
137
135
  post "/" do
136
+ status 201
137
+
138
138
  result = AlertCreator.result(params)
139
- if result.success?
140
- status 201
141
- return present(result.value!, with: Entities::Alert)
142
- end
139
+ return present(result.value!, with: Entities::Alert) if result.success?
143
140
 
144
- failure = result.failure
145
- case failure
141
+ case result.failure
146
142
  when ActiveRecord::RecordNotFound
147
143
  error!({ message: "Rule:#{params["ruleId"]} is not found" }, 404)
148
144
  end
149
- raise failure
145
+ raise result.failure
150
146
  end
151
147
  end
152
148
  end
@@ -64,7 +64,7 @@ module Mihari
64
64
  namespace :artifacts do
65
65
  desc "Get an artifact", {
66
66
  success: Entities::Artifact,
67
- failure: [{ code: 404, message: "Not found", model: Entities::Message }],
67
+ failure: [{ code: 404, model: Entities::Message }],
68
68
  summary: "Get an artifact"
69
69
  }
70
70
  params do
@@ -75,60 +75,55 @@ module Mihari
75
75
  result = ArtifactGetter.result(id)
76
76
  return present(result.value!, with: Entities::Artifact) if result.success?
77
77
 
78
- failure = result.failure
79
- case failure
78
+ case result.failure
80
79
  when ActiveRecord::RecordNotFound
81
80
  error!({ message: "ID:#{id} is not found" }, 404)
82
81
  end
83
- raise failure
82
+ raise result.failure
84
83
  end
85
84
 
86
85
  desc "Enrich an artifact", {
87
- success: Entities::Message,
88
- failure: [{ code: 404, message: "Not found", model: Entities::Message }],
86
+ success: { code: 201, model: Entities::Message },
87
+ failure: [{ code: 404, model: Entities::Message }],
89
88
  summary: "Enrich an artifact"
90
89
  }
91
90
  params do
92
91
  requires :id, type: Integer
93
92
  end
94
93
  get "/:id/enrich" do
94
+ status 201
95
+
95
96
  id = params["id"].to_i
96
97
  result = ArtifactEnricher.result(id)
97
- if result.success?
98
- status 201
99
- return present({ message: "" }, with: Entities::Message)
100
- end
98
+ return present({ message: "#{id} has been enriched" }, with: Entities::Message) if result.success?
101
99
 
102
- failure = result.failure
103
- case failure
100
+ case result.failure
104
101
  when ActiveRecord::RecordNotFound
105
102
  error!({ message: "ID:#{id} is not found" }, 404)
106
103
  end
107
- raise failure
104
+ raise result.failure
108
105
  end
109
106
 
110
107
  desc "Delete an artifact", {
111
- success: Entities::Message,
112
- failure: [{ code: 404, message: "Not found", model: Entities::Message }],
108
+ success: { code: 204, model: Entities::Message },
109
+ failure: [{ code: 404, model: Entities::Message }],
113
110
  summary: "Delete an artifact"
114
111
  }
115
112
  params do
116
113
  requires :id, type: Integer
117
114
  end
118
115
  delete "/:id" do
116
+ status 204
117
+
119
118
  id = params["id"].to_i
120
119
  result = ArtifactDestroyer.result(id)
121
- if result.success?
122
- status 204
123
- return present({ message: "" }, with: Entities::Message)
124
- end
120
+ return present({ message: "" }, with: Entities::Message) if result.success?
125
121
 
126
- failure = result.failure
127
- case failure
122
+ case result.failure
128
123
  when ActiveRecord::RecordNotFound
129
124
  error!({ message: "ID:#{id} is not found" }, 404)
130
125
  end
131
- raise failure
126
+ raise result.failure
132
127
  end
133
128
  end
134
129
  end
@@ -17,7 +17,6 @@ module Mihari
17
17
  configs = (Mihari.analyzers + Mihari.emitters + Mihari.enrichers).filter_map do |klass|
18
18
  Mihari::Structs::Config.from_class(klass)
19
19
  end
20
-
21
20
  present(configs, with: Entities::Config)
22
21
  end
23
22
  end
@@ -21,7 +21,7 @@ module Mihari
21
21
  namespace :ip_addresses do
22
22
  desc "Get an IP address", {
23
23
  success: Entities::IPAddress,
24
- failure: [{ code: 404, message: "Not found", model: Entities::Message }],
24
+ failure: [{ code: 404, model: Entities::Message }],
25
25
  summary: "Get an IP address"
26
26
  }
27
27
  params do