mihari 7.3.1 → 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 +2 -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 +10 -12
  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 +16 -16
  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-JHS0L8KZ.js +0 -1786
  127. /data/lib/mihari/web/public/assets/{mode-yaml-BC4MIiYj.js → mode-yaml-ELgwiJiP.js} +0 -0
@@ -20,7 +20,7 @@ module Mihari
20
20
  # @return [Mihari::Services::ResultValue]
21
21
  #
22
22
  def _search(q, page: 1, limit: 10)
23
- filter = Structs::Filters::Search.new(q: q, page: page, limit: limit)
23
+ filter = Structs::Filters::Search.new(q:, page:, limit:)
24
24
  Services::ArtifactSearcher.result(filter).value!
25
25
  end
26
26
  end
@@ -21,7 +21,7 @@ module Mihari
21
21
  # @return [Mihari::Services::ResultValue]
22
22
  #
23
23
  def _search(q, page: 1, limit: 10)
24
- filter = Structs::Filters::Search.new(q: q, page: page, limit: limit)
24
+ filter = Structs::Filters::Search.new(q:, page:, limit:)
25
25
  Services::RuleSearcher.result(filter).value!
26
26
  end
27
27
  end
@@ -20,7 +20,7 @@ module Mihari
20
20
  # @return [Mihari::Services::ResultValue]
21
21
  #
22
22
  def _search(q, page: 1, limit: 10)
23
- filter = Structs::Filters::Search.new(q: q, page: page, limit: limit)
23
+ filter = Structs::Filters::Search.new(q:, page:, limit:)
24
24
  Services::TagSearcher.result(filter).value!
25
25
  end
26
26
  end
@@ -16,10 +16,7 @@ module Mihari
16
16
  # @return [Integer]
17
17
  #
18
18
  def normalize_asn(asn)
19
- return asn if asn.is_a?(Integer)
20
- return asn.to_i unless asn.start_with?("AS")
21
-
22
- asn.delete_prefix("AS").to_i
19
+ asn.to_s.delete_prefix("AS").to_i
23
20
  end
24
21
  end
25
22
  end
@@ -40,7 +40,7 @@ module Mihari
40
40
  configuration_keys.map do |key|
41
41
  value = Mihari.config.send(key)
42
42
  value = "REDACTED" if value && Mihari.config.hide_config_values
43
- { key: key.upcase, value: value }
43
+ {key: key.upcase, value:}
44
44
  end
45
45
  end
46
46
 
@@ -8,8 +8,8 @@ module Mihari
8
8
  module DatabaseConnectable
9
9
  extend ActiveSupport::Concern
10
10
 
11
- def with_db_connection(&block)
12
- Database.with_db_connection(&block)
11
+ def with_db_connection(&)
12
+ Database.with_db_connection(&)
13
13
  end
14
14
  end
15
15
  end
@@ -41,7 +41,7 @@ module Mihari
41
41
  begin
42
42
  try += 1
43
43
  yield
44
- rescue StandardError => e
44
+ rescue => e
45
45
  # Raise error if it's not a retriable error
46
46
  raise e unless condition.call(e)
47
47
 
data/lib/mihari/config.rb CHANGED
@@ -42,7 +42,8 @@ module Mihari
42
42
  ignore_error: false,
43
43
  pagination_interval: 0,
44
44
  pagination_limit: 100,
45
- parallel: false,
45
+ analyzer_parallelism: false,
46
+ emitter_parallelism: true,
46
47
  retry_exponential_backoff: true,
47
48
  retry_interval: 5,
48
49
  retry_times: 3,
@@ -146,7 +147,10 @@ module Mihari
146
147
  # @!attribute [r] pagination_limit
147
148
  # @return [Integer]
148
149
 
149
- # @!attribute [r] parallel
150
+ # @!attribute [r] analyzer_parallelism
151
+ # @return [Boolean]
152
+
153
+ # @!attribute [r] emitter_parallelism
150
154
  # @return [Boolean]
151
155
 
152
156
  # @!attribute [r] ignore_error
@@ -5,8 +5,8 @@ module Mihari
5
5
  DEFAULT_DATA_TYPES = Types::DataTypes.values.freeze
6
6
 
7
7
  # @return [Array<Hash>]
8
- DEFAULT_EMITTERS = Emitters::Database.keys.map { |name| { emitter: name.downcase } }.freeze
8
+ DEFAULT_EMITTERS = Emitters::Database.keys.map { |name| {emitter: name.downcase} }.freeze
9
9
 
10
10
  # @return [Array<Hash>]
11
- DEFAULT_ENRICHERS = Mihari.enricher_to_class.keys.map { |name| { enricher: name.downcase } }.freeze
11
+ DEFAULT_ENRICHERS = Mihari.enricher_to_class.keys.map { |name| {enricher: name.downcase} }.freeze
12
12
  end
@@ -14,7 +14,7 @@ module Mihari
14
14
  # @param [Hash, nil] options
15
15
  #
16
16
  def initialize(rule:, options: nil)
17
- super(options: options)
17
+ super(options:)
18
18
 
19
19
  @rule = rule
20
20
  end
@@ -23,7 +23,7 @@ module Mihari
23
23
  # @return [Boolean]
24
24
  #
25
25
  def parallel?
26
- options[:parallel] || Mihari.config.parallel
26
+ options[:parallel] || Mihari.config.emitter_parallelism
27
27
  end
28
28
 
29
29
  # A target to emit the data
@@ -16,7 +16,7 @@ module Mihari
16
16
  def call(artifacts)
17
17
  return if artifacts.empty?
18
18
 
19
- alert = Models::Alert.new(artifacts: artifacts, rule_id: rule.id)
19
+ alert = Models::Alert.new(artifacts:, rule_id: rule.id)
20
20
  alert.save
21
21
  alert
22
22
  end
@@ -12,6 +12,9 @@ module Mihari
12
12
  # @return [String, nil]
13
13
  attr_reader :api_key
14
14
 
15
+ # @return [Array<String>]
16
+ attr_reader :attribute_tags
17
+
15
18
  # @return [Mihari::Rule]
16
19
  attr_reader :rule
17
20
 
@@ -24,10 +27,11 @@ module Mihari
24
27
  # @param [Hash, nil] params
25
28
  #
26
29
  def initialize(rule:, options: nil, **params)
27
- super(rule: rule, options: options)
30
+ super(rule:, options:)
28
31
 
29
32
  @url = params[:url] || Mihari.config.misp_url
30
33
  @api_key = params[:api_key] || Mihari.config.misp_api_key
34
+ @attribute_tags = params[:attribute_tags] || []
31
35
 
32
36
  @artifacts = []
33
37
  end
@@ -51,7 +55,7 @@ module Mihari
51
55
  Event: {
52
56
  info: rule.title,
53
57
  Attribute: artifacts.map { |artifact| build_attribute(artifact) },
54
- Tag: rule.tags.map { |tag| { name: tag } }
58
+ Tag: rule.tags.map { |tag| {name: tag.name} }
55
59
  }
56
60
  })
57
61
  end
@@ -66,7 +70,7 @@ module Mihari
66
70
  private
67
71
 
68
72
  def client
69
- @client ||= Clients::MISP.new(url, api_key: api_key, timeout: timeout)
73
+ @client ||= Clients::MISP.new(url, api_key:, timeout:)
70
74
  end
71
75
 
72
76
  #
@@ -77,7 +81,11 @@ module Mihari
77
81
  # @return [Hash]
78
82
  #
79
83
  def build_attribute(artifact)
80
- { value: artifact.data, type: to_misp_type(type: artifact.data_type, value: artifact.data) }
84
+ {
85
+ value: artifact.data,
86
+ type: to_misp_type(type: artifact.data_type, value: artifact.data),
87
+ Tag: attribute_tags.map { |tag| {name: tag} }
88
+ }
81
89
  end
82
90
 
83
91
  #
@@ -30,25 +30,25 @@ module Mihari
30
30
  def vt_link
31
31
  return nil unless _vt_link
32
32
 
33
- { type: "button", text: "VirusTotal", url: _vt_link }
33
+ {type: "button", text: "VirusTotal", url: _vt_link}
34
34
  end
35
35
 
36
36
  def urlscan_link
37
37
  return nil unless _urlscan_link
38
38
 
39
- { type: "button", text: "urlscan.io", url: _urlscan_link }
39
+ {type: "button", text: "urlscan.io", url: _urlscan_link}
40
40
  end
41
41
 
42
42
  def censys_link
43
43
  return nil unless _censys_link
44
44
 
45
- { type: "button", text: "Censys", url: _censys_link }
45
+ {type: "button", text: "Censys", url: _censys_link}
46
46
  end
47
47
 
48
48
  def shodan_link
49
49
  return nil unless _shodan_link
50
50
 
51
- { type: "button", text: "Shodan", url: _shodan_link }
51
+ {type: "button", text: "Shodan", url: _shodan_link}
52
52
  end
53
53
 
54
54
  # @return [Array]
@@ -57,7 +57,7 @@ module Mihari
57
57
  {
58
58
  text: defanged_data,
59
59
  fallback: "VT & urlscan.io links",
60
- actions: actions
60
+ actions:
61
61
  }
62
62
  ]
63
63
  end
@@ -140,7 +140,7 @@ module Mihari
140
140
  # @param [Hash, nil] params
141
141
  #
142
142
  def initialize(rule:, options: nil, **params)
143
- super(rule: rule, options: options)
143
+ super(rule:, options:)
144
144
 
145
145
  @webhook_url = params[:webhook_url] || Mihari.config.slack_webhook_url
146
146
  @channel = params[:channel] || Mihari.config.slack_channel || DEFAULT_CHANNEL
@@ -177,9 +177,9 @@ module Mihari
177
177
  #
178
178
  def notifier
179
179
  @notifier ||= lambda do
180
- return ::Slack::Notifier.new(webhook_url, channel: channel, username: username) if timeout.nil?
180
+ return ::Slack::Notifier.new(webhook_url, channel:, username:) if timeout.nil?
181
181
 
182
- ::Slack::Notifier.new(webhook_url, channel: channel, username: username, http_options: { timeout: timeout })
182
+ ::Slack::Notifier.new(webhook_url, channel:, username:, http_options: {timeout:})
183
183
  end.call
184
184
  end
185
185
 
@@ -215,7 +215,7 @@ module Mihari
215
215
 
216
216
  @artifacts = artifacts
217
217
 
218
- notifier.post(text: text, attachments: attachments, mrkdwn: true)
218
+ notifier.post(text:, attachments:, mrkdwn: true)
219
219
  end
220
220
  end
221
221
  end
@@ -9,6 +9,9 @@ module Mihari
9
9
  # @return [String, nil]
10
10
  attr_reader :api_key
11
11
 
12
+ # @return [Array<String>]
13
+ attr_reader :observable_tags
14
+
12
15
  # @return [Array<Mihari::Models::Artifact>]
13
16
  attr_accessor :artifacts
14
17
 
@@ -18,10 +21,11 @@ module Mihari
18
21
  # @param [Hash] params
19
22
  #
20
23
  def initialize(rule:, options: nil, **params)
21
- super(rule: rule, options: options)
24
+ super(rule:, options:)
22
25
 
23
26
  @url = params[:url] || Mihari.config.thehive_url
24
27
  @api_key = params[:api_key] || Mihari.config.thehive_api_key
28
+ @observable_tags = params[:observable_tags] || []
25
29
 
26
30
  @artifacts = []
27
31
  end
@@ -56,7 +60,7 @@ module Mihari
56
60
  private
57
61
 
58
62
  def client
59
- Clients::TheHive.new(url, api_key: api_key, api_version: "v1", timeout: timeout)
63
+ Clients::TheHive.new(url, api_key:, api_version: "v1", timeout:)
60
64
  end
61
65
 
62
66
  #
@@ -81,10 +85,11 @@ module Mihari
81
85
  {
82
86
  data: artifact.data,
83
87
  data_type: artifact.data_type,
84
- message: rule.description
88
+ message: rule.description,
89
+ tags: observable_tags
85
90
  }
86
91
  end,
87
- tags: rule.tags,
92
+ tags: rule.tags.map(&:name),
88
93
  type: "external",
89
94
  source: "mihari",
90
95
  source_ref: SecureRandom.uuid
@@ -36,7 +36,7 @@ module Mihari
36
36
  # @param [Hash, nil] params
37
37
  #
38
38
  def initialize(rule:, options: nil, **params)
39
- super(rule: rule, options: options)
39
+ super(rule:, options:)
40
40
 
41
41
  @url = Addressable::URI.parse(params[:url])
42
42
  @headers = params[:headers] || {}
@@ -75,14 +75,14 @@ module Mihari
75
75
  when "GET"
76
76
  http.get(url).body.to_s
77
77
  when "POST"
78
- http.post(url, json: json).body.to_s
78
+ http.post(url, json:).body.to_s
79
79
  end
80
80
  end
81
81
 
82
82
  private
83
83
 
84
84
  def http
85
- HTTP::Factory.build headers: headers, timeout: timeout
85
+ HTTP::Factory.build headers:, timeout:
86
86
  end
87
87
 
88
88
  #
@@ -91,7 +91,7 @@ module Mihari
91
91
  # @return [String]
92
92
  #
93
93
  def render
94
- Services::JbuilderRenderer.call(template, { rule: rule, artifacts: artifacts })
94
+ Services::JbuilderRenderer.call(template, {rule:, artifacts:})
95
95
  end
96
96
 
97
97
  #
@@ -10,7 +10,7 @@ module Mihari
10
10
  # @param [Hash, nil] options
11
11
  #
12
12
  def initialize(options: nil)
13
- super(options: options)
13
+ super(options:)
14
14
  end
15
15
 
16
16
  #
@@ -50,7 +50,7 @@ module Mihari
50
50
  end
51
51
 
52
52
  def client
53
- @client ||= Clients::GooglePublicDNS.new(timeout: timeout)
53
+ @client ||= Clients::GooglePublicDNS.new(timeout:)
54
54
  end
55
55
  end
56
56
  end
@@ -39,7 +39,7 @@ module Mihari
39
39
  end
40
40
 
41
41
  def client
42
- @client ||= Clients::MMDB.new(timeout: timeout)
42
+ @client ||= Clients::MMDB.new(timeout:)
43
43
  end
44
44
  end
45
45
  end
@@ -19,21 +19,19 @@ module Mihari
19
19
  artifact.tap do |tapped|
20
20
  tapped.cpes = (res&.cpes || []).map { |cpe| Models::CPE.new(name: cpe) } if tapped.cpes.empty?
21
21
  tapped.ports = (res&.ports || []).map { |port| Models::Port.new(number: port) } if tapped.ports.empty?
22
+
22
23
  if tapped.reverse_dns_names.empty?
23
24
  tapped.reverse_dns_names = (res&.hostnames || []).map do |name|
24
- Models::ReverseDnsName.new(name: name)
25
+ Models::ReverseDnsName.new(name:)
25
26
  end
26
27
  end
27
- end
28
- end
29
28
 
30
- #
31
- # @param [Mihari::Models::Artifact] artifact
32
- #
33
- # @return [Boolean]
34
- #
35
- def callable?(artifact)
36
- false unless supported_data_types.include?(artifact.data_type)
29
+ if tapped.vulnerabilities.empty?
30
+ tapped.vulnerabilities = (res&.vulns || []).map do |name|
31
+ Models::Vulnerability.new(name:)
32
+ end
33
+ end
34
+ end
37
35
  end
38
36
 
39
37
  private
@@ -44,7 +42,7 @@ module Mihari
44
42
  # @return [Boolean]
45
43
  #
46
44
  def callable_relationships?(artifact)
47
- artifact.cpes.empty? || artifact.ports.empty? || artifact.reverse_dns_names.empty?
45
+ artifact.cpes.empty? || artifact.ports.empty? || artifact.reverse_dns_names.empty? || artifact.vulnerabilities.empty?
48
46
  end
49
47
 
50
48
  def supported_data_types
@@ -52,7 +50,7 @@ module Mihari
52
50
  end
53
51
 
54
52
  def client
55
- @client ||= Clients::ShodanInternetDB.new(timeout: timeout)
53
+ @client ||= Clients::ShodanInternetDB.new(timeout:)
56
54
  end
57
55
  end
58
56
  end
@@ -23,7 +23,7 @@ module Mihari
23
23
  return if record.parser.available?
24
24
 
25
25
  artifact.whois_record ||= Models::WhoisRecord.new(
26
- domain: domain,
26
+ domain:,
27
27
  created_on: get_created_on(record.parser),
28
28
  updated_on: get_updated_on(record.parser),
29
29
  expires_on: get_expires_on(record.parser),
@@ -64,7 +64,7 @@ module Mihari
64
64
  @whois ||= lambda do
65
65
  return ::Whois::Client.new if timeout.nil?
66
66
 
67
- ::Whois::Client.new(timeout: timeout)
67
+ ::Whois::Client.new(timeout:)
68
68
  end.call
69
69
  end
70
70
 
@@ -3,16 +3,16 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Alert < Grape::Entity
6
- expose :id, documentation: { type: Integer, required: true }
7
- expose :rule_id, documentation: { type: String, required: true }, as: :ruleId
8
- expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
6
+ expose :id, documentation: {type: Integer, required: true}
7
+ expose :rule_id, documentation: {type: String, required: true}, as: :ruleId
8
+ expose :created_at, documentation: {type: DateTime, required: true}, as: :createdAt
9
9
 
10
- expose :artifacts, using: Entities::BaseArtifact, documentation: { type: Entities::BaseArtifact, is_array: true }
11
- expose :tags, using: Entities::Tag, documentation: { type: Entities::Tag, is_array: true, required: true }
10
+ expose :artifacts, using: Entities::BaseArtifact, documentation: {type: Entities::BaseArtifact, is_array: true}
11
+ expose :tags, using: Entities::Tag, documentation: {type: Entities::Tag, is_array: true, required: true}
12
12
  end
13
13
 
14
14
  class AlertsWithPagination < Pagination
15
- expose :results, using: Entities::Alert, documentation: { type: Entities::Alert, is_array: true, required: true }
15
+ expose :results, using: Entities::Alert, documentation: {type: Entities::Alert, is_array: true, required: true}
16
16
  end
17
17
  end
18
18
  end
@@ -3,40 +3,40 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class BaseArtifact < Grape::Entity
6
- expose :id, documentation: { type: Integer, required: true }
7
- expose :data, documentation: { type: String, required: true }
8
- expose :data_type, documentation: { type: String, required: true }, as: :dataType
9
- expose :source, documentation: { type: String, required: true }
10
- expose :query, documentation: { type: String, required: false }
11
- expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
12
- expose :tags, using: Entities::Tag, documentation: { type: Entities::Tag, is_array: true, required: true }
6
+ expose :id, documentation: {type: Integer, required: true}
7
+ expose :data, documentation: {type: String, required: true}
8
+ expose :data_type, documentation: {type: String, required: true}, as: :dataType
9
+ expose :source, documentation: {type: String, required: true}
10
+ expose :query, documentation: {type: String, required: false}
11
+ expose :created_at, documentation: {type: DateTime, required: true}, as: :createdAt
12
+ expose :tags, using: Entities::Tag, documentation: {type: Entities::Tag, is_array: true, required: true}
13
13
  end
14
14
 
15
15
  class Artifact < BaseArtifact
16
- expose :metadata, documentation: { type: Hash }
16
+ expose :metadata, documentation: {type: Hash}
17
17
  expose :autonomous_system, using: Entities::AutonomousSystem,
18
- documentation: { type: Entities::AutonomousSystem, required: false }, as: :autonomousSystem
19
- expose :geolocation, using: Entities::Geolocation, documentation: { type: Entities::Geolocation, required: false }
18
+ documentation: {type: Entities::AutonomousSystem, required: false}, as: :autonomousSystem
19
+ expose :geolocation, using: Entities::Geolocation, documentation: {type: Entities::Geolocation, required: false}
20
20
  expose :whois_record, using: Entities::WhoisRecord,
21
- documentation: { type: Entities::WhoisRecord, required: false }, as: :whoisRecord
21
+ documentation: {type: Entities::WhoisRecord, required: false}, as: :whoisRecord
22
22
 
23
23
  expose :reverse_dns_names, using: Entities::ReverseDnsName,
24
- documentation: { type: Entities::ReverseDnsName, is_array: true, required: false }, as: :reverseDnsNames do |status, _options|
24
+ documentation: {type: Entities::ReverseDnsName, is_array: true, required: false}, as: :reverseDnsNames do |status, _options|
25
25
  status.reverse_dns_names.empty? ? nil : status.reverse_dns_names
26
26
  end
27
27
  expose :dns_records, using: Entities::DnsRecord,
28
- documentation: { type: Entities::DnsRecord, is_array: true, required: false }, as: :dnsRecords do |status, _options|
28
+ documentation: {type: Entities::DnsRecord, is_array: true, required: false}, as: :dnsRecords do |status, _options|
29
29
  status.dns_records.empty? ? nil : status.dns_records
30
30
  end
31
- expose :ceps, using: Entities::CPE, documentation: { type: Entities::CPE, is_array: true, required: false },
31
+ expose :ceps, using: Entities::CPE, documentation: {type: Entities::CPE, is_array: true, required: false},
32
32
  as: :cpes do |status, _options|
33
33
  status.cpes.empty? ? nil : status.cpes
34
34
  end
35
- expose :ports, using: Entities::Port, documentation: { type: Entities::Port, is_array: true, required: false },
35
+ expose :ports, using: Entities::Port, documentation: {type: Entities::Port, is_array: true, required: false},
36
36
  as: :ports do |status, _options|
37
37
  status.ports.empty? ? nil : status.ports
38
38
  end
39
- expose :vulnerabilities, using: Vulnerability, documentation: { type: Vulnerability, is_array: true, required: false },
39
+ expose :vulnerabilities, using: Vulnerability, documentation: {type: Vulnerability, is_array: true, required: false},
40
40
  as: :vulnerabilities do |status, _options|
41
41
  status.vulnerabilities.empty? ? nil : status.vulnerabilities
42
42
  end
@@ -44,7 +44,7 @@ module Mihari
44
44
 
45
45
  class ArtifactsWithPagination < Pagination
46
46
  expose :results, using: Entities::BaseArtifact,
47
- documentation: { type: Entities::Artifact, is_array: true, required: true }
47
+ documentation: {type: Entities::Artifact, is_array: true, required: true}
48
48
  end
49
49
  end
50
50
  end
@@ -3,7 +3,7 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class AutonomousSystem < Grape::Entity
6
- expose :number, documentation: { type: Integer, required: true }
6
+ expose :number, documentation: {type: Integer, required: true}
7
7
  end
8
8
  end
9
9
  end
@@ -3,10 +3,14 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Config < Grape::Entity
6
- expose :name, documentation: { type: String, required: true }
7
- expose :type, documentation: { type: String, required: true }
8
- expose :items, documentation: { type: Hash, is_array: true, required: true }
9
- expose :configured, documentation: { type: Grape::API::Boolean, required: true }
6
+ expose :name, documentation: {type: String, required: true}
7
+ expose :type, documentation: {type: String, required: true}
8
+ expose :items, documentation: {type: Hash, is_array: true, required: true}
9
+ expose :configured, documentation: {type: Grape::API::Boolean, required: true}
10
+ end
11
+
12
+ class Configs < Grape::Entity
13
+ expose :results, using: Config, documentation: {type: Config, is_array: true, required: true}
10
14
  end
11
15
  end
12
16
  end
@@ -3,8 +3,8 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class CPE < 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,9 +3,9 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class DnsRecord < Grape::Entity
6
- expose :resource, documentation: { type: String, required: true }
7
- expose :value, documentation: { type: String, required: true }
8
- expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
6
+ expose :resource, documentation: {type: String, required: true}
7
+ expose :value, documentation: {type: String, required: true}
8
+ expose :created_at, documentation: {type: DateTime, required: true}, as: :createdAt
9
9
  end
10
10
  end
11
11
  end
@@ -3,9 +3,9 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Geolocation < Grape::Entity
6
- expose :country, documentation: { type: String, required: true }
7
- expose :country_code, documentation: { type: String, required: true }, as: :countryCode
8
- expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
6
+ expose :country, documentation: {type: String, required: true}
7
+ expose :country_code, documentation: {type: String, required: true}, as: :countryCode
8
+ expose :created_at, documentation: {type: DateTime, required: true}, as: :createdAt
9
9
  end
10
10
  end
11
11
  end
@@ -3,9 +3,9 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class IPAddress < Grape::Entity
6
- expose :country_code, documentation: { type: String, required: true }, as: :countryCode
7
- expose :asn, documentation: { type: Integer, required: false }
8
- expose :loc, documentation: { type: String, required: false }
6
+ expose :country_code, documentation: {type: String, required: true}, as: :countryCode
7
+ expose :asn, documentation: {type: Integer, required: false}
8
+ expose :loc, documentation: {type: String, required: false}
9
9
  end
10
10
  end
11
11
  end
@@ -3,15 +3,15 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Message < Grape::Entity
6
- expose :message, documentation: { type: String, required: true }
6
+ expose :message, documentation: {type: String, required: true}
7
7
  end
8
8
 
9
9
  class ErrorMessage < Message
10
- expose :detail, documentation: { type: Hash, required: false }
10
+ expose :detail, documentation: {type: Hash, required: false}
11
11
  end
12
12
 
13
13
  class QueueMessage < Message
14
- expose :queued, documentation: { type: Grape::API::Boolean, required: true }
14
+ expose :queued, documentation: {type: Grape::API::Boolean, required: true}
15
15
  end
16
16
  end
17
17
  end
@@ -3,9 +3,9 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Pagination < Grape::Entity
6
- expose :total, documentation: { type: Integer, required: true }
7
- expose :current_page, documentation: { type: Integer, required: true }, as: :currentPage
8
- expose :page_size, documentation: { type: Integer, required: true }, as: :pageSize
6
+ expose :total, documentation: {type: Integer, required: true}
7
+ expose :current_page, documentation: {type: Integer, required: true}, as: :currentPage
8
+ expose :page_size, documentation: {type: Integer, required: true}, as: :pageSize
9
9
  end
10
10
  end
11
11
  end