mihari 7.3.2 → 7.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) 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 +7 -6
  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/whois.rb +118 -0
  51. data/lib/mihari/clients/yeti.rb +38 -0
  52. data/lib/mihari/clients/zoomeye.rb +12 -12
  53. data/lib/mihari/commands/alert.rb +1 -1
  54. data/lib/mihari/commands/artifact.rb +1 -1
  55. data/lib/mihari/commands/rule.rb +1 -1
  56. data/lib/mihari/commands/tag.rb +1 -1
  57. data/lib/mihari/concerns/autonomous_system_normalizable.rb +1 -4
  58. data/lib/mihari/concerns/configurable.rb +1 -1
  59. data/lib/mihari/concerns/database_connectable.rb +2 -2
  60. data/lib/mihari/concerns/retriable.rb +1 -1
  61. data/lib/mihari/config.rb +14 -2
  62. data/lib/mihari/constants.rb +2 -2
  63. data/lib/mihari/data_type.rb +1 -3
  64. data/lib/mihari/emitters/base.rb +2 -2
  65. data/lib/mihari/emitters/database.rb +1 -1
  66. data/lib/mihari/emitters/misp.rb +12 -4
  67. data/lib/mihari/emitters/slack.rb +9 -9
  68. data/lib/mihari/emitters/the_hive.rb +9 -4
  69. data/lib/mihari/emitters/webhook.rb +4 -4
  70. data/lib/mihari/emitters/yeti.rb +107 -0
  71. data/lib/mihari/enrichers/base.rb +1 -1
  72. data/lib/mihari/enrichers/google_public_dns.rb +1 -1
  73. data/lib/mihari/enrichers/mmdb.rb +1 -1
  74. data/lib/mihari/enrichers/shodan.rb +3 -3
  75. data/lib/mihari/enrichers/whois.rb +6 -91
  76. data/lib/mihari/entities/alert.rb +6 -6
  77. data/lib/mihari/entities/artifact.rb +17 -17
  78. data/lib/mihari/entities/autonomous_system.rb +1 -1
  79. data/lib/mihari/entities/config.rb +8 -4
  80. data/lib/mihari/entities/cpe.rb +2 -2
  81. data/lib/mihari/entities/dns.rb +3 -3
  82. data/lib/mihari/entities/geolocation.rb +3 -3
  83. data/lib/mihari/entities/ip_address.rb +3 -3
  84. data/lib/mihari/entities/messages.rb +3 -3
  85. data/lib/mihari/entities/pagination.rb +3 -3
  86. data/lib/mihari/entities/port.rb +2 -2
  87. data/lib/mihari/entities/reverse_dns.rb +2 -2
  88. data/lib/mihari/entities/rule.rb +8 -8
  89. data/lib/mihari/entities/tag.rb +3 -3
  90. data/lib/mihari/entities/vulnerability.rb +2 -2
  91. data/lib/mihari/entities/whois.rb +7 -7
  92. data/lib/mihari/errors.rb +1 -1
  93. data/lib/mihari/models/artifact.rb +2 -2
  94. data/lib/mihari/models/port.rb +1 -1
  95. data/lib/mihari/models/tag.rb +3 -0
  96. data/lib/mihari/rule.rb +10 -14
  97. data/lib/mihari/schemas/emitter.rb +9 -0
  98. data/lib/mihari/services/feed.rb +3 -3
  99. data/lib/mihari/services/getters.rb +1 -1
  100. data/lib/mihari/services/proxies.rb +1 -1
  101. data/lib/mihari/services/renderer.rb +2 -0
  102. data/lib/mihari/services/searchers.rb +1 -1
  103. data/lib/mihari/sidekiq/application.rb +2 -2
  104. data/lib/mihari/structs/censys.rb +4 -4
  105. data/lib/mihari/structs/google_public_dns.rb +3 -3
  106. data/lib/mihari/structs/greynoise.rb +2 -2
  107. data/lib/mihari/structs/onyphe.rb +3 -3
  108. data/lib/mihari/structs/shodan.rb +10 -10
  109. data/lib/mihari/structs/urlscan.rb +1 -1
  110. data/lib/mihari/structs/virustotal_intelligence.rb +2 -2
  111. data/lib/mihari/version.rb +1 -1
  112. data/lib/mihari/web/api.rb +1 -1
  113. data/lib/mihari/web/application.rb +1 -1
  114. data/lib/mihari/web/endpoints/alerts.rb +12 -12
  115. data/lib/mihari/web/endpoints/artifacts.rb +11 -11
  116. data/lib/mihari/web/endpoints/configs.rb +7 -2
  117. data/lib/mihari/web/endpoints/ip_addresses.rb +5 -5
  118. data/lib/mihari/web/endpoints/rules.rb +26 -26
  119. data/lib/mihari/web/endpoints/tags.rb +4 -4
  120. data/lib/mihari/web/public/assets/{index-ReF8ffd-.css → index-80oZkhZG.css} +1 -1
  121. data/lib/mihari/web/public/assets/index-BNLbw8nG.js +1783 -0
  122. data/lib/mihari/web/public/index.html +2 -2
  123. data/lib/mihari/web/public/redoc-static.html +2 -2
  124. data/lib/mihari.rb +4 -1
  125. data/mihari.gemspec +19 -19
  126. data/renovate.json +1 -3
  127. data/requirements.txt +1 -1
  128. metadata +48 -44
  129. data/.standard.yml +0 -4
  130. data/lib/mihari/web/public/assets/index-lRP933ks.js +0 -1787
  131. /data/lib/mihari/web/public/assets/{mode-yaml-BC4MIiYj.js → mode-yaml-ELgwiJiP.js} +0 -0
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mihari
4
+ module Emitters
5
+ class Yeti < Base
6
+ # @return [String, nil]
7
+ attr_reader :url
8
+
9
+ # @return [String, nil]
10
+ attr_reader :api_key
11
+
12
+ # @return [Array<Mihari::Models::Artifact>]
13
+ attr_accessor :artifacts
14
+
15
+ #
16
+ # @param [Mihari::Rule] rule
17
+ # @param [Hash, nil] options
18
+ # @param [Hash] params
19
+ #
20
+ def initialize(rule:, options: nil, **params)
21
+ super(rule:, options:)
22
+
23
+ @url = params[:url] || Mihari.config.yeti_url
24
+ @api_key = params[:api_key] || Mihari.config.yeti_api_key
25
+
26
+ @artifacts = []
27
+ end
28
+
29
+ #
30
+ # @return [Boolean]
31
+ #
32
+ def configured?
33
+ api_key? && url?
34
+ end
35
+
36
+ #
37
+ # Create a Hive alert
38
+ #
39
+ # @param [Array<Mihari::Models::Artifact>] artifacts
40
+ #
41
+ def call(artifacts)
42
+ return if artifacts.empty?
43
+
44
+ @artifacts = artifacts
45
+
46
+ client.create_observables({observables:})
47
+ end
48
+
49
+ #
50
+ # @return [String]
51
+ #
52
+ def target
53
+ URI(url).host || "N/A"
54
+ end
55
+
56
+ private
57
+
58
+ def client
59
+ Clients::Yeti.new(url, api_key:, timeout:)
60
+ end
61
+
62
+ #
63
+ # Check whether a URL is set or not
64
+ #
65
+ # @return [Boolean]
66
+ #
67
+ def url?
68
+ !url.nil?
69
+ end
70
+
71
+ def acceptable_artifacts
72
+ artifacts.reject { |artifact| artifact.data_type == "mail" }
73
+ end
74
+
75
+ #
76
+ # @param [Mihari::Models::Artifact] artifact
77
+ #
78
+ # @return [Hash]
79
+ #
80
+ def artifact_to_observable(artifact)
81
+ convert_table = {
82
+ domain: "hostname",
83
+ ip: "ipv4"
84
+ }
85
+
86
+ type = lambda do
87
+ detailed_type = DataType.detailed_type(artifact.data)
88
+ convert_table[detailed_type.to_sym] || detailed_type || artifact.data_type
89
+ end.call
90
+
91
+ {
92
+ tags:,
93
+ type:,
94
+ value: artifact.data
95
+ }
96
+ end
97
+
98
+ def tags
99
+ @tags ||= rule.tags.map(&:name)
100
+ end
101
+
102
+ def observables
103
+ acceptable_artifacts.map { |artifact| artifact_to_observable(artifact) }
104
+ end
105
+ end
106
+ end
107
+ end
@@ -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
@@ -22,13 +22,13 @@ module Mihari
22
22
 
23
23
  if tapped.reverse_dns_names.empty?
24
24
  tapped.reverse_dns_names = (res&.hostnames || []).map do |name|
25
- Models::ReverseDnsName.new(name: name)
25
+ Models::ReverseDnsName.new(name:)
26
26
  end
27
27
  end
28
28
 
29
29
  if tapped.vulnerabilities.empty?
30
30
  tapped.vulnerabilities = (res&.vulns || []).map do |name|
31
- Models::Vulnerability.new(name: name)
31
+ Models::Vulnerability.new(name:)
32
32
  end
33
33
  end
34
34
  end
@@ -50,7 +50,7 @@ module Mihari
50
50
  end
51
51
 
52
52
  def client
53
- @client ||= Clients::ShodanInternetDB.new(timeout: timeout)
53
+ @client ||= Clients::ShodanInternetDB.new(timeout:)
54
54
  end
55
55
  end
56
56
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "whois-parser"
4
-
5
3
  module Mihari
6
4
  module Enrichers
7
5
  #
@@ -18,22 +16,15 @@ module Mihari
18
16
  def call(artifact)
19
17
  return if artifact.domain.nil?
20
18
 
21
- domain = PublicSuffix.domain(artifact.domain)
22
- record = memoized_lookup(domain)
23
- return if record.parser.available?
24
-
25
- artifact.whois_record ||= Models::WhoisRecord.new(
26
- domain: domain,
27
- created_on: get_created_on(record.parser),
28
- updated_on: get_updated_on(record.parser),
29
- expires_on: get_expires_on(record.parser),
30
- registrar: get_registrar(record.parser),
31
- contacts: get_contacts(record.parser)
32
- )
19
+ artifact.whois_record ||= memoized_lookup(PublicSuffix.domain(artifact.domain))
33
20
  end
34
21
 
35
22
  private
36
23
 
24
+ def client
25
+ @client ||= Clients::Whois.new(timeout:)
26
+ end
27
+
37
28
  #
38
29
  # @param [Mihari::Models::Artifact] artifact
39
30
  #
@@ -53,85 +44,9 @@ module Mihari
53
44
  # @return [Mihari::Models::WhoisRecord, nil]
54
45
  #
55
46
  def memoized_lookup(domain)
56
- whois.lookup domain
47
+ client.lookup domain
57
48
  end
58
49
  memo_wise :memoized_lookup
59
-
60
- #
61
- # @return [::Whois::Client]
62
- #
63
- def whois
64
- @whois ||= lambda do
65
- return ::Whois::Client.new if timeout.nil?
66
-
67
- ::Whois::Client.new(timeout: timeout)
68
- end.call
69
- end
70
-
71
- #
72
- # Get created_on
73
- #
74
- # @param [::Whois::Parser] parser
75
- #
76
- # @return [Date, nil]
77
- #
78
- def get_created_on(parser)
79
- parser.created_on
80
- rescue ::Whois::AttributeNotImplemented
81
- nil
82
- end
83
-
84
- #
85
- # Get updated_on
86
- #
87
- # @param [::Whois::Parser] parser
88
- #
89
- # @return [Date, nil]
90
- #
91
- def get_updated_on(parser)
92
- parser.updated_on
93
- rescue ::Whois::AttributeNotImplemented
94
- nil
95
- end
96
-
97
- #
98
- # Get expires_on
99
- #
100
- # @param [::Whois::Parser] parser
101
- #
102
- # @return [Date, nil]
103
- #
104
- def get_expires_on(parser)
105
- parser.expires_on
106
- rescue ::Whois::AttributeNotImplemented
107
- nil
108
- end
109
-
110
- #
111
- # Get registrar
112
- #
113
- # @param [::Whois::Parser] parser
114
- #
115
- # @return [Hash, nil]
116
- #
117
- def get_registrar(parser)
118
- parser.registrar&.to_h
119
- rescue ::Whois::AttributeNotImplemented
120
- nil
121
- end
122
-
123
- #
124
- # Get contacts
125
- #
126
- # @param [::Whois::Parser] parser
127
- #
128
- # @return [Array<Hash>, nil]
129
- #
130
- def get_contacts(parser)
131
- parser.contacts.map(&:to_h)
132
- rescue ::Whois::AttributeNotImplemented
133
- nil
134
- end
135
50
  end
136
51
  end
137
52
  end
@@ -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
@@ -3,8 +3,8 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class Port < Grape::Entity
6
- expose :number, documentation: { type: Integer, required: true }
7
- expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
6
+ expose :number, documentation: {type: Integer, required: true}
7
+ expose :created_at, documentation: {type: DateTime, required: true}, as: :createdAt
8
8
  end
9
9
  end
10
10
  end
@@ -3,8 +3,8 @@
3
3
  module Mihari
4
4
  module Entities
5
5
  class ReverseDnsName < 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,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