mihari 5.6.1 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -1
  3. data/README.md +1 -0
  4. data/config.ru +1 -1
  5. data/docs/analyzers/fofa.md +31 -0
  6. data/docs/analyzers/index.md +1 -0
  7. data/frontend/package-lock.json +183 -186
  8. data/frontend/package.json +10 -10
  9. data/frontend/src/components/alert/Form.vue +1 -14
  10. data/frontend/src/components/artifact/AS.vue +2 -8
  11. data/frontend/src/components/artifact/DnsRecords.vue +2 -8
  12. data/frontend/src/components/artifact/ReverseDnsNames.vue +2 -10
  13. data/frontend/src/components/artifact/WhoisRecord.vue +1 -1
  14. data/lib/mihari/{base.rb → actor.rb} +27 -3
  15. data/lib/mihari/analyzers/base.rb +16 -20
  16. data/lib/mihari/analyzers/binaryedge.rb +4 -1
  17. data/lib/mihari/analyzers/censys.rb +5 -3
  18. data/lib/mihari/analyzers/circl.rb +4 -1
  19. data/lib/mihari/analyzers/crtsh.rb +4 -1
  20. data/lib/mihari/analyzers/dnstwister.rb +4 -1
  21. data/lib/mihari/analyzers/feed.rb +3 -0
  22. data/lib/mihari/analyzers/fofa.rb +65 -0
  23. data/lib/mihari/analyzers/greynoise.rb +4 -1
  24. data/lib/mihari/analyzers/hunterhow.rb +7 -2
  25. data/lib/mihari/analyzers/onyphe.rb +4 -1
  26. data/lib/mihari/analyzers/otx.rb +4 -1
  27. data/lib/mihari/analyzers/passivetotal.rb +5 -2
  28. data/lib/mihari/analyzers/pulsedive.rb +4 -1
  29. data/lib/mihari/analyzers/securitytrails.rb +5 -2
  30. data/lib/mihari/analyzers/shodan.rb +4 -1
  31. data/lib/mihari/analyzers/urlscan.rb +5 -2
  32. data/lib/mihari/analyzers/virustotal.rb +9 -6
  33. data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -1
  34. data/lib/mihari/analyzers/zoomeye.rb +8 -5
  35. data/lib/mihari/cli/alert.rb +3 -0
  36. data/lib/mihari/cli/base.rb +3 -0
  37. data/lib/mihari/cli/database.rb +3 -0
  38. data/lib/mihari/cli/main.rb +3 -0
  39. data/lib/mihari/cli/rule.rb +3 -0
  40. data/lib/mihari/clients/base.rb +3 -0
  41. data/lib/mihari/clients/binaryedge.rb +5 -2
  42. data/lib/mihari/clients/censys.rb +7 -4
  43. data/lib/mihari/clients/circl.rb +3 -0
  44. data/lib/mihari/clients/crtsh.rb +5 -2
  45. data/lib/mihari/clients/dnstwister.rb +3 -0
  46. data/lib/mihari/clients/fofa.rb +83 -0
  47. data/lib/mihari/clients/greynoise.rb +5 -2
  48. data/lib/mihari/clients/hunterhow.rb +5 -2
  49. data/lib/mihari/clients/misp.rb +3 -0
  50. data/lib/mihari/clients/onyphe.rb +5 -2
  51. data/lib/mihari/clients/otx.rb +3 -0
  52. data/lib/mihari/clients/passivetotal.rb +7 -4
  53. data/lib/mihari/clients/publsedive.rb +4 -1
  54. data/lib/mihari/clients/securitytrails.rb +6 -3
  55. data/lib/mihari/clients/shodan.rb +5 -2
  56. data/lib/mihari/clients/the_hive.rb +3 -0
  57. data/lib/mihari/clients/urlscan.rb +7 -4
  58. data/lib/mihari/clients/virustotal.rb +5 -2
  59. data/lib/mihari/clients/zoomeye.rb +3 -0
  60. data/lib/mihari/commands/alert.rb +5 -14
  61. data/lib/mihari/commands/database.rb +3 -0
  62. data/lib/mihari/commands/rule.rb +11 -11
  63. data/lib/mihari/commands/search.rb +9 -6
  64. data/lib/mihari/commands/version.rb +3 -0
  65. data/lib/mihari/commands/web.rb +4 -1
  66. data/lib/mihari/config.rb +139 -150
  67. data/lib/mihari/constants.rb +1 -1
  68. data/lib/mihari/database.rb +6 -0
  69. data/lib/mihari/emitters/base.rb +16 -25
  70. data/lib/mihari/emitters/database.rb +10 -9
  71. data/lib/mihari/emitters/misp.rb +20 -41
  72. data/lib/mihari/emitters/slack.rb +16 -13
  73. data/lib/mihari/emitters/the_hive.rb +18 -46
  74. data/lib/mihari/emitters/webhook.rb +34 -23
  75. data/lib/mihari/enrichers/base.rb +16 -15
  76. data/lib/mihari/enrichers/google_public_dns.rb +6 -5
  77. data/lib/mihari/enrichers/ipinfo.rb +10 -8
  78. data/lib/mihari/enrichers/shodan.rb +4 -6
  79. data/lib/mihari/enrichers/whois.rb +13 -10
  80. data/lib/mihari/errors.rb +6 -0
  81. data/lib/mihari/feed/parser.rb +3 -0
  82. data/lib/mihari/feed/reader.rb +3 -0
  83. data/lib/mihari/http.rb +6 -0
  84. data/lib/mihari/mixins/autonomous_system.rb +3 -0
  85. data/lib/mihari/mixins/configurable.rb +3 -0
  86. data/lib/mihari/mixins/error_notification.rb +3 -0
  87. data/lib/mihari/mixins/falsepositive.rb +3 -0
  88. data/lib/mihari/mixins/refang.rb +3 -0
  89. data/lib/mihari/mixins/retriable.rb +6 -2
  90. data/lib/mihari/models/alert.rb +78 -73
  91. data/lib/mihari/models/artifact.rb +186 -178
  92. data/lib/mihari/models/autonomous_system.rb +25 -20
  93. data/lib/mihari/models/cpe.rb +24 -19
  94. data/lib/mihari/models/dns.rb +27 -22
  95. data/lib/mihari/models/geolocation.rb +25 -20
  96. data/lib/mihari/models/port.rb +24 -19
  97. data/lib/mihari/models/reverse_dns.rb +24 -19
  98. data/lib/mihari/models/rule.rb +71 -66
  99. data/lib/mihari/models/tag.rb +8 -3
  100. data/lib/mihari/models/tagging.rb +8 -3
  101. data/lib/mihari/models/whois.rb +20 -17
  102. data/lib/mihari/rule.rb +357 -0
  103. data/lib/mihari/schemas/alert.rb +3 -0
  104. data/lib/mihari/schemas/analyzer.rb +105 -87
  105. data/lib/mihari/schemas/emitter.rb +12 -5
  106. data/lib/mihari/schemas/enricher.rb +11 -4
  107. data/lib/mihari/schemas/macros.rb +4 -0
  108. data/lib/mihari/schemas/mixins.rb +20 -0
  109. data/lib/mihari/schemas/rule.rb +6 -10
  110. data/lib/mihari/service.rb +16 -0
  111. data/lib/mihari/services/alert_builder.rb +8 -5
  112. data/lib/mihari/services/alert_proxy.rb +16 -7
  113. data/lib/mihari/services/alert_runner.rb +10 -14
  114. data/lib/mihari/services/rule_builder.rb +10 -7
  115. data/lib/mihari/services/rule_runner.rb +11 -13
  116. data/lib/mihari/structs/binaryedge.rb +14 -29
  117. data/lib/mihari/structs/censys.rb +54 -133
  118. data/lib/mihari/structs/config.rb +20 -31
  119. data/lib/mihari/structs/filters.rb +38 -0
  120. data/lib/mihari/structs/fofa.rb +44 -0
  121. data/lib/mihari/structs/google_public_dns.rb +10 -28
  122. data/lib/mihari/structs/greynoise.rb +38 -89
  123. data/lib/mihari/structs/hunterhow.rb +27 -25
  124. data/lib/mihari/structs/ipinfo.rb +14 -35
  125. data/lib/mihari/structs/onyphe.rb +36 -81
  126. data/lib/mihari/structs/shodan.rb +53 -118
  127. data/lib/mihari/structs/urlscan.rb +27 -66
  128. data/lib/mihari/structs/virustotal_intelligence.rb +23 -59
  129. data/lib/mihari/type_checker.rb +4 -0
  130. data/lib/mihari/types.rb +3 -0
  131. data/lib/mihari/version.rb +1 -1
  132. data/lib/mihari/web/api.rb +15 -10
  133. data/lib/mihari/web/app.rb +59 -54
  134. data/lib/mihari/web/endpoints/alerts.rb +94 -89
  135. data/lib/mihari/web/endpoints/artifacts.rb +115 -110
  136. data/lib/mihari/web/endpoints/configs.rb +18 -13
  137. data/lib/mihari/web/endpoints/ip_addresses.rb +21 -16
  138. data/lib/mihari/web/endpoints/rules.rb +202 -204
  139. data/lib/mihari/web/endpoints/tags.rb +41 -36
  140. data/lib/mihari/web/middleware/connection_adapter.rb +16 -9
  141. data/lib/mihari/web/middleware/error_notification_adapter.rb +17 -10
  142. data/lib/mihari/web/public/assets/{index-9cc489e6.js → index-821134e2.js} +54 -54
  143. data/lib/mihari/web/public/assets/mode-yaml-24faa242.js +8 -0
  144. data/lib/mihari/web/public/index.html +1 -1
  145. data/lib/mihari.rb +30 -13
  146. data/mihari.gemspec +9 -3
  147. data/mkdocs.yml +3 -2
  148. data/requirements.txt +1 -1
  149. metadata +44 -26
  150. data/lib/mihari/analyzers/rule.rb +0 -232
  151. data/lib/mihari/services/rule_proxy.rb +0 -182
  152. data/lib/mihari/templates/rule.yml.erb +0 -5
  153. data/lib/mihari/web/public/assets/mode-yaml-a21faa53.js +0 -8
@@ -1,29 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- class CPE < ActiveRecord::Base
5
- belongs_to :artifact
4
+ module Models
5
+ #
6
+ # CPE model
7
+ #
8
+ class CPE < ActiveRecord::Base
9
+ belongs_to :artifact
6
10
 
7
- class << self
8
- include Dry::Monads[:result]
11
+ class << self
12
+ include Dry::Monads[:result]
9
13
 
10
- #
11
- # Build CPEs
12
- #
13
- # @param [String] ip
14
- # @param [Mihari::Enrichers::Shodan] enricher
15
- #
16
- # @return [Array<Mihari::CPE>]
17
- #
18
- def build_by_ip(ip, enricher: Enrichers::Shodan.new)
19
- result = enricher.query_result(ip).bind do |res|
20
- if res.nil?
21
- Success []
22
- else
23
- Success(res.cpes.map { |cpe| new(cpe: cpe) })
14
+ #
15
+ # Build CPEs
16
+ #
17
+ # @param [String] ip
18
+ # @param [Mihari::Enrichers::Shodan] enricher
19
+ #
20
+ # @return [Array<Mihari::CPE>]
21
+ #
22
+ def build_by_ip(ip, enricher: Enrichers::Shodan.new)
23
+ result = enricher.result(ip).bind do |res|
24
+ if res.nil?
25
+ Success []
26
+ else
27
+ Success(res.cpes.map { |cpe| new(cpe: cpe) })
28
+ end
24
29
  end
30
+ result.value_or []
25
31
  end
26
- result.value_or []
27
32
  end
28
33
  end
29
34
  end
@@ -1,31 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- class DnsRecord < ActiveRecord::Base
5
- belongs_to :artifact
4
+ module Models
5
+ #
6
+ # DNS record model
7
+ #
8
+ class DnsRecord < ActiveRecord::Base
9
+ belongs_to :artifact
6
10
 
7
- class << self
8
- include Dry::Monads[:result]
11
+ class << self
12
+ include Dry::Monads[:result]
9
13
 
10
- #
11
- # Build DNS records
12
- #
13
- # @param [String] domain
14
- # @param [Mihari::Enrichers::Shodan] enricher
15
- #
16
- # @return [Array<Mihari::DnsRecord>]
17
- #
18
- def build_by_domain(domain, enricher: Enrichers::GooglePublicDNS.new)
19
- result = enricher.query_result(domain).bind do |responses|
20
- Success(
21
- responses.map do |res|
22
- res.answers.map do |answer|
23
- new(resource: answer.resource_type, value: answer.data)
24
- end
25
- end.flatten
26
- )
14
+ #
15
+ # Build DNS records
16
+ #
17
+ # @param [String] domain
18
+ # @param [Mihari::Enrichers::Shodan] enricher
19
+ #
20
+ # @return [Array<Mihari::Models::DnsRecord>]
21
+ #
22
+ def build_by_domain(domain, enricher: Enrichers::GooglePublicDNS.new)
23
+ result = enricher.result(domain).bind do |responses|
24
+ Success(
25
+ responses.map do |res|
26
+ res.answers.map do |answer|
27
+ new(resource: answer.resource_type, value: answer.data)
28
+ end
29
+ end.flatten
30
+ )
31
+ end
32
+ result.value_or []
27
33
  end
28
- result.value_or []
29
34
  end
30
35
  end
31
36
  end
@@ -3,30 +3,35 @@
3
3
  require "normalize_country"
4
4
 
5
5
  module Mihari
6
- class Geolocation < ActiveRecord::Base
7
- belongs_to :artifact
6
+ module Models
7
+ #
8
+ # Geolocation model
9
+ #
10
+ class Geolocation < ActiveRecord::Base
11
+ belongs_to :artifact
8
12
 
9
- class << self
10
- include Dry::Monads[:result]
13
+ class << self
14
+ include Dry::Monads[:result]
11
15
 
12
- #
13
- # Build Geolocation
14
- #
15
- # @param [String] ip
16
- # @param [Mihari::Enrichers::IPinfo] enricher
17
- #
18
- # @return [Mihari::Geolocation, nil]
19
- #
20
- def build_by_ip(ip, enricher: Enrichers::IPInfo.new)
21
- result = enricher.query_result(ip).bind do |res|
22
- value = res&.country_code
23
- if value.nil?
24
- Success nil
25
- else
26
- Success new(country: NormalizeCountry(value, to: :short), country_code: value)
16
+ #
17
+ # Build Geolocation
18
+ #
19
+ # @param [String] ip
20
+ # @param [Mihari::Enrichers::IPinfo] enricher
21
+ #
22
+ # @return [Mihari::Geolocation, nil]
23
+ #
24
+ def build_by_ip(ip, enricher: Enrichers::IPInfo.new)
25
+ result = enricher.result(ip).bind do |res|
26
+ value = res&.country_code
27
+ if value.nil?
28
+ Success nil
29
+ else
30
+ Success new(country: NormalizeCountry(value, to: :short), country_code: value)
31
+ end
27
32
  end
33
+ result.value_or nil
28
34
  end
29
- result.value_or nil
30
35
  end
31
36
  end
32
37
  end
@@ -1,29 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- class Port < ActiveRecord::Base
5
- belongs_to :artifact
4
+ module Models
5
+ #
6
+ # Port model
7
+ #
8
+ class Port < ActiveRecord::Base
9
+ belongs_to :artifact
6
10
 
7
- class << self
8
- include Dry::Monads[:result]
11
+ class << self
12
+ include Dry::Monads[:result]
9
13
 
10
- #
11
- # Build ports
12
- #
13
- # @param [String] ip
14
- # @param [Mihari::Enrichers::Shodan] enricher
15
- #
16
- # @return [Array<Mihari::Port>]
17
- #
18
- def build_by_ip(ip, enricher: Enrichers::Shodan.new)
19
- result = enricher.query_result(ip).bind do |res|
20
- if res.nil?
21
- Success []
22
- else
23
- Success(res.ports.map { |port| new(port: port) })
14
+ #
15
+ # Build ports
16
+ #
17
+ # @param [String] ip
18
+ # @param [Mihari::Enrichers::Shodan] enricher
19
+ #
20
+ # @return [Array<Mihari::Port>]
21
+ #
22
+ def build_by_ip(ip, enricher: Enrichers::Shodan.new)
23
+ result = enricher.result(ip).bind do |res|
24
+ if res.nil?
25
+ Success []
26
+ else
27
+ Success(res.ports.map { |port| new(port: port) })
28
+ end
24
29
  end
30
+ result.value_or []
25
31
  end
26
- result.value_or []
27
32
  end
28
33
  end
29
34
  end
@@ -1,29 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- class ReverseDnsName < ActiveRecord::Base
5
- belongs_to :artifact
4
+ module Models
5
+ #
6
+ # Reverse DNS name model
7
+ #
8
+ class ReverseDnsName < ActiveRecord::Base
9
+ belongs_to :artifact
6
10
 
7
- class << self
8
- include Dry::Monads[:result]
11
+ class << self
12
+ include Dry::Monads[:result]
9
13
 
10
- #
11
- # Build reverse DNS names
12
- #
13
- # @param [String] ip
14
- # @param [Mihari::Enrichers::Shodan] enricher
15
- #
16
- # @return [Array<Mihari::ReverseDnsName>]
17
- #
18
- def build_by_ip(ip, enricher: Enrichers::Shodan.new)
19
- result = enricher.query_result(ip).bind do |res|
20
- if res.nil?
21
- Success []
22
- else
23
- Success(res.hostnames.map { |name| new(name: name) })
14
+ #
15
+ # Build reverse DNS names
16
+ #
17
+ # @param [String] ip
18
+ # @param [Mihari::Enrichers::Shodan] enricher
19
+ #
20
+ # @return [Array<Mihari::Models::ReverseDnsName>]
21
+ #
22
+ def build_by_ip(ip, enricher: Enrichers::Shodan.new)
23
+ result = enricher.result(ip).bind do |res|
24
+ if res.nil?
25
+ Success []
26
+ else
27
+ Success(res.hostnames.map { |name| new(name: name) })
28
+ end
24
29
  end
30
+ result.value_or []
25
31
  end
26
- result.value_or []
27
32
  end
28
33
  end
29
34
  end
@@ -3,77 +3,82 @@
3
3
  require "yaml"
4
4
 
5
5
  module Mihari
6
- class Rule < ActiveRecord::Base
7
- has_many :alerts, dependent: :destroy
8
-
9
- def symbolized_data
10
- @symbolized_data ||= data.deep_symbolize_keys
11
- end
12
-
13
- def yaml
14
- data.to_yaml
15
- end
16
-
17
- def tags
18
- (data["tags"] || []).map { |tag| { name: tag } }
19
- end
20
-
21
- class << self
22
- #
23
- # Search rules
24
- #
25
- # @param [Structs::Filters::Rule::SearchFilterWithPagination] filter
26
- #
27
- # @return [Array<Rule>]
28
- #
29
- def search(filter)
30
- limit = filter.limit.to_i
31
- raise ArgumentError, "limit should be bigger than zero" unless limit.positive?
32
-
33
- page = filter.page.to_i
34
- raise ArgumentError, "page should be bigger than zero" unless page.positive?
35
-
36
- offset = (page - 1) * limit
37
-
38
- relation = build_relation(filter.without_pagination)
39
-
40
- # TODO: improve queires
41
- rule_ids = relation.limit(limit).offset(offset).order(created_at: :desc).pluck(:id).uniq
42
- where(id: [rule_ids]).order(created_at: :desc)
6
+ module Models
7
+ #
8
+ # Rule model
9
+ #
10
+ class Rule < ActiveRecord::Base
11
+ has_many :alerts, dependent: :destroy
12
+
13
+ def symbolized_data
14
+ @symbolized_data ||= data.deep_symbolize_keys
43
15
  end
44
16
 
45
- #
46
- # Count alerts
47
- #
48
- # @param [Structs::Filters::Rule::SearchFilterWithPagination] filter
49
- #
50
- # @return [Integer]
51
- #
52
- def count(filter)
53
- relation = build_relation(filter)
54
- relation.distinct("rules.id").count
17
+ def yaml
18
+ data.to_yaml
55
19
  end
56
20
 
57
- private
58
-
59
- #
60
- # @param [Structs::Filters::Rule::SearchFilter] filter
61
- #
62
- # @return [Mihari::Rule]
63
- #
64
- def build_relation(filter)
65
- relation = self
66
- relation = relation.includes(alerts: :tags)
67
-
68
- relation = relation.where(alerts: { tags: { name: filter.tag_name } }) if filter.tag_name
69
-
70
- relation = relation.where("rules.title LIKE ?", "%#{filter.title}%") if filter.title
71
- relation = relation.where("rules.description LIKE ?", "%#{filter.description}%") if filter.description
72
-
73
- relation = relation.where("rules.created_at >= ?", filter.from_at) if filter.from_at
74
- relation = relation.where("rules.created_at <= ?", filter.to_at) if filter.to_at
21
+ def tags
22
+ (data["tags"] || []).map { |tag| { name: tag } }
23
+ end
75
24
 
76
- relation
25
+ class << self
26
+ #
27
+ # Search rules
28
+ #
29
+ # @param [Mihari::Structs::Filters::Rule::SearchFilterWithPagination] filter
30
+ #
31
+ # @return [Array<Rule>]
32
+ #
33
+ def search(filter)
34
+ limit = filter.limit.to_i
35
+ raise ArgumentError, "limit should be bigger than zero" unless limit.positive?
36
+
37
+ page = filter.page.to_i
38
+ raise ArgumentError, "page should be bigger than zero" unless page.positive?
39
+
40
+ offset = (page - 1) * limit
41
+
42
+ relation = build_relation(filter.without_pagination)
43
+
44
+ # TODO: improve queires
45
+ rule_ids = relation.limit(limit).offset(offset).order(created_at: :desc).pluck(:id).uniq
46
+ where(id: [rule_ids]).order(created_at: :desc)
47
+ end
48
+
49
+ #
50
+ # Count alerts
51
+ #
52
+ # @param [Mihari::Structs::Filters::Rule::SearchFilterWithPagination] filter
53
+ #
54
+ # @return [Integer]
55
+ #
56
+ def count(filter)
57
+ relation = build_relation(filter)
58
+ relation.distinct("rules.id").count
59
+ end
60
+
61
+ private
62
+
63
+ #
64
+ # @param [Mihari::Structs::Filters::Rule::SearchFilter] filter
65
+ #
66
+ # @return [Mihari::Models::Rule]
67
+ #
68
+ def build_relation(filter)
69
+ relation = self
70
+ relation = relation.includes(alerts: :tags)
71
+
72
+ relation = relation.where(alerts: { tags: { name: filter.tag_name } }) if filter.tag_name
73
+
74
+ relation = relation.where("rules.title LIKE ?", "%#{filter.title}%") if filter.title
75
+ relation = relation.where("rules.description LIKE ?", "%#{filter.description}%") if filter.description
76
+
77
+ relation = relation.where("rules.created_at >= ?", filter.from_at) if filter.from_at
78
+ relation = relation.where("rules.created_at <= ?", filter.to_at) if filter.to_at
79
+
80
+ relation
81
+ end
77
82
  end
78
83
  end
79
84
  end
@@ -1,8 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- class Tag < ActiveRecord::Base
5
- has_many :taggings, dependent: :destroy
6
- has_many :tags, through: :taggings
4
+ module Models
5
+ #
6
+ # Tag model
7
+ #
8
+ class Tag < ActiveRecord::Base
9
+ has_many :taggings, dependent: :destroy
10
+ has_many :tags, through: :taggings
11
+ end
7
12
  end
8
13
  end
@@ -1,8 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- class Tagging < ActiveRecord::Base
5
- belongs_to :alert
6
- belongs_to :tag
4
+ module Models
5
+ #
6
+ # Tagging model
7
+ #
8
+ class Tagging < ActiveRecord::Base
9
+ belongs_to :alert
10
+ belongs_to :tag
11
+ end
7
12
  end
8
13
  end
@@ -1,25 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- class WhoisRecord < ActiveRecord::Base
5
- belongs_to :artifact
4
+ module Models
5
+ #
6
+ # Whois record model
7
+ #
8
+ class WhoisRecord < ActiveRecord::Base
9
+ belongs_to :artifact
6
10
 
7
- @memo = {}
11
+ @memo = {}
8
12
 
9
- class << self
10
- include Dry::Monads[:result]
11
-
12
- #
13
- # Build whois record
14
- #
15
- # @param [String] domain
16
- # @param [Mihari::Enrichers::Whois] enricher
17
- #
18
- # @return [WhoisRecord, nil]
19
- #
20
- def build_by_domain(domain, enricher: Enrichers::Whois.new)
21
- result = enricher.query_result(domain)
22
- result.value_or nil
13
+ class << self
14
+ #
15
+ # Build whois record
16
+ #
17
+ # @param [String] domain
18
+ # @param [Mihari::Enrichers::Whois] enricher
19
+ #
20
+ # @return [WhoisRecord, nil]
21
+ #
22
+ def build_by_domain(domain, enricher: Enrichers::Whois.new)
23
+ result = enricher.result(domain)
24
+ result.value_or nil
25
+ end
23
26
  end
24
27
  end
25
28
  end