mihari 5.2.3 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/README.md +0 -10
  4. data/Rakefile +7 -1
  5. data/build_frontend.sh +2 -10
  6. data/frontend/.eslintrc.cjs +22 -0
  7. data/frontend/.gitignore +31 -0
  8. data/frontend/.prettierrc.json +8 -0
  9. data/frontend/README.md +3 -0
  10. data/frontend/env.d.ts +5 -0
  11. data/frontend/index.html +21 -0
  12. data/frontend/package-lock.json +8650 -0
  13. data/frontend/package.json +64 -0
  14. data/frontend/public/favicon.ico +0 -0
  15. data/frontend/scripts/swagger_doc_to_yaml.rb +23 -0
  16. data/frontend/src/App.vue +27 -0
  17. data/frontend/src/api-helper.ts +111 -0
  18. data/frontend/src/api.ts +105 -0
  19. data/frontend/src/components/ErrorMessage.vue +32 -0
  20. data/frontend/src/components/Loading.vue +15 -0
  21. data/frontend/src/components/Navbar.vue +42 -0
  22. data/frontend/src/components/Pagination.vue +119 -0
  23. data/frontend/src/components/alert/Alert.vue +87 -0
  24. data/frontend/src/components/alert/Alerts.vue +64 -0
  25. data/frontend/src/components/alert/AlertsWithPagination.vue +91 -0
  26. data/frontend/src/components/alert/AlertsWrapper.vue +134 -0
  27. data/frontend/src/components/alert/Form.vue +184 -0
  28. data/frontend/src/components/artifact/AS.vue +29 -0
  29. data/frontend/src/components/artifact/Artifact.vue +304 -0
  30. data/frontend/src/components/artifact/ArtifactTag.vue +64 -0
  31. data/frontend/src/components/artifact/ArtifactTags.vue +29 -0
  32. data/frontend/src/components/artifact/ArtifactWrapper.vue +59 -0
  33. data/frontend/src/components/artifact/CPEs.vue +23 -0
  34. data/frontend/src/components/artifact/DnsRecords.vue +38 -0
  35. data/frontend/src/components/artifact/Ports.vue +23 -0
  36. data/frontend/src/components/artifact/ReverseDnsNames.vue +31 -0
  37. data/frontend/src/components/artifact/Tags.vue +29 -0
  38. data/frontend/src/components/artifact/WhoisRecord.vue +47 -0
  39. data/frontend/src/components/config/Configs.vue +65 -0
  40. data/frontend/src/components/config/ConfigsWrapper.vue +34 -0
  41. data/frontend/src/components/link/Link.vue +32 -0
  42. data/frontend/src/components/link/Links.vue +42 -0
  43. data/frontend/src/components/rule/EditRule.vue +74 -0
  44. data/frontend/src/components/rule/EditRuleWrapper.vue +50 -0
  45. data/frontend/src/components/rule/Form.vue +160 -0
  46. data/frontend/src/components/rule/InputForm.vue +86 -0
  47. data/frontend/src/components/rule/NewRule.vue +60 -0
  48. data/frontend/src/components/rule/Rule.vue +106 -0
  49. data/frontend/src/components/rule/RuleWrapper.vue +55 -0
  50. data/frontend/src/components/rule/Rules.vue +84 -0
  51. data/frontend/src/components/rule/RulesWrapper.vue +127 -0
  52. data/frontend/src/components/rule/YAML.vue +44 -0
  53. data/frontend/src/components/tag/Tag.vue +65 -0
  54. data/frontend/src/components/tag/Tags.vue +37 -0
  55. data/frontend/src/countries.ts +350 -0
  56. data/frontend/src/index.ts +20 -0
  57. data/frontend/src/links/anyrun.ts +19 -0
  58. data/frontend/src/links/base.ts +14 -0
  59. data/frontend/src/links/censys.ts +20 -0
  60. data/frontend/src/links/crtsh.ts +20 -0
  61. data/frontend/src/links/dnslytics.ts +38 -0
  62. data/frontend/src/links/greynoise.ts +20 -0
  63. data/frontend/src/links/index.ts +40 -0
  64. data/frontend/src/links/intezer.ts +20 -0
  65. data/frontend/src/links/otx.ts +33 -0
  66. data/frontend/src/links/securitytrails.ts +38 -0
  67. data/frontend/src/links/shodan.ts +20 -0
  68. data/frontend/src/links/urlscan.ts +50 -0
  69. data/frontend/src/links/virustotal.ts +72 -0
  70. data/frontend/src/main.ts +11 -0
  71. data/frontend/src/router/index.ts +57 -0
  72. data/frontend/src/rule.ts +14 -0
  73. data/frontend/src/shims-vue.d.ts +6 -0
  74. data/frontend/src/swagger.yaml +737 -0
  75. data/frontend/src/types.ts +188 -0
  76. data/frontend/src/utils.ts +54 -0
  77. data/frontend/src/views/Alerts.vue +20 -0
  78. data/frontend/src/views/Artifact.vue +44 -0
  79. data/frontend/src/views/Configs.vue +20 -0
  80. data/frontend/src/views/EditRule.vue +44 -0
  81. data/frontend/src/views/NewRule.vue +26 -0
  82. data/frontend/src/views/Rule.vue +44 -0
  83. data/frontend/src/views/Rules.vue +20 -0
  84. data/frontend/tests/utils.spec.ts +9 -0
  85. data/frontend/tsconfig.app.json +21 -0
  86. data/frontend/tsconfig.json +14 -0
  87. data/frontend/tsconfig.node.json +13 -0
  88. data/frontend/tsconfig.vitest.json +12 -0
  89. data/frontend/vite.config.ts +24 -0
  90. data/frontend/vitest.config.ts +21 -0
  91. data/lefthook.yml +12 -0
  92. data/lib/mihari/analyzers/base.rb +63 -12
  93. data/lib/mihari/analyzers/binaryedge.rb +10 -15
  94. data/lib/mihari/analyzers/censys.rb +12 -15
  95. data/lib/mihari/analyzers/circl.rb +10 -10
  96. data/lib/mihari/analyzers/crtsh.rb +10 -6
  97. data/lib/mihari/analyzers/dnstwister.rb +6 -8
  98. data/lib/mihari/analyzers/feed.rb +21 -10
  99. data/lib/mihari/analyzers/greynoise.rb +10 -20
  100. data/lib/mihari/analyzers/onyphe.rb +9 -14
  101. data/lib/mihari/analyzers/otx.rb +8 -9
  102. data/lib/mihari/analyzers/passivetotal.rb +10 -10
  103. data/lib/mihari/analyzers/pulsedive.rb +21 -31
  104. data/lib/mihari/analyzers/rule.rb +8 -29
  105. data/lib/mihari/analyzers/securitytrails.rb +8 -6
  106. data/lib/mihari/analyzers/shodan.rb +8 -13
  107. data/lib/mihari/analyzers/urlscan.rb +15 -20
  108. data/lib/mihari/analyzers/virustotal.rb +16 -26
  109. data/lib/mihari/analyzers/virustotal_intelligence.rb +11 -17
  110. data/lib/mihari/analyzers/zoomeye.rb +12 -17
  111. data/lib/mihari/commands/search.rb +16 -7
  112. data/lib/mihari/config.rb +133 -0
  113. data/lib/mihari/constants.rb +3 -0
  114. data/lib/mihari/emitters/slack.rb +13 -3
  115. data/lib/mihari/entities/rule.rb +1 -1
  116. data/lib/mihari/entities/tag.rb +1 -1
  117. data/lib/mihari/errors.rb +1 -1
  118. data/lib/mihari/http.rb +2 -3
  119. data/lib/mihari/schemas/analyzer.rb +4 -7
  120. data/lib/mihari/schemas/rule.rb +1 -1
  121. data/lib/mihari/structs/config.rb +39 -16
  122. data/lib/mihari/structs/rule.rb +1 -1
  123. data/lib/mihari/type_checker.rb +6 -6
  124. data/lib/mihari/version.rb +1 -1
  125. data/lib/mihari/web/endpoints/configs.rb +5 -1
  126. data/lib/mihari/web/public/assets/{index-eed1bcd8.css → index-2ba8f0a6.css} +1 -1
  127. data/lib/mihari/web/public/assets/index-71285b15.js +50 -0
  128. data/lib/mihari/web/public/index.html +2 -2
  129. data/lib/mihari/web/public/redoc-static.html +388 -2193
  130. data/lib/mihari.rb +9 -59
  131. data/mihari.gemspec +13 -13
  132. metadata +112 -69
  133. data/.gitmodules +0 -0
  134. data/.overcommit.yml +0 -12
  135. data/lib/mihari/web/public/assets/index-cbe1734c.js +0 -50
@@ -3,11 +3,45 @@
3
3
  module Mihari
4
4
  module Analyzers
5
5
  class Base
6
- extend Dry::Initializer
7
-
8
6
  include Mixins::Configurable
9
7
  include Mixins::Retriable
10
8
 
9
+ # @return [String]
10
+ attr_reader :query
11
+
12
+ # @return [Hash]
13
+ attr_reader :options
14
+
15
+ #
16
+ # @param [String] query
17
+ # @param [Hash, nil] options
18
+ #
19
+ def initialize(query, options: nil)
20
+ @query = query
21
+ @options = options || {}
22
+ end
23
+
24
+ #
25
+ # @return [Integer, nil]
26
+ #
27
+ def interval
28
+ @interval = options[:interval]
29
+ end
30
+
31
+ #
32
+ # @return [Integer]
33
+ #
34
+ def retry_interval
35
+ @retry_interval ||= options[:retry_interval] || DEFAULT_RETRY_INTERVAL
36
+ end
37
+
38
+ #
39
+ # @return [Integer]
40
+ #
41
+ def retry_times
42
+ @retry_times ||= options[:retry_times] || DEFAULT_RETRY_TIMES
43
+ end
44
+
11
45
  # @return [Array<String>, Array<Mihari::Artifact>]
12
46
  def artifacts
13
47
  raise NotImplementedError, "You must implement #{self.class}##{__method__}"
@@ -21,31 +55,48 @@ module Mihari
21
55
  # @return [Array<Mihari::Artifact>]
22
56
  #
23
57
  def normalized_artifacts
24
- retry_on_error do
58
+ retry_on_error(times: retry_times, interval: retry_interval) do
25
59
  @normalized_artifacts ||= artifacts.compact.sort.map do |artifact|
26
60
  # No need to set data_type manually
27
61
  # It is set automatically in #initialize
28
62
  artifact = artifact.is_a?(Artifact) ? artifact : Artifact.new(data: artifact)
29
- artifact
30
- end.select(&:valid?).uniq(&:data).map do |artifact|
31
- # set source
32
63
  artifact.source = source
33
64
  artifact
34
- end
65
+ end.select(&:valid?).uniq(&:data)
35
66
  end
36
67
  end
37
68
 
38
- # @return [String]
39
- def source
40
- self.class.to_s.split("::").last.to_s
41
- end
42
-
43
69
  # @return [String]
44
70
  def class_name
45
71
  self.class.to_s.split("::").last
46
72
  end
47
73
 
74
+ alias_method :source, :class_name
75
+
48
76
  class << self
77
+ #
78
+ # Initialize an analyzer by query params
79
+ #
80
+ # @param [Hash] params
81
+ #
82
+ # @return [Mihari::Analyzers::Base]
83
+ #
84
+ def from_query(params)
85
+ copied = params.deep_dup
86
+
87
+ # convert params into arguments for initialization
88
+ query = copied[:query]
89
+
90
+ # delete analyzer and query
91
+ %i[analyzer query].each do |key|
92
+ copied.delete key
93
+ end
94
+
95
+ copied[:options] = copied[:options] || nil
96
+
97
+ new(query, **copied)
98
+ end
99
+
49
100
  def inherited(child)
50
101
  super
51
102
  Mihari.analyzers << child
@@ -3,23 +3,18 @@
3
3
  module Mihari
4
4
  module Analyzers
5
5
  class BinaryEdge < Base
6
- param :query
7
-
8
- option :interval, default: proc { 0 }
9
-
10
6
  # @return [String, nil]
11
7
  attr_reader :api_key
12
8
 
13
- # @return [String]
14
- attr_reader :query
15
-
16
- # @return [Integer]
17
- attr_reader :interval
18
-
19
- def initialize(*args, **kwargs)
20
- super(*args, **kwargs)
9
+ #
10
+ # @param [String] query
11
+ # @param [Hash, nil] options
12
+ # @param [String, nil] api_key
13
+ #
14
+ def initialize(query, options: nil, api_key: nil)
15
+ super(query, options: options)
21
16
 
22
- @api_key = kwargs[:api_key] || Mihari.config.binaryedge_api_key
17
+ @api_key = api_key || Mihari.config.binaryedge_api_key
23
18
  end
24
19
 
25
20
  def artifacts
@@ -48,7 +43,7 @@ module Mihari
48
43
  #
49
44
  def search_with_page(page: 1)
50
45
  client.search(query, page: page)
51
- rescue UnsuccessfulStatusCodeError => e
46
+ rescue StatusCodeError => e
52
47
  raise RetryableError, e if e.message.include?("Request time limit exceeded")
53
48
 
54
49
  raise e
@@ -69,7 +64,7 @@ module Mihari
69
64
  break if total <= page * PAGE_SIZE
70
65
 
71
66
  # sleep #{interval} seconds to avoid the rate limitation (if it is set)
72
- sleep interval
67
+ sleep(interval) if interval
73
68
  end
74
69
  responses
75
70
  end
@@ -3,27 +3,24 @@
3
3
  module Mihari
4
4
  module Analyzers
5
5
  class Censys < Base
6
- param :query
7
-
8
- option :interval, default: proc { 0 }
9
-
10
6
  # @return [String, nil]
11
7
  attr_reader :id
12
8
 
13
9
  # @return [String, nil]
14
10
  attr_reader :secret
15
11
 
16
- # @return [Integer]
17
- attr_reader :interval
18
-
19
- # @return [String]
20
- attr_reader :query
21
-
22
- def initialize(*args, **kwargs)
23
- super(*args, **kwargs)
12
+ #
13
+ # @param [String] query
14
+ # @param [hash, nil] options
15
+ # @param [String, nil] api_key
16
+ # @param [String, nil] id
17
+ # @param [String, nil] secret
18
+ #
19
+ def initialize(query, options: nil, id: nil, secret: nil)
20
+ super(query, options: options)
24
21
 
25
- @id = kwargs[:id] || Mihari.config.censys_id
26
- @secret = kwargs[:secret] || Mihari.config.censys_secret
22
+ @id = id || Mihari.config.censys_id
23
+ @secret = secret || Mihari.config.censys_secret
27
24
  end
28
25
 
29
26
  #
@@ -45,7 +42,7 @@ module Mihari
45
42
  break if cursor.nil? || cursor.empty?
46
43
 
47
44
  # sleep #{interval} seconds to avoid the rate limitation (if it is set)
48
- sleep interval
45
+ sleep(interval) if interval
49
46
  end
50
47
 
51
48
  artifacts.flatten.uniq(&:data)
@@ -5,8 +5,6 @@ module Mihari
5
5
  class CIRCL < Base
6
6
  include Mixins::Refang
7
7
 
8
- param :query
9
-
10
8
  # @return [String, nil]
11
9
  attr_reader :type
12
10
 
@@ -16,17 +14,19 @@ module Mihari
16
14
  # @return [String, nil]
17
15
  attr_reader :password
18
16
 
19
- # @return [String]
20
- attr_reader :query
21
-
22
- def initialize(*args, **kwargs)
23
- super
17
+ #
18
+ # @param [String] query
19
+ # @param [Hash, nil] options
20
+ # @param [String, nil] username
21
+ # @param [String, nil] password
22
+ #
23
+ def initialize(query, options: nil, username: nil, password: nil)
24
+ super(refang(query), options: options)
24
25
 
25
- @query = refang(query)
26
26
  @type = TypeChecker.type(query)
27
27
 
28
- @username = kwargs[:username] || Mihari.config.circl_passive_username
29
- @password = kwargs[:password] || Mihari.config.circl_passive_password
28
+ @username = username || Mihari.config.circl_passive_username
29
+ @password = password || Mihari.config.circl_passive_password
30
30
  end
31
31
 
32
32
  def artifacts
@@ -3,15 +3,19 @@
3
3
  module Mihari
4
4
  module Analyzers
5
5
  class Crtsh < Base
6
- param :query
7
-
8
- option :exclude_expired, default: proc { true }
9
-
10
6
  # @return [Boolean]
11
7
  attr_reader :exclude_expired
12
8
 
13
- # @return [String]
14
- attr_reader :query
9
+ #
10
+ # @param [String] query
11
+ # @param [Hash, nil] options
12
+ # @param [Bool] exclude_expired
13
+ #
14
+ def initialize(query, options: nil, exclude_expired: true)
15
+ super(query, options: options)
16
+
17
+ @exclude_expired = exclude_expired
18
+ end
15
19
 
16
20
  def artifacts
17
21
  results = search
@@ -5,18 +5,16 @@ module Mihari
5
5
  class DNSTwister < Base
6
6
  include Mixins::Refang
7
7
 
8
- param :query
9
-
10
8
  # @return [String]
11
9
  attr_reader :type
12
10
 
13
- # @return [String]
14
- attr_reader :query
15
-
16
- def initialize(*args, **kwargs)
17
- super
11
+ #
12
+ # @param [String] query
13
+ # @param [Hash, nil] options
14
+ #
15
+ def initialize(query, options: nil)
16
+ super(refang(query), options: options)
18
17
 
19
- @query = refang(query)
20
18
  @type = TypeChecker.type(query)
21
19
  end
22
20
 
@@ -6,16 +6,6 @@ require "mihari/feed/parser"
6
6
  module Mihari
7
7
  module Analyzers
8
8
  class Feed < Base
9
- param :query
10
-
11
- option :method, default: proc { "GET" }
12
- option :headers, default: proc { {} }
13
- option :params, default: proc {}
14
- option :json, default: proc {}
15
- option :data, default: proc {}
16
-
17
- option :selector, default: proc { "" }
18
-
19
9
  # @return [Hash, nil]
20
10
  attr_reader :data
21
11
 
@@ -37,6 +27,27 @@ module Mihari
37
27
  # @return [String]
38
28
  attr_reader :query
39
29
 
30
+ #
31
+ # @param [String] query
32
+ # @param [Hash, nil] options
33
+ # @param [String] method
34
+ # @param [Hash] headers
35
+ # @param [Hash] params
36
+ # @param [Hash] json
37
+ # @param [Hash] data
38
+ # @param [String] selector
39
+ #
40
+ def initialize(query, options: nil, method: "GET", headers: {}, params: {}, json: {}, data: {}, selector: "")
41
+ super(query, options: options)
42
+
43
+ @method = method
44
+ @headers = headers
45
+ @params = params
46
+ @json = json
47
+ @data = data
48
+ @selector = selector
49
+ end
50
+
40
51
  def artifacts
41
52
  Mihari::Feed::Parser.new(results).parse selector
42
53
  end
@@ -3,29 +3,28 @@
3
3
  module Mihari
4
4
  module Analyzers
5
5
  class GreyNoise < Base
6
- param :query
6
+ PAGE_SIZE = 10_000
7
7
 
8
8
  # @return [String, nil]
9
9
  attr_reader :api_key
10
10
 
11
- # @return [String]
12
- attr_reader :query
13
-
14
- def initialize(*args, **kwargs)
15
- super(*args, **kwargs)
11
+ #
12
+ # @param [String] query
13
+ # @param [Hash, nil] options
14
+ # @param [String, nil] api_key
15
+ #
16
+ def initialize(query, options: nil, api_key: nil)
17
+ super(query, options: options)
16
18
 
17
- @api_key = kwargs[:api_key] || Mihari.config.greynoise_api_key
19
+ @api_key = api_key || Mihari.config.greynoise_api_key
18
20
  end
19
21
 
20
22
  def artifacts
21
- res = search
22
- res.to_artifacts
23
+ client.gnql_search(query, size: PAGE_SIZE).to_artifacts
23
24
  end
24
25
 
25
26
  private
26
27
 
27
- PAGE_SIZE = 10_000
28
-
29
28
  def configuration_keys
30
29
  %w[greynoise_api_key]
31
30
  end
@@ -33,15 +32,6 @@ module Mihari
33
32
  def client
34
33
  @client ||= Clients::GreyNoise.new(api_key: api_key)
35
34
  end
36
-
37
- #
38
- # Search
39
- #
40
- # @return [Hash]
41
- #
42
- def search
43
- client.gnql_search(query, size: PAGE_SIZE)
44
- end
45
35
  end
46
36
  end
47
37
  end
@@ -5,23 +5,18 @@ require "normalize_country"
5
5
  module Mihari
6
6
  module Analyzers
7
7
  class Onyphe < Base
8
- param :query
9
-
10
- option :interval, default: proc { 0 }
11
-
12
8
  # @return [String, nil]
13
9
  attr_reader :api_key
14
10
 
15
- # @return [String]
16
- attr_reader :query
17
-
18
- # @return [Integer]
19
- attr_reader :interval
20
-
21
- def initialize(*args, **kwargs)
22
- super(*args, **kwargs)
11
+ #
12
+ # @param [String] query
13
+ # @param [Hash, nil] options
14
+ # @param [String, nil] api_key
15
+ #
16
+ def initialize(query, options: nil, api_key: nil)
17
+ super(query, options: options)
23
18
 
24
- @api_key = kwargs[:api_key] || Mihari.config.onyphe_api_key
19
+ @api_key = api_key || Mihari.config.onyphe_api_key
25
20
  end
26
21
 
27
22
  def artifacts
@@ -70,7 +65,7 @@ module Mihari
70
65
  break if total <= page * PAGE_SIZE
71
66
 
72
67
  # sleep #{interval} seconds to avoid the rate limitation (if it is set)
73
- sleep interval
68
+ sleep(interval) if interval
74
69
  end
75
70
  responses
76
71
  end
@@ -5,24 +5,23 @@ module Mihari
5
5
  class OTX < Base
6
6
  include Mixins::Refang
7
7
 
8
- param :query
9
-
10
8
  # @return [String, nil]
11
9
  attr_reader :type
12
10
 
13
11
  # @return [String, nil]
14
12
  attr_reader :api_key
15
13
 
16
- # @return [String]
17
- attr_reader :query
18
-
19
- def initialize(*args, **kwargs)
20
- super
14
+ #
15
+ # @param [String] query
16
+ # @param [Hash, nil] options
17
+ # @param [String, nil] api_key
18
+ #
19
+ def initialize(query, options: nil, api_key: nil)
20
+ super(refang(query), options: options)
21
21
 
22
- @query = refang(query)
23
22
  @type = TypeChecker.type(query)
24
23
 
25
- @api_key = kwargs[:api_key] || Mihari.config.otx_api_key
24
+ @api_key = api_key || Mihari.config.otx_api_key
26
25
  end
27
26
 
28
27
  def artifacts
@@ -5,8 +5,6 @@ module Mihari
5
5
  class PassiveTotal < Base
6
6
  include Mixins::Refang
7
7
 
8
- param :query
9
-
10
8
  # @return [String, nil]
11
9
  attr_reader :type
12
10
 
@@ -16,17 +14,19 @@ module Mihari
16
14
  # @return [String, nil]
17
15
  attr_reader :api_key
18
16
 
19
- # @return [String]
20
- attr_reader :query
21
-
22
- def initialize(*args, **kwargs)
23
- super(*args, **kwargs)
17
+ #
18
+ # @param [String] query
19
+ # @param [Hash, nil] options
20
+ # @param [String, nil] api_key
21
+ # @param [String, nil] username
22
+ #
23
+ def initialize(query, options: nil, api_key: nil, username: nil)
24
+ super(refang(query), options: options)
24
25
 
25
- @query = refang(query)
26
26
  @type = TypeChecker.type(query)
27
27
 
28
- @username = kwargs[:username] || Mihari.config.passivetotal_username
29
- @api_key = kwargs[:api_key] || Mihari.config.passivetotal_api_key
28
+ @username = username || Mihari.config.passivetotal_username
29
+ @api_key = api_key || Mihari.config.passivetotal_api_key
30
30
  end
31
31
 
32
32
  def artifacts
@@ -5,28 +5,39 @@ module Mihari
5
5
  class Pulsedive < Base
6
6
  include Mixins::Refang
7
7
 
8
- param :query
9
-
10
8
  # @return [String, nil]
11
9
  attr_reader :type
12
10
 
13
11
  # @return [String, nil]
14
12
  attr_reader :api_key
15
13
 
16
- # @return [Integer]
17
- attr_reader :query
18
-
19
- def initialize(*args, **kwargs)
20
- super
14
+ #
15
+ # @param [String] query
16
+ # @param [Hash, nil] options
17
+ # @param [String, nil] api_key
18
+ #
19
+ def initialize(query, options: nil, api_key: nil)
20
+ super(refang(query), options: options)
21
21
 
22
- @query = refang(query)
23
22
  @type = TypeChecker.type(query)
24
23
 
25
- @api_key = kwargs[:api_key] || Mihari.config.pulsedive_api_key
24
+ @api_key = api_key || Mihari.config.pulsedive_api_key
26
25
  end
27
26
 
28
27
  def artifacts
29
- search || []
28
+ raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
29
+
30
+ indicator = client.get_indicator(query)
31
+ iid = indicator["iid"]
32
+ properties = client.get_properties(iid)
33
+ (properties["dns"] || []).filter_map do |property|
34
+ if %w[A PTR].include?(property["name"])
35
+ nil
36
+ else
37
+ data = property["value"]
38
+ Artifact.new(data: data, source: source, metadata: property)
39
+ end
40
+ end
30
41
  end
31
42
 
32
43
  private
@@ -47,27 +58,6 @@ module Mihari
47
58
  def valid_type?
48
59
  %w[ip domain].include? type
49
60
  end
50
-
51
- #
52
- # Search
53
- #
54
- # @return [Array<Mihari::Artifact>]
55
- #
56
- def search
57
- raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
58
-
59
- indicator = client.get_indicator(query)
60
- iid = indicator["iid"]
61
- properties = client.get_properties(iid)
62
- (properties["dns"] || []).filter_map do |property|
63
- if %w[A PTR].include?(property["name"])
64
- nil
65
- else
66
- data = property["value"]
67
- Artifact.new(data: data, source: source, metadata: property)
68
- end
69
- end
70
- end
71
61
  end
72
62
  end
73
63
  end
@@ -46,7 +46,7 @@ module Mihari
46
46
  #
47
47
  # @param [Mihari::Structs::Rule] rule
48
48
  #
49
- def initialize(rule:)
49
+ def initialize(rule)
50
50
  @rule = rule
51
51
  @base_time = Time.now.utc
52
52
 
@@ -153,15 +153,6 @@ module Mihari
153
153
  end
154
154
  end
155
155
 
156
- #
157
- # Deep copied queries
158
- #
159
- # @return [Array<Hash>]
160
- #
161
- def queries
162
- rule.queries.map(&:deep_dup)
163
- end
164
-
165
156
  #
166
157
  # Get analyzer class
167
158
  #
@@ -177,26 +168,13 @@ module Mihari
177
168
  end
178
169
 
179
170
  #
180
- # @return [Array<Mihari::Analyzers::Base>] <description>
171
+ # @return [Array<Mihari::Analyzers::Base>]
181
172
  #
182
173
  def analyzers
183
- @analyzers ||= queries.map do |params|
184
- analyzer_name = params[:analyzer]
174
+ @analyzers ||= rule.queries.map do |query_params|
175
+ analyzer_name = query_params[:analyzer]
185
176
  klass = get_analyzer_class(analyzer_name)
186
-
187
- # set interval in the top level
188
- options = params[:options] || {}
189
- interval = options[:interval]
190
- params[:interval] = interval if interval
191
-
192
- # set rule
193
- params[:rule] = rule
194
- query = params[:query]
195
-
196
- analyzer = klass.new(query, **params)
197
- raise ConfigurationError, "#{analyzer.source} is not configured correctly" unless analyzer.configured?
198
-
199
- analyzer
177
+ klass.from_query(query_params)
200
178
  end
201
179
  end
202
180
 
@@ -240,8 +218,9 @@ module Mihari
240
218
  # Validate configuration of analyzers
241
219
  #
242
220
  def validate_analyzer_configurations
243
- # memoize analyzers & raise ConfigurationError if there is an analyzer which is not configured
244
- analyzers
221
+ analyzers.map do |analyzer|
222
+ raise ConfigurationError, "#{analyzer.source} is not configured correctly" unless analyzer.configured?
223
+ end
245
224
  end
246
225
  end
247
226
  end
@@ -5,8 +5,6 @@ module Mihari
5
5
  class SecurityTrails < Base
6
6
  include Mixins::Refang
7
7
 
8
- param :query
9
-
10
8
  # @return [String, nil]
11
9
  attr_reader :type
12
10
 
@@ -16,13 +14,17 @@ module Mihari
16
14
  # @return [String]
17
15
  attr_reader :query
18
16
 
19
- def initialize(*args, **kwargs)
20
- super
17
+ #
18
+ # @param [String] query
19
+ # @param [Hash, nil] options
20
+ # @param [String, nil] api_key
21
+ #
22
+ def initialize(query, options: nil, api_key: nil)
23
+ super(refang(query), options: options)
21
24
 
22
- @query = refang(query)
23
25
  @type = TypeChecker.type(query)
24
26
 
25
- @api_key = kwargs[:api_key] || Mihari.config.securitytrails_api_key
27
+ @api_key = api_key || Mihari.config.securitytrails_api_key
26
28
  end
27
29
 
28
30
  def artifacts