mihari 7.3.2 → 7.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +0 -2
  4. data/.shadowenv.d/.gitignore +2 -0
  5. data/.shadowenv.d/000_unset_all.lisp +39 -0
  6. data/README.md +0 -8
  7. data/lib/mihari/analyzers/base.rb +2 -2
  8. data/lib/mihari/analyzers/binaryedge.rb +5 -5
  9. data/lib/mihari/analyzers/censys.rb +6 -6
  10. data/lib/mihari/analyzers/circl.rb +2 -2
  11. data/lib/mihari/analyzers/crtsh.rb +3 -3
  12. data/lib/mihari/analyzers/dnstwister.rb +2 -2
  13. data/lib/mihari/analyzers/feed.rb +12 -18
  14. data/lib/mihari/analyzers/fofa.rb +6 -6
  15. data/lib/mihari/analyzers/greynoise.rb +5 -5
  16. data/lib/mihari/analyzers/hunterhow.rb +4 -4
  17. data/lib/mihari/analyzers/onyphe.rb +5 -5
  18. data/lib/mihari/analyzers/otx.rb +2 -2
  19. data/lib/mihari/analyzers/passivetotal.rb +3 -3
  20. data/lib/mihari/analyzers/pulsedive.rb +3 -3
  21. data/lib/mihari/analyzers/securitytrails.rb +4 -4
  22. data/lib/mihari/analyzers/shodan.rb +5 -5
  23. data/lib/mihari/analyzers/urlscan.rb +5 -5
  24. data/lib/mihari/analyzers/virustotal.rb +4 -4
  25. data/lib/mihari/analyzers/virustotal_intelligence.rb +5 -5
  26. data/lib/mihari/analyzers/zoomeye.rb +5 -5
  27. data/lib/mihari/cli/application.rb +1 -1
  28. data/lib/mihari/clients/base.rb +5 -5
  29. data/lib/mihari/clients/binaryedge.rb +6 -6
  30. data/lib/mihari/clients/censys.rb +4 -4
  31. data/lib/mihari/clients/circl.rb +2 -2
  32. data/lib/mihari/clients/crtsh.rb +2 -2
  33. data/lib/mihari/clients/dnstwister.rb +1 -1
  34. data/lib/mihari/clients/fofa.rb +4 -4
  35. data/lib/mihari/clients/google_public_dns.rb +2 -2
  36. data/lib/mihari/clients/greynoise.rb +4 -4
  37. data/lib/mihari/clients/hunterhow.rb +10 -10
  38. data/lib/mihari/clients/misp.rb +1 -1
  39. data/lib/mihari/clients/mmdb.rb +1 -1
  40. data/lib/mihari/clients/onyphe.rb +4 -4
  41. data/lib/mihari/clients/otx.rb +1 -1
  42. data/lib/mihari/clients/passivetotal.rb +5 -5
  43. data/lib/mihari/clients/publsedive.rb +3 -3
  44. data/lib/mihari/clients/securitytrails.rb +6 -6
  45. data/lib/mihari/clients/shodan.rb +6 -6
  46. data/lib/mihari/clients/shodan_internet_db.rb +1 -1
  47. data/lib/mihari/clients/the_hive.rb +2 -2
  48. data/lib/mihari/clients/urlscan.rb +4 -4
  49. data/lib/mihari/clients/virustotal.rb +4 -4
  50. data/lib/mihari/clients/zoomeye.rb +12 -12
  51. data/lib/mihari/commands/alert.rb +1 -1
  52. data/lib/mihari/commands/artifact.rb +1 -1
  53. data/lib/mihari/commands/rule.rb +1 -1
  54. data/lib/mihari/commands/tag.rb +1 -1
  55. data/lib/mihari/concerns/autonomous_system_normalizable.rb +1 -4
  56. data/lib/mihari/concerns/configurable.rb +1 -1
  57. data/lib/mihari/concerns/database_connectable.rb +2 -2
  58. data/lib/mihari/concerns/retriable.rb +1 -1
  59. data/lib/mihari/config.rb +6 -2
  60. data/lib/mihari/constants.rb +2 -2
  61. data/lib/mihari/emitters/base.rb +2 -2
  62. data/lib/mihari/emitters/database.rb +1 -1
  63. data/lib/mihari/emitters/misp.rb +12 -4
  64. data/lib/mihari/emitters/slack.rb +9 -9
  65. data/lib/mihari/emitters/the_hive.rb +9 -4
  66. data/lib/mihari/emitters/webhook.rb +4 -4
  67. data/lib/mihari/enrichers/base.rb +1 -1
  68. data/lib/mihari/enrichers/google_public_dns.rb +1 -1
  69. data/lib/mihari/enrichers/mmdb.rb +1 -1
  70. data/lib/mihari/enrichers/shodan.rb +3 -3
  71. data/lib/mihari/enrichers/whois.rb +2 -2
  72. data/lib/mihari/entities/alert.rb +6 -6
  73. data/lib/mihari/entities/artifact.rb +17 -17
  74. data/lib/mihari/entities/autonomous_system.rb +1 -1
  75. data/lib/mihari/entities/config.rb +8 -4
  76. data/lib/mihari/entities/cpe.rb +2 -2
  77. data/lib/mihari/entities/dns.rb +3 -3
  78. data/lib/mihari/entities/geolocation.rb +3 -3
  79. data/lib/mihari/entities/ip_address.rb +3 -3
  80. data/lib/mihari/entities/messages.rb +3 -3
  81. data/lib/mihari/entities/pagination.rb +3 -3
  82. data/lib/mihari/entities/port.rb +2 -2
  83. data/lib/mihari/entities/reverse_dns.rb +2 -2
  84. data/lib/mihari/entities/rule.rb +8 -8
  85. data/lib/mihari/entities/tag.rb +3 -3
  86. data/lib/mihari/entities/vulnerability.rb +2 -2
  87. data/lib/mihari/entities/whois.rb +7 -7
  88. data/lib/mihari/errors.rb +1 -1
  89. data/lib/mihari/models/artifact.rb +2 -2
  90. data/lib/mihari/models/port.rb +1 -1
  91. data/lib/mihari/models/tag.rb +3 -0
  92. data/lib/mihari/rule.rb +10 -14
  93. data/lib/mihari/schemas/emitter.rb +2 -0
  94. data/lib/mihari/services/feed.rb +3 -3
  95. data/lib/mihari/services/getters.rb +1 -1
  96. data/lib/mihari/services/proxies.rb +1 -1
  97. data/lib/mihari/services/renderer.rb +2 -0
  98. data/lib/mihari/services/searchers.rb +1 -1
  99. data/lib/mihari/sidekiq/application.rb +2 -2
  100. data/lib/mihari/structs/censys.rb +4 -4
  101. data/lib/mihari/structs/google_public_dns.rb +3 -3
  102. data/lib/mihari/structs/greynoise.rb +2 -2
  103. data/lib/mihari/structs/onyphe.rb +3 -3
  104. data/lib/mihari/structs/shodan.rb +10 -10
  105. data/lib/mihari/structs/urlscan.rb +1 -1
  106. data/lib/mihari/structs/virustotal_intelligence.rb +2 -2
  107. data/lib/mihari/version.rb +1 -1
  108. data/lib/mihari/web/api.rb +1 -1
  109. data/lib/mihari/web/application.rb +1 -1
  110. data/lib/mihari/web/endpoints/alerts.rb +12 -12
  111. data/lib/mihari/web/endpoints/artifacts.rb +11 -11
  112. data/lib/mihari/web/endpoints/configs.rb +7 -2
  113. data/lib/mihari/web/endpoints/ip_addresses.rb +5 -5
  114. data/lib/mihari/web/endpoints/rules.rb +26 -26
  115. data/lib/mihari/web/endpoints/tags.rb +4 -4
  116. data/lib/mihari/web/public/assets/index-DsMIBgVm.js +1787 -0
  117. data/lib/mihari/web/public/assets/{index-ReF8ffd-.css → index-qLffdzXi.css} +1 -1
  118. data/lib/mihari/web/public/index.html +2 -2
  119. data/lib/mihari/web/public/redoc-static.html +2 -2
  120. data/lib/mihari.rb +1 -1
  121. data/mihari.gemspec +15 -15
  122. data/renovate.json +1 -3
  123. data/requirements.txt +1 -1
  124. metadata +37 -36
  125. data/.standard.yml +0 -4
  126. data/lib/mihari/web/public/assets/index-lRP933ks.js +0 -1787
  127. /data/lib/mihari/web/public/assets/{mode-yaml-BC4MIiYj.js → mode-yaml-ELgwiJiP.js} +0 -0
@@ -3,17 +3,17 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Rule < Grape::Entity
6
- expose :id, documentation: { type: String, required: true }
7
- expose :title, documentation: { type: String, required: true }
8
- expose :description, documentation: { type: String, required: true }
9
- expose :yaml, documentation: { type: String, required: true }
10
- expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
11
- expose :updated_at, documentation: { type: DateTime, required: true }, as: :updatedAt
12
- expose :tags, using: Entities::Tag, documentation: { type: Entities::Tag, is_array: true, required: true }
6
+ expose :id, documentation: {type: String, required: true}
7
+ expose :title, documentation: {type: String, required: true}
8
+ expose :description, documentation: {type: String, required: true}
9
+ expose :yaml, documentation: {type: String, required: true}
10
+ expose :created_at, documentation: {type: DateTime, required: true}, as: :createdAt
11
+ expose :updated_at, documentation: {type: DateTime, required: true}, as: :updatedAt
12
+ expose :tags, using: Entities::Tag, documentation: {type: Entities::Tag, is_array: true, required: true}
13
13
  end
14
14
 
15
15
  class RulesWithPagination < Pagination
16
- expose :results, using: Entities::Rule, documentation: { type: Entities::Rule, is_array: true, required: true }
16
+ expose :results, using: Entities::Rule, documentation: {type: Entities::Rule, is_array: true, required: true}
17
17
  end
18
18
  end
19
19
  end
@@ -3,12 +3,12 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Tag < Grape::Entity
6
- expose :id, documentation: { type: Integer, required: true }
7
- expose :name, documentation: { type: String, required: true }
6
+ expose :id, documentation: {type: Integer, required: true}
7
+ expose :name, documentation: {type: String, required: true}
8
8
  end
9
9
 
10
10
  class TagsWithPagination < Pagination
11
- expose :results, using: Entities::Tag, documentation: { type: Entities::Tag, is_array: true, required: true }
11
+ expose :results, using: Entities::Tag, documentation: {type: Entities::Tag, is_array: true, required: true}
12
12
  end
13
13
  end
14
14
  end
@@ -3,8 +3,8 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Vulnerability < Grape::Entity
6
- expose :name, documentation: { type: String, required: true }
7
- expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
6
+ expose :name, documentation: {type: String, required: true}
7
+ expose :created_at, documentation: {type: DateTime, required: true}, as: :createdAt
8
8
  end
9
9
  end
10
10
  end
@@ -3,15 +3,15 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class WhoisRecord < Grape::Entity
6
- expose :domain, documentation: { type: String, required: true }
7
- expose :created_on, documentation: { type: Date, required: false }, as: :createdOn
8
- expose :updated_on, documentation: { type: Date, required: false }, as: :updatedOn
9
- expose :expires_on, documentation: { type: Date, required: false }, as: :expiresOn
10
- expose :registrar, documentation: { type: Hash, required: false }
11
- expose :contacts, documentation: { type: Hash, is_array: true, required: true } do |whois_record, _options|
6
+ expose :domain, documentation: {type: String, required: true}
7
+ expose :created_on, documentation: {type: Date, required: false}, as: :createdOn
8
+ expose :updated_on, documentation: {type: Date, required: false}, as: :updatedOn
9
+ expose :expires_on, documentation: {type: Date, required: false}, as: :expiresOn
10
+ expose :registrar, documentation: {type: Hash, required: false}
11
+ expose :contacts, documentation: {type: Hash, is_array: true, required: true} do |whois_record, _options|
12
12
  whois_record.contacts.map(&:to_camelback_keys)
13
13
  end
14
- expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
14
+ expose :created_at, documentation: {type: DateTime, required: true}, as: :createdAt
15
15
  end
16
16
  end
17
17
  end
data/lib/mihari/errors.rb CHANGED
@@ -74,7 +74,7 @@ module Mihari
74
74
  end
75
75
 
76
76
  def detail
77
- { status_code: status_code, body: body }
77
+ {status_code:, body:}
78
78
  end
79
79
  end
80
80
 
@@ -159,8 +159,8 @@ module Mihari
159
159
  #
160
160
  def unique?(base_time: nil, artifact_ttl: nil)
161
161
  artifact = self.class.joins(:alert).where(
162
- data: data,
163
- alert: { rule_id: rule_id }
162
+ data:,
163
+ alert: {rule_id:}
164
164
  ).order(created_at: :desc).first
165
165
  return true if artifact.nil?
166
166
 
@@ -19,7 +19,7 @@ module Mihari
19
19
  #
20
20
  def build_by_ip(ip, enricher: Enrichers::Shodan.new)
21
21
  enricher.result(ip).fmap do |res|
22
- (res&.ports || []).map { |port| new(port: port) }
22
+ (res&.ports || []).map { |port| new(port:) }
23
23
  end.value_or []
24
24
  end
25
25
  end
@@ -6,6 +6,9 @@ module Mihari
6
6
  # Tag model
7
7
  #
8
8
  class Tag < ActiveRecord::Base
9
+ # @!attribute [rw] name
10
+ # @return [String]
11
+
9
12
  has_many :taggings, dependent: :destroy
10
13
 
11
14
  include SearchCop
data/lib/mihari/rule.rb CHANGED
@@ -103,7 +103,7 @@ module Mihari
103
103
  #
104
104
  def tags
105
105
  data[:tags].uniq.filter_map do |name|
106
- Models::Tag.find_or_create_by(name: name)
106
+ Models::Tag.find_or_create_by(name:)
107
107
  end
108
108
  end
109
109
 
@@ -163,7 +163,7 @@ module Mihari
163
163
  # @return [Array<Mihari::Models::Artifact>]
164
164
  #
165
165
  def unique_artifacts
166
- normalized_artifacts.select { |artifact| artifact.unique?(base_time: base_time, artifact_ttl: artifact_ttl) }
166
+ normalized_artifacts.select { |artifact| artifact.unique?(base_time:, artifact_ttl:) }
167
167
  end
168
168
 
169
169
  #
@@ -221,11 +221,11 @@ module Mihari
221
221
  end
222
222
  rescue ActiveRecord::RecordNotFound
223
223
  Mihari::Models::Rule.new(
224
- id: id,
225
- title: title,
226
- description: description,
227
- data: data,
228
- taggings: taggings
224
+ id:,
225
+ title:,
226
+ description:,
227
+ data:,
228
+ taggings:
229
229
  )
230
230
  end
231
231
 
@@ -319,9 +319,7 @@ module Mihari
319
319
  @analyzers ||= queries.deep_dup.map do |params|
320
320
  name = params.delete(:analyzer)
321
321
  klass = get_analyzer_class(name)
322
- klass.from_params(params).tap do |analyzer|
323
- analyzer.validate_configuration!
324
- end
322
+ klass.from_params(params).tap(&:validate_configuration!)
325
323
  end
326
324
  end
327
325
 
@@ -363,9 +361,7 @@ module Mihari
363
361
  options = params.delete(:options)
364
362
 
365
363
  klass = get_emitter_class(name)
366
- klass.new(rule: self, options: options, **params).tap do |emitter|
367
- emitter.validate_configuration!
368
- end
364
+ klass.new(rule: self, options:, **params).tap(&:validate_configuration!)
369
365
  end
370
366
  end
371
367
 
@@ -399,7 +395,7 @@ module Mihari
399
395
  options = params.delete(:options)
400
396
 
401
397
  klass = get_enricher_class(name)
402
- klass.new(options: options, **params)
398
+ klass.new(options:, **params)
403
399
  end
404
400
  end
405
401
 
@@ -17,6 +17,7 @@ module Mihari
17
17
  required(:emitter).value(Types::String.enum(*Mihari::Emitters::MISP.keys))
18
18
  optional(:url).filled(:string)
19
19
  optional(:api_key).filled(:string)
20
+ optional(:attribute_tags).array { filled(:string) }.default([])
20
21
  optional(:options).hash(EmitterOptions)
21
22
  end
22
23
 
@@ -24,6 +25,7 @@ module Mihari
24
25
  required(:emitter).value(Types::String.enum(*Mihari::Emitters::TheHive.keys))
25
26
  optional(:url).filled(:string)
26
27
  optional(:api_key).filled(:string)
28
+ optional(:observable_tags).array { filled(:string) }.default([])
27
29
  optional(:options).hash(EmitterOptions)
28
30
  end
29
31
 
@@ -28,10 +28,10 @@ module Mihari
28
28
 
29
29
  return read_file(url.path) if url.scheme == "file"
30
30
 
31
- http = HTTP::Factory.build(headers: headers, timeout: timeout)
31
+ http = HTTP::Factory.build(headers:, timeout:)
32
32
 
33
- res = http.get(url, params: params) if method == "GET"
34
- res = http.post(url, params: params, json: json, form: form) if method == "POST"
33
+ res = http.get(url, params:) if method == "GET"
34
+ res = http.post(url, params:, json:, form:) if method == "POST"
35
35
 
36
36
  body = res.body.to_s
37
37
  content_type = res["Content-Type"].to_s
@@ -35,7 +35,7 @@ module Mihari
35
35
 
36
36
  class RuleGetter < Service
37
37
  #
38
- # @params [String] id
38
+ # @param [String] id
39
39
  #
40
40
  # @return [Mihari::Models::Rule]
41
41
  #
@@ -61,7 +61,7 @@ module Mihari
61
61
  #
62
62
  def artifacts
63
63
  @artifacts ||= data[:artifacts].map do |data|
64
- artifact = Models::Artifact.new(data: data)
64
+ artifact = Models::Artifact.new(data:)
65
65
  artifact.rule_id = rule_id
66
66
  artifact.source = source
67
67
  artifact
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "tilt/jbuilder"
2
4
 
3
5
  module Mihari
@@ -35,7 +35,7 @@ module Mihari
35
35
  ResultValue.new(
36
36
  total: klass.count_by_filter(filter),
37
37
  results: klass.search_by_filter(filter),
38
- filter: filter
38
+ filter:
39
39
  )
40
40
  end
41
41
 
@@ -5,9 +5,9 @@ require "sidekiq"
5
5
  require "mihari/sidekiq/jobs"
6
6
 
7
7
  Sidekiq.configure_server do |config|
8
- config.redis = { url: Mihari.config.sidekiq_redis_url.to_s }
8
+ config.redis = {url: Mihari.config.sidekiq_redis_url.to_s}
9
9
  end
10
10
 
11
11
  Sidekiq.configure_client do |config|
12
- config.redis = { url: Mihari.config.sidekiq_redis_url.to_s }
12
+ config.redis = {url: Mihari.config.sidekiq_redis_url.to_s}
13
13
  end
@@ -48,8 +48,8 @@ module Mihari
48
48
  return nil if country.nil?
49
49
 
50
50
  Mihari::Models::Geolocation.new(
51
- country: country,
52
- country_code: country_code
51
+ country:,
52
+ country_code:
53
53
  )
54
54
  end
55
55
 
@@ -126,10 +126,10 @@ module Mihari
126
126
  def artifact
127
127
  Models::Artifact.new(
128
128
  data: ip,
129
- metadata: metadata,
129
+ metadata:,
130
130
  autonomous_system: autonomous_system.as,
131
131
  geolocation: location.geolocation,
132
- ports: ports
132
+ ports:
133
133
  )
134
134
  end
135
135
 
@@ -4,8 +4,8 @@ module Mihari
4
4
  module Structs
5
5
  module GooglePublicDNS
6
6
  INT_TYPE_TO_TYPE =
7
- { 1 => :A, 38 => :A6, 28 => :AAAA, 18 => :AFSDB, 255 => :ANY, 42 => :APL, 34 => :ATMA, 252 => :AXFR, 37 => :CERT,
8
- 5 => :CNAME, 49 => :DHCID, 32_769 => :DLV, 39 => :DNAME, 48 => :DNSKEY, 43 => :DS, 31 => :EID, 102 => :GID, 27 => :GPOS, 13 => :HINFO, 45 => :IPSECKEY, 20 => :ISDN, 251 => :IXFR, 25 => :KEY, 36 => :KX, 29 => :LOC, 254 => :MAILA, 253 => :MAILB, 7 => :MB, 3 => :MD, 4 => :MF, 8 => :MG, 14 => :MINFO, 9 => :MR, 15 => :MX, 35 => :NAPTR, 32 => :NIMLOC, 2 => :NS, 22 => :NSAP, 23 => :NSAP_PTR, 47 => :NSEC, 50 => :NSEC3, 51 => :NSEC3PARAMS, 10 => :NULL, 30 => :NXT, 41 => :OPT, 12 => :PTR, 26 => :PX, 17 => :RP, 46 => :RRSIG, 21 => :RT, 24 => :SIG, 40 => :SINK, 6 => :SOA, 33 => :SRV, 44 => :SSHFP, 250 => :TSIG, 16 => :TXT, 101 => :UID, 100 => :UINFO, 103 => :UNSPEC, 11 => :WKS, 19 => :X25 }.freeze
7
+ {1 => :A, 38 => :A6, 28 => :AAAA, 18 => :AFSDB, 255 => :ANY, 42 => :APL, 34 => :ATMA, 252 => :AXFR, 37 => :CERT,
8
+ 5 => :CNAME, 49 => :DHCID, 32_769 => :DLV, 39 => :DNAME, 48 => :DNSKEY, 43 => :DS, 31 => :EID, 102 => :GID, 27 => :GPOS, 13 => :HINFO, 45 => :IPSECKEY, 20 => :ISDN, 251 => :IXFR, 25 => :KEY, 36 => :KX, 29 => :LOC, 254 => :MAILA, 253 => :MAILB, 7 => :MB, 3 => :MD, 4 => :MF, 8 => :MG, 14 => :MINFO, 9 => :MR, 15 => :MX, 35 => :NAPTR, 32 => :NIMLOC, 2 => :NS, 22 => :NSAP, 23 => :NSAP_PTR, 47 => :NSEC, 50 => :NSEC3, 51 => :NSEC3PARAMS, 10 => :NULL, 30 => :NXT, 41 => :OPT, 12 => :PTR, 26 => :PX, 17 => :RP, 46 => :RRSIG, 21 => :RT, 24 => :SIG, 40 => :SINK, 6 => :SOA, 33 => :SRV, 44 => :SSHFP, 250 => :TSIG, 16 => :TXT, 101 => :UID, 100 => :UINFO, 103 => :UNSPEC, 11 => :WKS, 19 => :X25}.freeze
9
9
 
10
10
  class Answer < Dry::Struct
11
11
  # @!attribute [r] name
@@ -30,7 +30,7 @@ module Mihari
30
30
  new(
31
31
  name: d.fetch("name"),
32
32
  data: d.fetch("data"),
33
- resource_type: resource_type
33
+ resource_type:
34
34
  )
35
35
  end
36
36
  end
@@ -30,8 +30,8 @@ module Mihari
30
30
  #
31
31
  def geolocation
32
32
  Mihari::Models::Geolocation.new(
33
- country: country,
34
- country_code: country_code
33
+ country:,
34
+ country_code:
35
35
  )
36
36
  end
37
37
 
@@ -29,9 +29,9 @@ module Mihari
29
29
  def artifact
30
30
  Mihari::Models::Artifact.new(
31
31
  data: ip,
32
- metadata: metadata,
32
+ metadata:,
33
33
  autonomous_system: as,
34
- geolocation: geolocation
34
+ geolocation:
35
35
  )
36
36
  end
37
37
 
@@ -43,7 +43,7 @@ module Mihari
43
43
 
44
44
  Mihari::Models::Geolocation.new(
45
45
  country: NormalizeCountry(country_code, to: :short),
46
- country_code: country_code
46
+ country_code:
47
47
  )
48
48
  end
49
49
 
@@ -20,7 +20,7 @@ module Mihari
20
20
 
21
21
  Mihari::Models::Geolocation.new(
22
22
  country: country_name,
23
- country_code: country_code
23
+ country_code:
24
24
  )
25
25
  end
26
26
 
@@ -106,7 +106,7 @@ module Mihari
106
106
 
107
107
  new(
108
108
  asn: d["asn"],
109
- hostnames: hostnames,
109
+ hostnames:,
110
110
  location: Location.from_dynamic!(d.fetch("location")),
111
111
  domains: d.fetch("domains"),
112
112
  ip_str: d.fetch("ip_str"),
@@ -205,20 +205,20 @@ module Mihari
205
205
 
206
206
  ports = collect_ports_by_ip(match.ip_str).map { |port| Models::Port.new(number: port) }
207
207
  reverse_dns_names = collect_hostnames_by_ip(match.ip_str).map do |name|
208
- Models::ReverseDnsName.new(name: name)
208
+ Models::ReverseDnsName.new(name:)
209
209
  end
210
- cpes = collect_cpes_by_ip(match.ip_str).map { |name| Models::CPE.new(name: name) }
211
- vulnerabilities = collect_vulns_by_ip(match.ip_str).map { |name| Models::Vulnerability.new(name: name) }
210
+ cpes = collect_cpes_by_ip(match.ip_str).map { |name| Models::CPE.new(name:) }
211
+ vulnerabilities = collect_vulns_by_ip(match.ip_str).map { |name| Models::Vulnerability.new(name:) }
212
212
 
213
213
  Mihari::Models::Artifact.new(
214
214
  data: match.ip_str,
215
- metadata: metadata,
215
+ metadata:,
216
216
  autonomous_system: match.autonomous_system,
217
217
  geolocation: match.location.geolocation,
218
- ports: ports,
219
- reverse_dns_names: reverse_dns_names,
220
- cpes: cpes,
221
- vulnerabilities: vulnerabilities
218
+ ports:,
219
+ reverse_dns_names:,
220
+ cpes:,
221
+ vulnerabilities:
222
222
  )
223
223
  end
224
224
  end
@@ -53,7 +53,7 @@ module Mihari
53
53
  #
54
54
  def artifacts
55
55
  values = [page.url, page.domain, page.ip].compact
56
- values.map { |value| Mihari::Models::Artifact.new(data: value, metadata: metadata) }
56
+ values.map { |value| Mihari::Models::Artifact.new(data: value, metadata:) }
57
57
  end
58
58
 
59
59
  class << self
@@ -56,7 +56,7 @@ module Mihari
56
56
  # @return [Mihari::Models::Artifact]
57
57
  #
58
58
  def artifact
59
- Models::Artifact.new(data: value, metadata: metadata)
59
+ Models::Artifact.new(data: value, metadata:)
60
60
  end
61
61
 
62
62
  class << self
@@ -74,7 +74,7 @@ module Mihari
74
74
  new(
75
75
  type: d.fetch("type"),
76
76
  id: d.fetch("id"),
77
- context_attributes: context_attributes,
77
+ context_attributes:,
78
78
  metadata: d
79
79
  )
80
80
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "7.3.2"
4
+ VERSION = "7.4.0"
5
5
  end
@@ -24,7 +24,7 @@ module Mihari
24
24
  mount Endpoints::Rules
25
25
  mount Endpoints::Tags
26
26
 
27
- add_swagger_documentation(api_version: "v1", info: { title: "Mihari API" })
27
+ add_swagger_documentation(api_version: "v1", info: {title: "Mihari API"})
28
28
  end
29
29
  end
30
30
  end
@@ -97,7 +97,7 @@ module Mihari
97
97
  Host: host,
98
98
  Threads: threads,
99
99
  Verbose: verbose,
100
- worker_timeout: worker_timeout
100
+ worker_timeout:
101
101
  ) do |_|
102
102
  Launchy.open("http://#{host}:#{port}") if !Mihari.development? && open
103
103
  rescue Launchy::CommandNotFoundError
@@ -33,7 +33,7 @@ module Mihari
33
33
 
34
34
  desc "Get an alert", {
35
35
  success: Entities::Alert,
36
- failure: [{ code: 404, model: Entities::ErrorMessage }],
36
+ failure: [{code: 404, model: Entities::ErrorMessage}],
37
37
  summary: "Get an alert"
38
38
  }
39
39
  params do
@@ -46,14 +46,14 @@ module Mihari
46
46
 
47
47
  case result.failure
48
48
  when ActiveRecord::RecordNotFound
49
- error!({ message: "ID:#{id} not found" }, 404)
49
+ error!({message: "ID:#{id} not found"}, 404)
50
50
  end
51
51
  raise result.failure
52
52
  end
53
53
 
54
54
  desc "Delete an alert", {
55
- success: { code: 204, model: Entities::Message },
56
- failure: [{ code: 404, model: Entities::ErrorMessage }],
55
+ success: {code: 204, model: Entities::Message},
56
+ failure: [{code: 404, model: Entities::ErrorMessage}],
57
57
  summary: "Delete an alert"
58
58
  }
59
59
  params do
@@ -64,26 +64,26 @@ module Mihari
64
64
 
65
65
  id = params["id"].to_i
66
66
  result = Services::AlertDestroyer.result(id)
67
- return present({ message: "" }, with: Entities::Message) if result.success?
67
+ return present({message: ""}, with: Entities::Message) if result.success?
68
68
 
69
69
  case result.failure
70
70
  when ActiveRecord::RecordNotFound
71
- error!({ message: "ID:#{id} not found" }, 404)
71
+ error!({message: "ID:#{id} not found"}, 404)
72
72
  end
73
73
  raise result.failure
74
74
  end
75
75
 
76
76
  desc "Create an alert", {
77
- success: { code: 201, model: Entities::Alert },
77
+ success: {code: 201, model: Entities::Alert},
78
78
  failure: [
79
- { code: 404, model: Entities::ErrorMessage }
79
+ {code: 404, model: Entities::ErrorMessage}
80
80
  ],
81
81
  summary: "Create an alert"
82
82
  }
83
83
  params do
84
- requires :ruleId, type: String, documentation: { param_type: "body" }
85
- requires :artifacts, type: Array, documentation: { type: String, is_array: true, param_type: "body" }
86
- optional :source, type: String, documentation: { param_type: "body" }
84
+ requires :ruleId, type: String, documentation: {param_type: "body"}
85
+ requires :artifacts, type: Array, documentation: {type: String, is_array: true, param_type: "body"}
86
+ optional :source, type: String, documentation: {param_type: "body"}
87
87
  end
88
88
  post "/" do
89
89
  status 201
@@ -93,7 +93,7 @@ module Mihari
93
93
 
94
94
  case result.failure
95
95
  when ActiveRecord::RecordNotFound
96
- error!({ message: "Rule:#{params["ruleId"]} not found" }, 404)
96
+ error!({message: "Rule:#{params["ruleId"]} not found"}, 404)
97
97
  end
98
98
  raise result.failure
99
99
  end
@@ -33,7 +33,7 @@ module Mihari
33
33
 
34
34
  desc "Get an artifact", {
35
35
  success: Entities::Artifact,
36
- failure: [{ code: 404, model: Entities::ErrorMessage }],
36
+ failure: [{code: 404, model: Entities::ErrorMessage}],
37
37
  summary: "Get an artifact"
38
38
  }
39
39
  params do
@@ -46,14 +46,14 @@ module Mihari
46
46
 
47
47
  case result.failure
48
48
  when ActiveRecord::RecordNotFound
49
- error!({ message: "ID:#{id} not found" }, 404)
49
+ error!({message: "ID:#{id} not found"}, 404)
50
50
  end
51
51
  raise result.failure
52
52
  end
53
53
 
54
54
  desc "Enrich an artifact", {
55
- success: { code: 201, model: Entities::Message },
56
- failure: [{ code: 400, model: Entities::ErrorMessage }, { code: 404, model: Entities::ErrorMessage }],
55
+ success: {code: 201, model: Entities::Message},
56
+ failure: [{code: 400, model: Entities::ErrorMessage}, {code: 404, model: Entities::ErrorMessage}],
57
57
  summary: "Enrich an artifact"
58
58
  }
59
59
  params do
@@ -75,20 +75,20 @@ module Mihari
75
75
  end.to_result
76
76
 
77
77
  message = queued ? "ID:#{id}'s enrichment is queued" : "ID:#{id}'s enrichment is successful"
78
- return present({ message: message, queued: queued }, with: Entities::QueueMessage) if result.success?
78
+ return present({message:, queued:}, with: Entities::QueueMessage) if result.success?
79
79
 
80
80
  case result.failure
81
81
  when UnenrichableError
82
- error!({ message: result.failure.message }, 400)
82
+ error!({message: result.failure.message}, 400)
83
83
  when ActiveRecord::RecordNotFound
84
- error!({ message: "ID:#{id} not found" }, 404)
84
+ error!({message: "ID:#{id} not found"}, 404)
85
85
  end
86
86
  raise result.failure
87
87
  end
88
88
 
89
89
  desc "Delete an artifact", {
90
- success: { code: 204, model: Entities::Message },
91
- failure: [{ code: 404, model: Entities::ErrorMessage }],
90
+ success: {code: 204, model: Entities::Message},
91
+ failure: [{code: 404, model: Entities::ErrorMessage}],
92
92
  summary: "Delete an artifact"
93
93
  }
94
94
  params do
@@ -99,11 +99,11 @@ module Mihari
99
99
 
100
100
  id = params["id"].to_i
101
101
  result = Services::ArtifactDestroyer.result(id)
102
- return present({ message: "" }, with: Entities::Message) if result.success?
102
+ return present({message: ""}, with: Entities::Message) if result.success?
103
103
 
104
104
  case result.failure
105
105
  when ActiveRecord::RecordNotFound
106
- error!({ message: "ID:#{id} not found" }, 404)
106
+ error!({message: "ID:#{id} not found"}, 404)
107
107
  end
108
108
  raise result.failure
109
109
  end
@@ -10,12 +10,17 @@ module Mihari
10
10
  namespace :configs do
11
11
  desc "list configs", {
12
12
  is_array: true,
13
- success: Entities::Config,
13
+ success: Entities::Configs,
14
14
  summary: "List configs"
15
15
  }
16
16
  get "/" do
17
17
  configs = Services::ConfigSearcher.call
18
- present(configs, with: Entities::Config)
18
+ present(
19
+ {
20
+ results: configs
21
+ },
22
+ with: Entities::Configs
23
+ )
19
24
  end
20
25
  end
21
26
  end
@@ -11,15 +11,15 @@ module Mihari
11
11
  desc "Get IP address data", {
12
12
  success: Entities::IPAddress,
13
13
  failure: [
14
- { code: 404, model: Entities::ErrorMessage },
15
- { code: 422, model: Entities::ErrorMessage }
14
+ {code: 404, model: Entities::ErrorMessage},
15
+ {code: 422, model: Entities::ErrorMessage}
16
16
  ],
17
17
  summary: "Get IP address data"
18
18
  }
19
19
  params do
20
20
  requires :ip, type: String
21
21
  end
22
- get "/:ip", requirements: { ip: %r{[^/]+} } do
22
+ get "/:ip", requirements: {ip: %r{[^/]+}} do
23
23
  ip = params[:ip].to_s
24
24
  result = Services::IPGetter.result(ip)
25
25
  if result.success?
@@ -37,8 +37,8 @@ module Mihari
37
37
  failure = result.failure
38
38
  case failure
39
39
  when Mihari::StatusError
40
- error!({ message: "IP:#{ip} not found" }, failure.status_code) if failure.status_code == 404
41
- error!({ message: "IP format invalid" }, failure.status_code) if failure.status_code == 422
40
+ error!({message: "IP:#{ip} not found"}, failure.status_code) if failure.status_code == 404
41
+ error!({message: "IP format invalid"}, failure.status_code) if failure.status_code == 422
42
42
  end
43
43
  raise failure
44
44
  end