mihari 5.6.1 → 5.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/frontend/package-lock.json +173 -176
  3. data/frontend/package.json +9 -9
  4. data/lib/mihari/{base.rb → actor.rb} +16 -2
  5. data/lib/mihari/analyzers/base.rb +5 -10
  6. data/lib/mihari/analyzers/censys.rb +1 -1
  7. data/lib/mihari/analyzers/hunterhow.rb +1 -1
  8. data/lib/mihari/analyzers/passivetotal.rb +1 -1
  9. data/lib/mihari/analyzers/pulsedive.rb +1 -1
  10. data/lib/mihari/analyzers/securitytrails.rb +1 -1
  11. data/lib/mihari/analyzers/urlscan.rb +1 -1
  12. data/lib/mihari/analyzers/virustotal.rb +5 -5
  13. data/lib/mihari/analyzers/zoomeye.rb +3 -3
  14. data/lib/mihari/clients/crtsh.rb +2 -2
  15. data/lib/mihari/clients/passivetotal.rb +4 -4
  16. data/lib/mihari/clients/securitytrails.rb +3 -3
  17. data/lib/mihari/commands/rule.rb +2 -11
  18. data/lib/mihari/commands/search.rb +1 -1
  19. data/lib/mihari/emitters/base.rb +13 -24
  20. data/lib/mihari/emitters/database.rb +7 -9
  21. data/lib/mihari/emitters/misp.rb +14 -38
  22. data/lib/mihari/emitters/slack.rb +14 -11
  23. data/lib/mihari/emitters/the_hive.rb +16 -44
  24. data/lib/mihari/emitters/webhook.rb +31 -21
  25. data/lib/mihari/enrichers/base.rb +1 -6
  26. data/lib/mihari/enrichers/whois.rb +1 -1
  27. data/lib/mihari/models/alert.rb +75 -73
  28. data/lib/mihari/models/artifact.rb +182 -180
  29. data/lib/mihari/models/autonomous_system.rb +22 -20
  30. data/lib/mihari/models/cpe.rb +21 -19
  31. data/lib/mihari/models/dns.rb +24 -22
  32. data/lib/mihari/models/geolocation.rb +22 -20
  33. data/lib/mihari/models/port.rb +21 -19
  34. data/lib/mihari/models/reverse_dns.rb +21 -19
  35. data/lib/mihari/models/rule.rb +67 -65
  36. data/lib/mihari/models/tag.rb +5 -3
  37. data/lib/mihari/models/tagging.rb +5 -3
  38. data/lib/mihari/models/whois.rb +18 -16
  39. data/lib/mihari/rule.rb +352 -0
  40. data/lib/mihari/schemas/analyzer.rb +94 -87
  41. data/lib/mihari/schemas/emitter.rb +9 -5
  42. data/lib/mihari/schemas/enricher.rb +8 -4
  43. data/lib/mihari/schemas/mixins.rb +15 -0
  44. data/lib/mihari/schemas/rule.rb +3 -10
  45. data/lib/mihari/services/alert_builder.rb +1 -1
  46. data/lib/mihari/services/alert_proxy.rb +10 -6
  47. data/lib/mihari/services/alert_runner.rb +4 -4
  48. data/lib/mihari/services/rule_builder.rb +3 -3
  49. data/lib/mihari/services/rule_runner.rb +5 -5
  50. data/lib/mihari/structs/binaryedge.rb +1 -1
  51. data/lib/mihari/structs/censys.rb +6 -6
  52. data/lib/mihari/structs/config.rb +1 -1
  53. data/lib/mihari/structs/greynoise.rb +5 -5
  54. data/lib/mihari/structs/hunterhow.rb +3 -3
  55. data/lib/mihari/structs/onyphe.rb +5 -5
  56. data/lib/mihari/structs/shodan.rb +6 -6
  57. data/lib/mihari/structs/urlscan.rb +3 -3
  58. data/lib/mihari/structs/virustotal_intelligence.rb +3 -3
  59. data/lib/mihari/version.rb +1 -1
  60. data/lib/mihari/web/endpoints/alerts.rb +4 -4
  61. data/lib/mihari/web/endpoints/artifacts.rb +6 -6
  62. data/lib/mihari/web/endpoints/rules.rb +10 -17
  63. data/lib/mihari/web/endpoints/tags.rb +2 -2
  64. data/lib/mihari/web/public/assets/{index-9cc489e6.js → index-28d4c79d.js} +48 -48
  65. data/lib/mihari/web/public/index.html +1 -1
  66. data/lib/mihari.rb +6 -8
  67. data/mihari.gemspec +1 -2
  68. data/requirements.txt +1 -1
  69. metadata +8 -22
  70. data/lib/mihari/analyzers/rule.rb +0 -232
  71. data/lib/mihari/services/rule_proxy.rb +0 -182
@@ -1,229 +1,231 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class ArtifactValidator < ActiveModel::Validator
4
- def validate(record)
5
- return if record.data_type
6
-
7
- record.errors.add :data, "#{record.data} is not supported"
8
- end
9
- end
10
-
11
3
  module Mihari
12
- class Artifact < ActiveRecord::Base
13
- belongs_to :alert
4
+ module Models
5
+ class ArtifactValidator < ActiveModel::Validator
6
+ def validate(record)
7
+ return if record.data_type
14
8
 
15
- has_one :autonomous_system, dependent: :destroy
16
- has_one :geolocation, dependent: :destroy
17
- has_one :whois_record, dependent: :destroy
9
+ record.errors.add :data, "#{record.data} is not supported"
10
+ end
11
+ end
18
12
 
19
- has_many :cpes, dependent: :destroy
20
- has_many :dns_records, dependent: :destroy
21
- has_many :ports, dependent: :destroy
22
- has_many :reverse_dns_names, dependent: :destroy
13
+ class Artifact < ActiveRecord::Base
14
+ belongs_to :alert
23
15
 
24
- include ActiveModel::Validations
16
+ has_one :autonomous_system, dependent: :destroy
17
+ has_one :geolocation, dependent: :destroy
18
+ has_one :whois_record, dependent: :destroy
25
19
 
26
- validates_with ArtifactValidator
20
+ has_many :cpes, dependent: :destroy
21
+ has_many :dns_records, dependent: :destroy
22
+ has_many :ports, dependent: :destroy
23
+ has_many :reverse_dns_names, dependent: :destroy
27
24
 
28
- # @return [Array<Mihari::Tag>] Tags
29
- attr_accessor :tags
25
+ include ActiveModel::Validations
30
26
 
31
- # @return [String, nil] Rule ID
32
- attr_accessor :rule_id
27
+ validates_with ArtifactValidator
33
28
 
34
- def initialize(*args, **kwargs)
35
- attrs = args.first || kwargs
36
- data_ = attrs[:data]
29
+ # @return [Array<Mihari::Tag>] Tags
30
+ attr_accessor :tags
37
31
 
38
- raise TypeError if data_.is_a?(Array) || data_.is_a?(Hash)
32
+ # @return [String, nil] Rule ID
33
+ attr_accessor :rule_id
39
34
 
40
- super(*args, **kwargs)
35
+ def initialize(*args, **kwargs)
36
+ attrs = args.first || kwargs
37
+ data_ = attrs[:data]
41
38
 
42
- self.data_type = TypeChecker.type(data)
39
+ raise TypeError if data_.is_a?(Array) || data_.is_a?(Hash)
43
40
 
44
- @tags = []
45
- @rule_id = ""
46
- end
41
+ super(*args, **kwargs)
47
42
 
48
- #
49
- # Check uniqueness of artifact
50
- #
51
- # @param [Time, nil] base_time Base time to check decaying
52
- # @param [Integer, nil] artifact_lifetime Artifact lifetime (TTL) in seconds
53
- #
54
- # @return [Boolean] true if it is unique. Otherwise false.
55
- #
56
- def unique?(base_time: nil, artifact_lifetime: nil)
57
- artifact = self.class.joins(:alert).where(
58
- data: data,
59
- alert: { rule_id: rule_id }
60
- ).order(created_at: :desc).first
61
- return true if artifact.nil?
62
-
63
- # check whether the artifact is decayed or not
64
- return false if artifact_lifetime.nil?
65
-
66
- # use the current UTC time if base_time is not given (for testing)
67
- base_time ||= Time.now.utc
68
-
69
- decayed_at = base_time - (artifact_lifetime || -1).seconds
70
- artifact.created_at < decayed_at
71
- end
43
+ self.data_type = TypeChecker.type(data)
72
44
 
73
- #
74
- # Enrich(add) whois record
75
- #
76
- # @param [Mihari::Enrichers::Whois] enricher
77
- #
78
- def enrich_whois(enricher = Enrichers::Whois.new)
79
- return unless can_enrich_whois?
45
+ @tags = []
46
+ @rule_id = ""
47
+ end
80
48
 
81
- self.whois_record = WhoisRecord.build_by_domain(normalize_as_domain(data), enricher: enricher)
82
- end
49
+ #
50
+ # Check uniqueness of artifact
51
+ #
52
+ # @param [Time, nil] base_time Base time to check decaying
53
+ # @param [Integer, nil] artifact_lifetime Artifact lifetime (TTL) in seconds
54
+ #
55
+ # @return [Boolean] true if it is unique. Otherwise false.
56
+ #
57
+ def unique?(base_time: nil, artifact_lifetime: nil)
58
+ artifact = self.class.joins(:alert).where(
59
+ data: data,
60
+ alert: { rule_id: rule_id }
61
+ ).order(created_at: :desc).first
62
+ return true if artifact.nil?
63
+
64
+ # check whether the artifact is decayed or not
65
+ return false if artifact_lifetime.nil?
66
+
67
+ # use the current UTC time if base_time is not given (for testing)
68
+ base_time ||= Time.now.utc
69
+
70
+ decayed_at = base_time - (artifact_lifetime || -1).seconds
71
+ artifact.created_at < decayed_at
72
+ end
83
73
 
84
- #
85
- # Enrich(add) DNS records
86
- #
87
- # @param [Mihari::Enrichers::GooglePublicDNS] enricher
88
- #
89
- def enrich_dns(enricher = Enrichers::GooglePublicDNS.new)
90
- return unless can_enrich_dns?
74
+ #
75
+ # Enrich(add) whois record
76
+ #
77
+ # @param [Mihari::Enrichers::Whois] enricher
78
+ #
79
+ def enrich_whois(enricher = Enrichers::Whois.new)
80
+ return unless can_enrich_whois?
91
81
 
92
- self.dns_records = DnsRecord.build_by_domain(normalize_as_domain(data), enricher: enricher)
93
- end
82
+ self.whois_record = WhoisRecord.build_by_domain(normalize_as_domain(data), enricher: enricher)
83
+ end
94
84
 
95
- #
96
- # Enrich(add) reverse DNS names
97
- #
98
- # @param [Mihari::Enrichers::Shodan] enricher
99
- #
100
- def enrich_reverse_dns(enricher = Enrichers::Shodan.new)
101
- return unless can_enrich_revese_dns?
85
+ #
86
+ # Enrich(add) DNS records
87
+ #
88
+ # @param [Mihari::Enrichers::GooglePublicDNS] enricher
89
+ #
90
+ def enrich_dns(enricher = Enrichers::GooglePublicDNS.new)
91
+ return unless can_enrich_dns?
102
92
 
103
- self.reverse_dns_names = ReverseDnsName.build_by_ip(data, enricher: enricher)
104
- end
93
+ self.dns_records = DnsRecord.build_by_domain(normalize_as_domain(data), enricher: enricher)
94
+ end
105
95
 
106
- #
107
- # Enrich(add) geolocation
108
- #
109
- # @param [Mihari::Enrichers::IPInfo] enricher
110
- #
111
- def enrich_geolocation(enricher = Enrichers::IPInfo.new)
112
- return unless can_enrich_geolocation?
96
+ #
97
+ # Enrich(add) reverse DNS names
98
+ #
99
+ # @param [Mihari::Enrichers::Shodan] enricher
100
+ #
101
+ def enrich_reverse_dns(enricher = Enrichers::Shodan.new)
102
+ return unless can_enrich_revese_dns?
113
103
 
114
- self.geolocation = Geolocation.build_by_ip(data, enricher: enricher)
115
- end
104
+ self.reverse_dns_names = ReverseDnsName.build_by_ip(data, enricher: enricher)
105
+ end
116
106
 
117
- #
118
- # Enrich AS
119
- #
120
- # @param [Mihari::Enrichers::IPInfo] enricher
121
- #
122
- def enrich_autonomous_system(enricher = Enrichers::IPInfo.new)
123
- return unless can_enrich_autonomous_system?
107
+ #
108
+ # Enrich(add) geolocation
109
+ #
110
+ # @param [Mihari::Enrichers::IPInfo] enricher
111
+ #
112
+ def enrich_geolocation(enricher = Enrichers::IPInfo.new)
113
+ return unless can_enrich_geolocation?
124
114
 
125
- self.autonomous_system = AutonomousSystem.build_by_ip(data, enricher: enricher)
126
- end
115
+ self.geolocation = Geolocation.build_by_ip(data, enricher: enricher)
116
+ end
127
117
 
128
- #
129
- # Enrich ports
130
- #
131
- # @param [Mihari::Enrichers::Shodan] enricher
132
- #
133
- def enrich_ports(enricher = Enrichers::Shodan.new)
134
- return unless can_enrich_ports?
118
+ #
119
+ # Enrich AS
120
+ #
121
+ # @param [Mihari::Enrichers::IPInfo] enricher
122
+ #
123
+ def enrich_autonomous_system(enricher = Enrichers::IPInfo.new)
124
+ return unless can_enrich_autonomous_system?
135
125
 
136
- self.ports = Port.build_by_ip(data, enricher: enricher)
137
- end
126
+ self.autonomous_system = AutonomousSystem.build_by_ip(data, enricher: enricher)
127
+ end
138
128
 
139
- #
140
- # Enrich CPEs
141
- #
142
- # @param [Mihari::Enrichers::Shodan] enricher
143
- #
144
- def enrich_cpes(enricher = Enrichers::Shodan.new)
145
- return unless can_enrich_cpes?
129
+ #
130
+ # Enrich ports
131
+ #
132
+ # @param [Mihari::Enrichers::Shodan] enricher
133
+ #
134
+ def enrich_ports(enricher = Enrichers::Shodan.new)
135
+ return unless can_enrich_ports?
146
136
 
147
- self.cpes = CPE.build_by_ip(data, enricher: enricher)
148
- end
137
+ self.ports = Port.build_by_ip(data, enricher: enricher)
138
+ end
149
139
 
150
- #
151
- # Enrich all the enrichable relationships of the artifact
152
- #
153
- def enrich_all
154
- enrich_autonomous_system
155
- enrich_dns
156
- enrich_geolocation
157
- enrich_reverse_dns
158
- enrich_whois
159
- enrich_ports
160
- enrich_cpes
161
- end
140
+ #
141
+ # Enrich CPEs
142
+ #
143
+ # @param [Mihari::Enrichers::Shodan] enricher
144
+ #
145
+ def enrich_cpes(enricher = Enrichers::Shodan.new)
146
+ return unless can_enrich_cpes?
162
147
 
163
- ENRICH_METHODS_BY_ENRICHER = {
164
- Enrichers::Whois => %i[
165
- enrich_whois
166
- ],
167
- Enrichers::IPInfo => %i[
148
+ self.cpes = CPE.build_by_ip(data, enricher: enricher)
149
+ end
150
+
151
+ #
152
+ # Enrich all the enrichable relationships of the artifact
153
+ #
154
+ def enrich_all
168
155
  enrich_autonomous_system
156
+ enrich_dns
169
157
  enrich_geolocation
170
- ],
171
- Enrichers::Shodan => %i[
158
+ enrich_reverse_dns
159
+ enrich_whois
172
160
  enrich_ports
173
161
  enrich_cpes
174
- enrich_reverse_dns
175
- ],
176
- Enrichers::GooglePublicDNS => %i[
177
- enrich_dns
178
- ]
179
- }.freeze
180
-
181
- #
182
- # Enrich by name of enricher
183
- #
184
- # @param [Mihari::Enrichers::Base] enricher
185
- #
186
- def enrich_by_enricher(enricher)
187
- methods = ENRICH_METHODS_BY_ENRICHER[enricher.class] || []
188
- methods.each do |method|
189
- send(method, enricher) if respond_to?(method)
190
162
  end
191
- end
192
163
 
193
- private
164
+ ENRICH_METHODS_BY_ENRICHER = {
165
+ Enrichers::Whois => %i[
166
+ enrich_whois
167
+ ],
168
+ Enrichers::IPInfo => %i[
169
+ enrich_autonomous_system
170
+ enrich_geolocation
171
+ ],
172
+ Enrichers::Shodan => %i[
173
+ enrich_ports
174
+ enrich_cpes
175
+ enrich_reverse_dns
176
+ ],
177
+ Enrichers::GooglePublicDNS => %i[
178
+ enrich_dns
179
+ ]
180
+ }.freeze
181
+
182
+ #
183
+ # Enrich by name of enricher
184
+ #
185
+ # @param [Mihari::Enrichers::Base] enricher
186
+ #
187
+ def enrich_by_enricher(enricher)
188
+ methods = ENRICH_METHODS_BY_ENRICHER[enricher.class] || []
189
+ methods.each do |method|
190
+ send(method, enricher) if respond_to?(method)
191
+ end
192
+ end
194
193
 
195
- def normalize_as_domain(url_or_domain)
196
- return url_or_domain if data_type == "domain"
194
+ private
197
195
 
198
- Addressable::URI.parse(url_or_domain).host
199
- end
196
+ def normalize_as_domain(url_or_domain)
197
+ return url_or_domain if data_type == "domain"
200
198
 
201
- def can_enrich_whois?
202
- %w[domain url].include?(data_type) && whois_record.nil?
203
- end
199
+ Addressable::URI.parse(url_or_domain).host
200
+ end
204
201
 
205
- def can_enrich_dns?
206
- %w[domain url].include?(data_type) && dns_records.empty?
207
- end
202
+ def can_enrich_whois?
203
+ %w[domain url].include?(data_type) && whois_record.nil?
204
+ end
208
205
 
209
- def can_enrich_revese_dns?
210
- data_type == "ip" && reverse_dns_names.empty?
211
- end
206
+ def can_enrich_dns?
207
+ %w[domain url].include?(data_type) && dns_records.empty?
208
+ end
212
209
 
213
- def can_enrich_geolocation?
214
- data_type == "ip" && geolocation.nil?
215
- end
210
+ def can_enrich_revese_dns?
211
+ data_type == "ip" && reverse_dns_names.empty?
212
+ end
216
213
 
217
- def can_enrich_autonomous_system?
218
- data_type == "ip" && autonomous_system.nil?
219
- end
214
+ def can_enrich_geolocation?
215
+ data_type == "ip" && geolocation.nil?
216
+ end
220
217
 
221
- def can_enrich_ports?
222
- data_type == "ip" && ports.empty?
223
- end
218
+ def can_enrich_autonomous_system?
219
+ data_type == "ip" && autonomous_system.nil?
220
+ end
224
221
 
225
- def can_enrich_cpes?
226
- data_type == "ip" && cpes.empty?
222
+ def can_enrich_ports?
223
+ data_type == "ip" && ports.empty?
224
+ end
225
+
226
+ def can_enrich_cpes?
227
+ data_type == "ip" && cpes.empty?
228
+ end
227
229
  end
228
230
  end
229
231
  end
@@ -1,30 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- class AutonomousSystem < ActiveRecord::Base
5
- belongs_to :artifact
4
+ module Models
5
+ class AutonomousSystem < ActiveRecord::Base
6
+ belongs_to :artifact
6
7
 
7
- class << self
8
- include Dry::Monads[:result]
8
+ class << self
9
+ include Dry::Monads[:result]
9
10
 
10
- #
11
- # Build AS
12
- #
13
- # @param [String] ip
14
- # @param [Mihari::Enrichers::IPInfo] enricher
15
- #
16
- # @return [Mihari::AutonomousSystem, nil]
17
- #
18
- def build_by_ip(ip, enricher: Enrichers::IPInfo.new)
19
- result = enricher.query_result(ip).bind do |res|
20
- value = res&.asn
21
- if value.nil?
22
- Success nil
23
- else
24
- Success new(asn: value)
11
+ #
12
+ # Build AS
13
+ #
14
+ # @param [String] ip
15
+ # @param [Mihari::Enrichers::IPInfo] enricher
16
+ #
17
+ # @return [Mihari::AutonomousSystem, nil]
18
+ #
19
+ def build_by_ip(ip, enricher: Enrichers::IPInfo.new)
20
+ result = enricher.query_result(ip).bind do |res|
21
+ value = res&.asn
22
+ if value.nil?
23
+ Success nil
24
+ else
25
+ Success new(asn: value)
26
+ end
25
27
  end
28
+ result.value_or nil
26
29
  end
27
- result.value_or nil
28
30
  end
29
31
  end
30
32
  end
@@ -1,29 +1,31 @@
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
+ class CPE < ActiveRecord::Base
6
+ belongs_to :artifact
6
7
 
7
- class << self
8
- include Dry::Monads[:result]
8
+ class << self
9
+ include Dry::Monads[:result]
9
10
 
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) })
11
+ #
12
+ # Build CPEs
13
+ #
14
+ # @param [String] ip
15
+ # @param [Mihari::Enrichers::Shodan] enricher
16
+ #
17
+ # @return [Array<Mihari::CPE>]
18
+ #
19
+ def build_by_ip(ip, enricher: Enrichers::Shodan.new)
20
+ result = enricher.query_result(ip).bind do |res|
21
+ if res.nil?
22
+ Success []
23
+ else
24
+ Success(res.cpes.map { |cpe| new(cpe: cpe) })
25
+ end
24
26
  end
27
+ result.value_or []
25
28
  end
26
- result.value_or []
27
29
  end
28
30
  end
29
31
  end
@@ -1,31 +1,33 @@
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
+ class DnsRecord < ActiveRecord::Base
6
+ belongs_to :artifact
6
7
 
7
- class << self
8
- include Dry::Monads[:result]
8
+ class << self
9
+ include Dry::Monads[:result]
9
10
 
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
- )
11
+ #
12
+ # Build DNS records
13
+ #
14
+ # @param [String] domain
15
+ # @param [Mihari::Enrichers::Shodan] enricher
16
+ #
17
+ # @return [Array<Mihari::Models::DnsRecord>]
18
+ #
19
+ def build_by_domain(domain, enricher: Enrichers::GooglePublicDNS.new)
20
+ result = enricher.query_result(domain).bind do |responses|
21
+ Success(
22
+ responses.map do |res|
23
+ res.answers.map do |answer|
24
+ new(resource: answer.resource_type, value: answer.data)
25
+ end
26
+ end.flatten
27
+ )
28
+ end
29
+ result.value_or []
27
30
  end
28
- result.value_or []
29
31
  end
30
32
  end
31
33
  end
@@ -3,30 +3,32 @@
3
3
  require "normalize_country"
4
4
 
5
5
  module Mihari
6
- class Geolocation < ActiveRecord::Base
7
- belongs_to :artifact
6
+ module Models
7
+ class Geolocation < ActiveRecord::Base
8
+ belongs_to :artifact
8
9
 
9
- class << self
10
- include Dry::Monads[:result]
10
+ class << self
11
+ include Dry::Monads[:result]
11
12
 
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)
13
+ #
14
+ # Build Geolocation
15
+ #
16
+ # @param [String] ip
17
+ # @param [Mihari::Enrichers::IPinfo] enricher
18
+ #
19
+ # @return [Mihari::Geolocation, nil]
20
+ #
21
+ def build_by_ip(ip, enricher: Enrichers::IPInfo.new)
22
+ result = enricher.query_result(ip).bind do |res|
23
+ value = res&.country_code
24
+ if value.nil?
25
+ Success nil
26
+ else
27
+ Success new(country: NormalizeCountry(value, to: :short), country_code: value)
28
+ end
27
29
  end
30
+ result.value_or nil
28
31
  end
29
- result.value_or nil
30
32
  end
31
33
  end
32
34
  end
@@ -1,29 +1,31 @@
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
+ class Port < ActiveRecord::Base
6
+ belongs_to :artifact
6
7
 
7
- class << self
8
- include Dry::Monads[:result]
8
+ class << self
9
+ include Dry::Monads[:result]
9
10
 
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) })
11
+ #
12
+ # Build ports
13
+ #
14
+ # @param [String] ip
15
+ # @param [Mihari::Enrichers::Shodan] enricher
16
+ #
17
+ # @return [Array<Mihari::Port>]
18
+ #
19
+ def build_by_ip(ip, enricher: Enrichers::Shodan.new)
20
+ result = enricher.query_result(ip).bind do |res|
21
+ if res.nil?
22
+ Success []
23
+ else
24
+ Success(res.ports.map { |port| new(port: port) })
25
+ end
24
26
  end
27
+ result.value_or []
25
28
  end
26
- result.value_or []
27
29
  end
28
30
  end
29
31
  end