mihari 5.5.0 → 5.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/analyzers/binaryedge.md +1 -1
- data/docs/analyzers/censys.md +1 -1
- data/docs/analyzers/circl.md +1 -1
- data/docs/analyzers/crtsh.md +1 -1
- data/docs/analyzers/dnstwister.md +1 -1
- data/docs/analyzers/greynoise.md +1 -1
- data/docs/analyzers/hunterhow.md +1 -1
- data/docs/analyzers/index.md +29 -15
- data/docs/analyzers/onyphe.md +1 -1
- data/docs/analyzers/otx.md +2 -2
- data/docs/analyzers/passivetotal.md +6 -2
- data/docs/analyzers/pulsedive.md +2 -2
- data/docs/analyzers/securitytrails.md +6 -2
- data/docs/analyzers/shodan.md +1 -1
- data/docs/analyzers/urlscan.md +3 -3
- data/docs/analyzers/virustotal.md +6 -2
- data/docs/analyzers/virustotal_intelligence.md +8 -4
- data/docs/analyzers/zoomeye.md +5 -0
- data/docs/emitters/hive.md +1 -1
- data/docs/emitters/slack.md +0 -5
- data/docs/enrichers/google_public_dns.md +1 -1
- data/docs/enrichers/ipinfo.md +2 -2
- data/docs/enrichers/shodan.md +4 -4
- data/docs/enrichers/whois.md +1 -1
- data/docs/rule.md +1 -4
- data/docs/usage.md +5 -2
- data/frontend/package-lock.json +3 -3
- data/frontend/src/components/ErrorMessage.vue +0 -1
- data/frontend/src/components/alert/Alerts.vue +0 -1
- data/frontend/src/components/alert/AlertsWithPagination.vue +0 -1
- data/frontend/src/components/alert/AlertsWrapper.vue +0 -6
- data/frontend/src/components/alert/Form.vue +1 -3
- data/frontend/src/components/artifact/Artifact.vue +0 -17
- data/frontend/src/components/artifact/ArtifactWrapper.vue +0 -2
- data/frontend/src/components/artifact/WhoisRecord.vue +0 -3
- data/frontend/src/components/config/ConfigsWrapper.vue +0 -2
- data/frontend/src/components/rule/EditRule.vue +0 -3
- data/frontend/src/components/rule/EditRuleWrapper.vue +0 -2
- data/frontend/src/components/rule/Form.vue +1 -3
- data/frontend/src/components/rule/NewRule.vue +0 -3
- data/frontend/src/components/rule/Rule.vue +1 -7
- data/frontend/src/components/rule/RuleWrapper.vue +0 -2
- data/frontend/src/components/rule/RulesWrapper.vue +0 -6
- data/frontend/src/swagger.yaml +254 -254
- data/lib/mihari/analyzers/base.rb +4 -41
- data/lib/mihari/analyzers/circl.rb +1 -1
- data/lib/mihari/analyzers/crtsh.rb +1 -1
- data/lib/mihari/analyzers/dnstwister.rb +1 -1
- data/lib/mihari/analyzers/otx.rb +1 -1
- data/lib/mihari/analyzers/passivetotal.rb +10 -1
- data/lib/mihari/analyzers/pulsedive.rb +2 -2
- data/lib/mihari/analyzers/rule.rb +24 -59
- data/lib/mihari/analyzers/securitytrails.rb +10 -1
- data/lib/mihari/analyzers/virustotal.rb +11 -2
- data/lib/mihari/analyzers/virustotal_intelligence.rb +16 -0
- data/lib/mihari/analyzers/zoomeye.rb +2 -2
- data/lib/mihari/base.rb +69 -0
- data/lib/mihari/cli/main.rb +36 -0
- data/lib/mihari/clients/base.rb +2 -2
- data/lib/mihari/clients/binaryedge.rb +3 -5
- data/lib/mihari/clients/censys.rb +3 -3
- data/lib/mihari/clients/circl.rb +5 -4
- data/lib/mihari/clients/crtsh.rb +3 -2
- data/lib/mihari/clients/dnstwister.rb +3 -2
- data/lib/mihari/clients/greynoise.rb +2 -2
- data/lib/mihari/clients/hunterhow.rb +2 -2
- data/lib/mihari/clients/misp.rb +1 -1
- data/lib/mihari/clients/onyphe.rb +2 -2
- data/lib/mihari/clients/otx.rb +4 -3
- data/lib/mihari/clients/passivetotal.rb +5 -4
- data/lib/mihari/clients/publsedive.rb +4 -3
- data/lib/mihari/clients/securitytrails.rb +5 -3
- data/lib/mihari/clients/shodan.rb +2 -2
- data/lib/mihari/clients/the_hive.rb +1 -1
- data/lib/mihari/clients/urlscan.rb +4 -4
- data/lib/mihari/clients/virustotal.rb +2 -2
- data/lib/mihari/clients/zoomeye.rb +2 -2
- data/lib/mihari/commands/alert.rb +6 -33
- data/lib/mihari/commands/rule.rb +7 -12
- data/lib/mihari/commands/search.rb +10 -38
- data/lib/mihari/constants.rb +3 -3
- data/lib/mihari/emitters/base.rb +3 -33
- data/lib/mihari/emitters/database.rb +1 -1
- data/lib/mihari/enrichers/base.rb +2 -33
- data/lib/mihari/enrichers/google_public_dns.rb +9 -0
- data/lib/mihari/schemas/analyzer.rb +24 -24
- data/lib/mihari/schemas/emitter.rb +6 -13
- data/lib/mihari/schemas/enricher.rb +4 -11
- data/lib/mihari/schemas/options.rb +27 -0
- data/lib/mihari/schemas/rule.rb +2 -2
- data/lib/mihari/services/alert_runner.rb +1 -1
- data/lib/mihari/services/rule_runner.rb +1 -11
- data/lib/mihari/types.rb +1 -14
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/public/assets/{index-33165282.css → index-56fc2187.css} +1 -1
- data/lib/mihari/web/public/assets/{index-b5d817a3.js → index-9cc489e6.js} +2 -2
- data/lib/mihari/web/public/index.html +2 -2
- data/lib/mihari.rb +67 -37
- data/mihari.gemspec +1 -0
- data/mkdocs.yml +0 -3
- metadata +20 -4
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Mihari
|
4
4
|
module Analyzers
|
5
|
-
class Base
|
5
|
+
class Base < Mihari::Base
|
6
6
|
include Dry::Monads[:result, :try]
|
7
7
|
|
8
8
|
include Mixins::Configurable
|
@@ -11,37 +11,14 @@ module Mihari
|
|
11
11
|
# @return [String]
|
12
12
|
attr_reader :query
|
13
13
|
|
14
|
-
# @return [Hash]
|
15
|
-
attr_reader :options
|
16
|
-
|
17
14
|
#
|
18
15
|
# @param [String] query
|
19
16
|
# @param [Hash, nil] options
|
20
17
|
#
|
21
18
|
def initialize(query, options: nil)
|
22
|
-
|
23
|
-
@options = options || {}
|
24
|
-
end
|
25
|
-
|
26
|
-
#
|
27
|
-
# @return [Integer]
|
28
|
-
#
|
29
|
-
def retry_interval
|
30
|
-
options[:retry_interval] || Mihari.config.retry_interval
|
31
|
-
end
|
32
|
-
|
33
|
-
#
|
34
|
-
# @return [Boolean]
|
35
|
-
#
|
36
|
-
def retry_exponential_backoff
|
37
|
-
options[:retry_exponential_backoff] || Mihari.config.retry_exponential_backoff
|
38
|
-
end
|
19
|
+
super(options: options)
|
39
20
|
|
40
|
-
|
41
|
-
# @return [Integer]
|
42
|
-
#
|
43
|
-
def retry_times
|
44
|
-
options[:retry_times] || Mihari.config.retry_times
|
21
|
+
@query = query
|
45
22
|
end
|
46
23
|
|
47
24
|
#
|
@@ -68,13 +45,6 @@ module Mihari
|
|
68
45
|
Mihari.config.ignore_error
|
69
46
|
end
|
70
47
|
|
71
|
-
#
|
72
|
-
# @return [Integer, nil]
|
73
|
-
#
|
74
|
-
def timeout
|
75
|
-
options[:timeout]
|
76
|
-
end
|
77
|
-
|
78
48
|
# @return [Array<String>, Array<Mihari::Artifact>]
|
79
49
|
def artifacts
|
80
50
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
@@ -93,7 +63,7 @@ module Mihari
|
|
93
63
|
# No need to set data_type manually
|
94
64
|
# It is set automatically in #initialize
|
95
65
|
artifact = artifact.is_a?(Artifact) ? artifact : Artifact.new(data: artifact)
|
96
|
-
artifact.source =
|
66
|
+
artifact.source = self.class.class_key
|
97
67
|
artifact
|
98
68
|
end.select(&:valid?).uniq(&:data)
|
99
69
|
end
|
@@ -106,13 +76,6 @@ module Mihari
|
|
106
76
|
Try[StandardError] { normalized_artifacts }.to_result
|
107
77
|
end
|
108
78
|
|
109
|
-
# @return [String]
|
110
|
-
def class_name
|
111
|
-
self.class.to_s.split("::").last
|
112
|
-
end
|
113
|
-
|
114
|
-
alias_method :source, :class_name
|
115
|
-
|
116
79
|
class << self
|
117
80
|
#
|
118
81
|
# Initialize an analyzer by query params
|
data/lib/mihari/analyzers/otx.rb
CHANGED
@@ -50,10 +50,19 @@ module Mihari
|
|
50
50
|
%w[passivetotal_username passivetotal_api_key]
|
51
51
|
end
|
52
52
|
|
53
|
+
class << self
|
54
|
+
#
|
55
|
+
# @return [Array<String>, nil]
|
56
|
+
#
|
57
|
+
def key_aliases
|
58
|
+
["pt"]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
53
62
|
private
|
54
63
|
|
55
64
|
def client
|
56
|
-
@client ||= Clients::PassiveTotal.new(username: username, api_key: api_key)
|
65
|
+
@client ||= Clients::PassiveTotal.new(username: username, api_key: api_key, timeout: timeout)
|
57
66
|
end
|
58
67
|
|
59
68
|
#
|
@@ -35,7 +35,7 @@ module Mihari
|
|
35
35
|
nil
|
36
36
|
else
|
37
37
|
data = property["value"]
|
38
|
-
Artifact.new(data: data,
|
38
|
+
Artifact.new(data: data, metadata: property)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -47,7 +47,7 @@ module Mihari
|
|
47
47
|
private
|
48
48
|
|
49
49
|
def client
|
50
|
-
@client ||= Clients::PulseDive.new(api_key: api_key)
|
50
|
+
@client ||= Clients::PulseDive.new(api_key: api_key, timeout: timeout)
|
51
51
|
end
|
52
52
|
|
53
53
|
#
|
@@ -2,46 +2,6 @@
|
|
2
2
|
|
3
3
|
module Mihari
|
4
4
|
module Analyzers
|
5
|
-
ANALYZER_TO_CLASS = {
|
6
|
-
"binaryedge" => BinaryEdge,
|
7
|
-
"censys" => Censys,
|
8
|
-
"circl" => CIRCL,
|
9
|
-
"crtsh" => Crtsh,
|
10
|
-
"dnstwister" => DNSTwister,
|
11
|
-
"feed" => Feed,
|
12
|
-
"greynoise" => GreyNoise,
|
13
|
-
"hunterhow" => HunterHow,
|
14
|
-
"onyphe" => Onyphe,
|
15
|
-
"otx" => OTX,
|
16
|
-
"passivetotal" => PassiveTotal,
|
17
|
-
"pt" => PassiveTotal,
|
18
|
-
"pulsedive" => Pulsedive,
|
19
|
-
"securitytrails" => SecurityTrails,
|
20
|
-
"shodan" => Shodan,
|
21
|
-
"st" => SecurityTrails,
|
22
|
-
"urlscan" => Urlscan,
|
23
|
-
"virustotal_intelligence" => VirusTotalIntelligence,
|
24
|
-
"virustotal" => VirusTotal,
|
25
|
-
"vt_intel" => VirusTotalIntelligence,
|
26
|
-
"vt" => VirusTotal,
|
27
|
-
"zoomeye" => ZoomEye
|
28
|
-
}.freeze
|
29
|
-
|
30
|
-
EMITTER_TO_CLASS = {
|
31
|
-
"database" => Emitters::Database,
|
32
|
-
"misp" => Emitters::MISP,
|
33
|
-
"slack" => Emitters::Slack,
|
34
|
-
"the_hive" => Emitters::TheHive,
|
35
|
-
"webhook" => Emitters::Webhook
|
36
|
-
}.freeze
|
37
|
-
|
38
|
-
ENRICHER_TO_CLASS = {
|
39
|
-
"whois" => Enrichers::Whois,
|
40
|
-
"ipinfo" => Enrichers::IPInfo,
|
41
|
-
"shodan" => Enrichers::Shodan,
|
42
|
-
"google_public_dns" => Enrichers::GooglePublicDNS
|
43
|
-
}.freeze
|
44
|
-
|
45
5
|
class Rule
|
46
6
|
include Mixins::FalsePositive
|
47
7
|
|
@@ -126,8 +86,14 @@ module Mihari
|
|
126
86
|
def bulk_emit
|
127
87
|
return [] if enriched_artifacts.empty?
|
128
88
|
|
129
|
-
|
130
|
-
|
89
|
+
# NOTE: separate parallel execution and logging
|
90
|
+
# because the logger does not work along with Parallel
|
91
|
+
results = Parallel.map(valid_emitters) do |emitter|
|
92
|
+
emitter.result
|
93
|
+
end
|
94
|
+
|
95
|
+
results.zip(valid_emitters).map do |result_and_emitter|
|
96
|
+
result, emitter = result_and_emitter
|
131
97
|
|
132
98
|
Mihari.logger.info "Emission by #{emitter.class} is failed: #{result.failure}" if result.failure?
|
133
99
|
Mihari.logger.info "Emission by #{emitter.class} is succeeded" if result.success?
|
@@ -164,15 +130,14 @@ module Mihari
|
|
164
130
|
#
|
165
131
|
# Get analyzer class
|
166
132
|
#
|
167
|
-
# @param [String]
|
133
|
+
# @param [String] key
|
168
134
|
#
|
169
135
|
# @return [Class<Mihari::Analyzers::Base>] analyzer class
|
170
136
|
#
|
171
|
-
def get_analyzer_class(
|
172
|
-
|
173
|
-
return analyzer if analyzer
|
137
|
+
def get_analyzer_class(key)
|
138
|
+
raise ArgumentError, "#{key} is not supported" unless Mihari.analyzer_to_class.key?(key)
|
174
139
|
|
175
|
-
|
140
|
+
Mihari.analyzer_to_class[key]
|
176
141
|
end
|
177
142
|
|
178
143
|
#
|
@@ -189,15 +154,14 @@ module Mihari
|
|
189
154
|
#
|
190
155
|
# Get emitter class
|
191
156
|
#
|
192
|
-
# @param [String]
|
157
|
+
# @param [String] key
|
193
158
|
#
|
194
159
|
# @return [Class<Mihari::Emitters::Base>] emitter class
|
195
160
|
#
|
196
|
-
def get_emitter_class(
|
197
|
-
|
198
|
-
return emitter if emitter
|
161
|
+
def get_emitter_class(key)
|
162
|
+
raise ArgumentError, "#{key} is not supported" unless Mihari.emitter_to_class.key?(key)
|
199
163
|
|
200
|
-
|
164
|
+
Mihari.emitter_to_class[key]
|
201
165
|
end
|
202
166
|
|
203
167
|
#
|
@@ -219,21 +183,20 @@ module Mihari
|
|
219
183
|
# @return [Array<Mihari::Emitters::Base>]
|
220
184
|
#
|
221
185
|
def valid_emitters
|
222
|
-
emitters.select(&:valid?)
|
186
|
+
@valid_emitters ||= emitters.select(&:valid?)
|
223
187
|
end
|
224
188
|
|
225
189
|
#
|
226
190
|
# Get enricher class
|
227
191
|
#
|
228
|
-
# @param [String]
|
192
|
+
# @param [String] key
|
229
193
|
#
|
230
194
|
# @return [Class<Mihari::Enrichers::Base>] enricher class
|
231
195
|
#
|
232
|
-
def get_enricher_class(
|
233
|
-
|
234
|
-
return enricher if enricher
|
196
|
+
def get_enricher_class(key)
|
197
|
+
raise ArgumentError, "#{key} is not supported" unless Mihari.enricher_to_class.key?(key)
|
235
198
|
|
236
|
-
|
199
|
+
Mihari.enricher_to_class[key]
|
237
200
|
end
|
238
201
|
|
239
202
|
#
|
@@ -258,7 +221,9 @@ module Mihari
|
|
258
221
|
analyzers.map do |analyzer|
|
259
222
|
next if analyzer.configured?
|
260
223
|
|
261
|
-
|
224
|
+
joined = analyzer.configuration_keys.join(", ")
|
225
|
+
be = (analyzer.configuration_keys.length > 1) ? "are" : "is"
|
226
|
+
message = "#{analyzer.class.class_key} is not configured correctly. #{joined} #{be} missing."
|
262
227
|
raise ConfigurationError, message
|
263
228
|
end
|
264
229
|
end
|
@@ -44,10 +44,19 @@ module Mihari
|
|
44
44
|
%w[securitytrails_api_key]
|
45
45
|
end
|
46
46
|
|
47
|
+
class << self
|
48
|
+
#
|
49
|
+
# @return [Array<String>, nil]
|
50
|
+
#
|
51
|
+
def key_aliases
|
52
|
+
["st"]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
47
56
|
private
|
48
57
|
|
49
58
|
def client
|
50
|
-
@client ||= Clients::SecurityTrails.new(api_key: api_key)
|
59
|
+
@client ||= Clients::SecurityTrails.new(api_key: api_key, timeout: timeout)
|
51
60
|
end
|
52
61
|
|
53
62
|
#
|
@@ -39,6 +39,15 @@ module Mihari
|
|
39
39
|
%w[virustotal_api_key]
|
40
40
|
end
|
41
41
|
|
42
|
+
class << self
|
43
|
+
#
|
44
|
+
# @return [Array<String>, nil]
|
45
|
+
#
|
46
|
+
def key_aliases
|
47
|
+
["vt"]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
42
51
|
private
|
43
52
|
|
44
53
|
def client
|
@@ -65,7 +74,7 @@ module Mihari
|
|
65
74
|
data = res["data"] || []
|
66
75
|
data.filter_map do |item|
|
67
76
|
data = item.dig("attributes", "ip_address")
|
68
|
-
data.nil? ? nil : Artifact.new(data: data,
|
77
|
+
data.nil? ? nil : Artifact.new(data: data, metadata: item)
|
69
78
|
end
|
70
79
|
end
|
71
80
|
|
@@ -80,7 +89,7 @@ module Mihari
|
|
80
89
|
data = res["data"] || []
|
81
90
|
data.filter_map do |item|
|
82
91
|
data = item.dig("attributes", "host_name")
|
83
|
-
Artifact.new(data: data,
|
92
|
+
Artifact.new(data: data, metadata: item)
|
84
93
|
end.uniq
|
85
94
|
end
|
86
95
|
end
|
@@ -25,6 +25,22 @@ module Mihari
|
|
25
25
|
%w[virustotal_api_key]
|
26
26
|
end
|
27
27
|
|
28
|
+
class << self
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
#
|
32
|
+
def class_key
|
33
|
+
"virustotal_intelligence"
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# @return [Array<String>, nil]
|
38
|
+
#
|
39
|
+
def class_key_aliases
|
40
|
+
["vt_intel"]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
28
44
|
private
|
29
45
|
|
30
46
|
#
|
@@ -73,9 +73,9 @@ module Mihari
|
|
73
73
|
data = match["ip"]
|
74
74
|
|
75
75
|
if data.is_a?(Array)
|
76
|
-
data.map { |d| Artifact.new(data: d,
|
76
|
+
data.map { |d| Artifact.new(data: d, metadata: match) }
|
77
77
|
else
|
78
|
-
Artifact.new(data: data,
|
78
|
+
Artifact.new(data: data, metadata: match)
|
79
79
|
end
|
80
80
|
end.flatten
|
81
81
|
end
|
data/lib/mihari/base.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
#
|
5
|
+
# Base class for Analyzer, Emitter and Enricher
|
6
|
+
#
|
7
|
+
class Base
|
8
|
+
# @return [Hash]
|
9
|
+
attr_reader :options
|
10
|
+
|
11
|
+
#
|
12
|
+
# @param [Hash, nil] options
|
13
|
+
#
|
14
|
+
def initialize(*_args, options: nil, **_kwargs)
|
15
|
+
@options = options || {}
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# @return [Integer]
|
20
|
+
#
|
21
|
+
def retry_interval
|
22
|
+
options[:retry_interval] || Mihari.config.retry_interval
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
#
|
28
|
+
def retry_exponential_backoff
|
29
|
+
options[:retry_exponential_backoff] || Mihari.config.retry_exponential_backoff
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# @return [Integer]
|
34
|
+
#
|
35
|
+
def retry_times
|
36
|
+
options[:retry_times] || Mihari.config.retry_times
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# @return [Integer, nil]
|
41
|
+
#
|
42
|
+
def timeout
|
43
|
+
options[:timeout]
|
44
|
+
end
|
45
|
+
|
46
|
+
class << self
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
#
|
50
|
+
def class_key
|
51
|
+
to_s.split("::").last
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# @return [Array<String>, nil]
|
56
|
+
#
|
57
|
+
def class_key_aliases
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# @return [Array<String>]
|
63
|
+
#
|
64
|
+
def class_keys
|
65
|
+
([class_key] + [class_key_aliases]).flatten.compact
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/mihari/cli/main.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "thor"
|
4
|
+
require "thor/hollaback"
|
4
5
|
|
5
6
|
# Commands
|
6
7
|
require "mihari/commands/alert"
|
@@ -19,10 +20,45 @@ require "mihari/cli/rule"
|
|
19
20
|
module Mihari
|
20
21
|
module CLI
|
21
22
|
class Main < Base
|
23
|
+
class_option :debug, desc: "Sets up debug mode", aliases: ["-d"], type: :boolean
|
24
|
+
class_around :safe_execute
|
25
|
+
|
22
26
|
include Mihari::Commands::Search
|
23
27
|
include Mihari::Commands::Version
|
24
28
|
include Mihari::Commands::Web
|
25
29
|
|
30
|
+
no_commands do
|
31
|
+
def unwrap_error(err)
|
32
|
+
return err unless err.is_a?(Dry::Monads::UnwrapError)
|
33
|
+
|
34
|
+
# NOTE: UnwrapError's receiver can be either of:
|
35
|
+
# - Dry::Monads::Try::Error
|
36
|
+
# - Dry::Monads::Result::Failure
|
37
|
+
receiver = err.receiver
|
38
|
+
return receiver.exception if receiver.is_a?(Dry::Monads::Try::Error)
|
39
|
+
|
40
|
+
receiver.failure
|
41
|
+
end
|
42
|
+
|
43
|
+
def safe_execute
|
44
|
+
yield
|
45
|
+
rescue StandardError => e
|
46
|
+
err = unwrap_error(e)
|
47
|
+
|
48
|
+
raise err if options["debug"]
|
49
|
+
|
50
|
+
case err
|
51
|
+
when ValidationError
|
52
|
+
warn JSON.pretty_generate(err.errors.to_h)
|
53
|
+
when StandardError
|
54
|
+
Sentry.capture_exception(err) if Sentry.initialized?
|
55
|
+
warn err
|
56
|
+
end
|
57
|
+
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
26
62
|
desc "db", "Sub commands for DB"
|
27
63
|
subcommand "db", Database
|
28
64
|
|
data/lib/mihari/clients/base.rb
CHANGED
@@ -18,10 +18,10 @@ module Mihari
|
|
18
18
|
#
|
19
19
|
# @param [String] base_url
|
20
20
|
# @param [Hash] headers
|
21
|
-
# @param [Integer]
|
21
|
+
# @param [Integer] pagination_interval
|
22
22
|
# @param [Integer, nil] timeout
|
23
23
|
#
|
24
|
-
def initialize(base_url, headers: {}, pagination_interval:
|
24
|
+
def initialize(base_url, headers: {}, pagination_interval: Mihari.config.pagination_interval, timeout: nil)
|
25
25
|
@base_url = base_url
|
26
26
|
@headers = headers || {}
|
27
27
|
@pagination_interval = pagination_interval
|
@@ -7,21 +7,19 @@ module Mihari
|
|
7
7
|
# @param [String] base_url
|
8
8
|
# @param [String, nil] api_key
|
9
9
|
# @param [Hash] headers
|
10
|
-
# @param [Integer] pagnation_interval
|
11
10
|
# @param [Integer, nil] timeout
|
11
|
+
# @param [Integer] pagination_interval
|
12
12
|
#
|
13
13
|
def initialize(
|
14
14
|
base_url = "https://api.binaryedge.io/v2",
|
15
15
|
api_key:,
|
16
16
|
headers: {},
|
17
|
-
pagination_interval:
|
17
|
+
pagination_interval: Mihari.config.pagination_interval,
|
18
18
|
timeout: nil
|
19
19
|
)
|
20
|
-
raise(ArgumentError, "'api_key' argument is required") unless api_key
|
21
|
-
|
22
20
|
headers["x-key"] = api_key
|
23
21
|
|
24
|
-
super(base_url, headers: headers,
|
22
|
+
super(base_url, headers: headers, timeout: timeout, pagination_interval: pagination_interval)
|
25
23
|
end
|
26
24
|
|
27
25
|
#
|
@@ -18,11 +18,11 @@ module Mihari
|
|
18
18
|
id:,
|
19
19
|
secret:,
|
20
20
|
headers: {},
|
21
|
-
pagination_interval:
|
21
|
+
pagination_interval: Mihari.config.pagination_interval,
|
22
22
|
timeout: nil
|
23
23
|
)
|
24
|
-
raise(ArgumentError, "
|
25
|
-
raise(ArgumentError, "
|
24
|
+
raise(ArgumentError, "id is required") if id.nil?
|
25
|
+
raise(ArgumentError, "secret is required") if secret.nil?
|
26
26
|
|
27
27
|
headers["authorization"] = "Basic #{Base64.strict_encode64("#{id}:#{secret}")}"
|
28
28
|
|
data/lib/mihari/clients/circl.rb
CHANGED
@@ -10,14 +10,15 @@ module Mihari
|
|
10
10
|
# @param [String, nil] username
|
11
11
|
# @param [String, nil] password
|
12
12
|
# @param [Hash] headers
|
13
|
+
# @param [Integer, nil] timeout
|
13
14
|
#
|
14
|
-
def initialize(base_url = "https://www.circl.lu", username:, password:, headers: {})
|
15
|
-
raise(ArgumentError, "
|
16
|
-
raise(ArgumentError, "
|
15
|
+
def initialize(base_url = "https://www.circl.lu", username:, password:, headers: {}, timeout: nil)
|
16
|
+
raise(ArgumentError, "username is required") if username.nil?
|
17
|
+
raise(ArgumentError, "password is required") if password.nil?
|
17
18
|
|
18
19
|
headers["authorization"] = "Basic #{Base64.strict_encode64("#{username}:#{password}")}"
|
19
20
|
|
20
|
-
super(base_url, headers: headers)
|
21
|
+
super(base_url, headers: headers, timeout: timeout)
|
21
22
|
end
|
22
23
|
|
23
24
|
#
|
data/lib/mihari/clients/crtsh.rb
CHANGED
@@ -6,9 +6,10 @@ module Mihari
|
|
6
6
|
#
|
7
7
|
# @param [String] base_url
|
8
8
|
# @param [Hash] headers
|
9
|
+
# @param [Integer, nil] timeout
|
9
10
|
#
|
10
|
-
def initialize(base_url = "https://crt.sh", headers: {})
|
11
|
-
super(base_url, headers: headers)
|
11
|
+
def initialize(base_url = "https://crt.sh", headers: {}, timeout: nil)
|
12
|
+
super(base_url, headers: headers, timeout: timeout)
|
12
13
|
end
|
13
14
|
|
14
15
|
#
|
@@ -6,9 +6,10 @@ module Mihari
|
|
6
6
|
#
|
7
7
|
# @param [String] base_url
|
8
8
|
# @param [Hash] headers
|
9
|
+
# @param [Integer, nil] timeout
|
9
10
|
#
|
10
|
-
def initialize(base_url = "https://dnstwister.report", headers: {})
|
11
|
-
super(base_url, headers: headers)
|
11
|
+
def initialize(base_url = "https://dnstwister.report", headers: {}, timeout: nil)
|
12
|
+
super(base_url, headers: headers, timeout: timeout)
|
12
13
|
end
|
13
14
|
|
14
15
|
#
|
@@ -16,10 +16,10 @@ module Mihari
|
|
16
16
|
base_url = "https://api.greynoise.io",
|
17
17
|
api_key:,
|
18
18
|
headers: {},
|
19
|
-
pagination_interval:
|
19
|
+
pagination_interval: Mihari.config.pagination_interval,
|
20
20
|
timeout: nil
|
21
21
|
)
|
22
|
-
raise(ArgumentError, "
|
22
|
+
raise(ArgumentError, "api_key is required") unless api_key
|
23
23
|
|
24
24
|
headers["key"] = api_key
|
25
25
|
super(base_url, headers: headers, pagination_interval: pagination_interval, timeout: timeout)
|
@@ -21,10 +21,10 @@ module Mihari
|
|
21
21
|
base_url = "https://api.hunter.how/",
|
22
22
|
api_key:,
|
23
23
|
headers: {},
|
24
|
-
pagination_interval:
|
24
|
+
pagination_interval: Mihari.config.pagination_interval,
|
25
25
|
timeout: nil
|
26
26
|
)
|
27
|
-
raise(ArgumentError, "
|
27
|
+
raise(ArgumentError, "api_key is required") unless api_key
|
28
28
|
|
29
29
|
super(base_url, headers: headers, pagination_interval: pagination_interval, timeout: timeout)
|
30
30
|
|
data/lib/mihari/clients/misp.rb
CHANGED
@@ -10,7 +10,7 @@ module Mihari
|
|
10
10
|
# @param [Integer, nil] timeout
|
11
11
|
#
|
12
12
|
def initialize(base_url, api_key:, headers: {}, timeout: nil)
|
13
|
-
raise(ArgumentError, "
|
13
|
+
raise(ArgumentError, "api_key is required") unless api_key
|
14
14
|
|
15
15
|
headers["authorization"] = api_key
|
16
16
|
headers["accept"] = "application/json"
|
@@ -19,10 +19,10 @@ module Mihari
|
|
19
19
|
base_url = "https://www.onyphe.io",
|
20
20
|
api_key:,
|
21
21
|
headers: {},
|
22
|
-
pagination_interval:
|
22
|
+
pagination_interval: Mihari.config.pagination_interval,
|
23
23
|
timeout: nil
|
24
24
|
)
|
25
|
-
raise(ArgumentError, "
|
25
|
+
raise(ArgumentError, "api_key is required") if api_key.nil?
|
26
26
|
|
27
27
|
super(base_url, headers: headers, pagination_interval: pagination_interval, timeout: timeout)
|
28
28
|
|