mihari 3.6.0 → 3.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/Steepfile +32 -0
  4. data/lib/mihari/analyzers/base.rb +7 -22
  5. data/lib/mihari/analyzers/binaryedge.rb +13 -0
  6. data/lib/mihari/analyzers/censys.rb +5 -0
  7. data/lib/mihari/analyzers/circl.rb +15 -0
  8. data/lib/mihari/analyzers/crtsh.rb +5 -0
  9. data/lib/mihari/analyzers/dnpedia.rb +5 -0
  10. data/lib/mihari/analyzers/dnstwister.rb +17 -0
  11. data/lib/mihari/analyzers/onyphe.rb +20 -4
  12. data/lib/mihari/analyzers/otx.rb +20 -0
  13. data/lib/mihari/analyzers/passivetotal.rb +25 -0
  14. data/lib/mihari/analyzers/pulsedive.rb +10 -0
  15. data/lib/mihari/analyzers/rule.rb +18 -0
  16. data/lib/mihari/analyzers/securitytrails.rb +25 -0
  17. data/lib/mihari/analyzers/shodan.rb +13 -0
  18. data/lib/mihari/analyzers/spyse.rb +20 -0
  19. data/lib/mihari/analyzers/urlscan.rb +10 -0
  20. data/lib/mihari/analyzers/virustotal.rb +20 -0
  21. data/lib/mihari/analyzers/zoomeye.rb +38 -0
  22. data/lib/mihari/database.rb +13 -0
  23. data/lib/mihari/emitters/base.rb +1 -1
  24. data/lib/mihari/emitters/misp.rb +38 -5
  25. data/lib/mihari/emitters/slack.rb +20 -2
  26. data/lib/mihari/emitters/the_hive.rb +16 -3
  27. data/lib/mihari/emitters/webhook.rb +18 -3
  28. data/lib/mihari/enrichers/base.rb +18 -0
  29. data/lib/mihari/enrichers/ipinfo.rb +49 -0
  30. data/lib/mihari/mixins/autonomous_system.rb +19 -0
  31. data/lib/mihari/mixins/disallowed_data_value.rb +1 -1
  32. data/lib/mihari/models/artifact.rb +42 -3
  33. data/lib/mihari/models/autonomous_system.rb +18 -1
  34. data/lib/mihari/models/dns.rb +2 -0
  35. data/lib/mihari/models/geolocation.rb +21 -1
  36. data/lib/mihari/models/reverse_dns.rb +2 -0
  37. data/lib/mihari/models/whois.rb +1 -1
  38. data/lib/mihari/status.rb +7 -2
  39. data/lib/mihari/structs/ipinfo.rb +39 -0
  40. data/lib/mihari/structs/onyphe.rb +2 -2
  41. data/lib/mihari/type_checker.rb +9 -9
  42. data/lib/mihari/version.rb +1 -1
  43. data/lib/mihari/web/controllers/artifacts_controller.rb +27 -1
  44. data/lib/mihari/web/controllers/ip_address_controller.rb +4 -19
  45. data/lib/mihari/web/public/index.html +1 -1
  46. data/lib/mihari/web/public/redoc-static.html +7 -6
  47. data/lib/mihari/web/public/static/js/app.06d5cf1c.js +36 -0
  48. data/lib/mihari/web/public/static/js/app.06d5cf1c.js.map +1 -0
  49. data/lib/mihari.rb +40 -26
  50. data/mihari.gemspec +7 -4
  51. data/sig/lib/mihari/analyzers/base.rbs +90 -0
  52. data/sig/lib/mihari/analyzers/basic.rbs +17 -0
  53. data/sig/lib/mihari/analyzers/binaryedge.rbs +25 -0
  54. data/sig/lib/mihari/analyzers/censys.rbs +38 -0
  55. data/sig/lib/mihari/analyzers/circl.rbs +29 -0
  56. data/sig/lib/mihari/analyzers/crtsh.rbs +19 -0
  57. data/sig/lib/mihari/analyzers/dnpedia.rbs +18 -0
  58. data/sig/lib/mihari/analyzers/dnstwister.rbs +27 -0
  59. data/sig/lib/mihari/analyzers/onyphe.rbs +33 -0
  60. data/sig/lib/mihari/analyzers/otx.rbs +33 -0
  61. data/sig/lib/mihari/analyzers/passivetotal.rbs +33 -0
  62. data/sig/lib/mihari/analyzers/pulsedive.rbs +27 -0
  63. data/sig/lib/mihari/analyzers/rule.rbs +68 -0
  64. data/sig/lib/mihari/analyzers/securitytrails.rbs +33 -0
  65. data/sig/lib/mihari/analyzers/shodan.rbs +33 -0
  66. data/sig/lib/mihari/analyzers/spyse.rbs +29 -0
  67. data/sig/lib/mihari/analyzers/urlscan.rbs +28 -0
  68. data/sig/lib/mihari/analyzers/virustotal.rbs +31 -0
  69. data/sig/lib/mihari/analyzers/zoomeye.rbs +33 -0
  70. data/sig/lib/mihari/cli/analyzer.rbs +39 -0
  71. data/sig/lib/mihari/cli/base.rbs +11 -0
  72. data/sig/lib/mihari/cli/init.rbs +7 -0
  73. data/sig/lib/mihari/cli/main.rbs +9 -0
  74. data/sig/lib/mihari/cli/mixins/utils.rbs +50 -0
  75. data/sig/lib/mihari/cli/validator.rbs +7 -0
  76. data/sig/lib/mihari/commands/binaryedge.rbs +7 -0
  77. data/sig/lib/mihari/commands/censys.rbs +7 -0
  78. data/sig/lib/mihari/commands/circl.rbs +7 -0
  79. data/sig/lib/mihari/commands/crtsh.rbs +7 -0
  80. data/sig/lib/mihari/commands/dnpedia.rbs +7 -0
  81. data/sig/lib/mihari/commands/dnstwister.rbs +7 -0
  82. data/sig/lib/mihari/commands/init.rbs +11 -0
  83. data/sig/lib/mihari/commands/json.rbs +7 -0
  84. data/sig/lib/mihari/commands/onyphe.rbs +7 -0
  85. data/sig/lib/mihari/commands/otx.rbs +7 -0
  86. data/sig/lib/mihari/commands/passivetotal.rbs +7 -0
  87. data/sig/lib/mihari/commands/pulsedive.rbs +7 -0
  88. data/sig/lib/mihari/commands/search.rbs +35 -0
  89. data/sig/lib/mihari/commands/securitytrails.rbs +7 -0
  90. data/sig/lib/mihari/commands/shodan.rbs +7 -0
  91. data/sig/lib/mihari/commands/spyse.rbs +7 -0
  92. data/sig/lib/mihari/commands/urlscan.rbs +7 -0
  93. data/sig/lib/mihari/commands/validator.rbs +11 -0
  94. data/sig/lib/mihari/commands/virustotal.rbs +7 -0
  95. data/sig/lib/mihari/commands/web.rbs +7 -0
  96. data/sig/lib/mihari/commands/zoomeye.rbs +7 -0
  97. data/sig/lib/mihari/constants.rbs +3 -0
  98. data/sig/lib/mihari/database.rbs +25 -0
  99. data/sig/lib/mihari/emitters/base.rbs +18 -0
  100. data/sig/lib/mihari/emitters/database.rbs +9 -0
  101. data/sig/lib/mihari/emitters/misp.rbs +28 -0
  102. data/sig/lib/mihari/emitters/slack.rbs +58 -0
  103. data/sig/lib/mihari/emitters/stdout.rbs +9 -0
  104. data/sig/lib/mihari/emitters/the_hive.rbs +24 -0
  105. data/sig/lib/mihari/emitters/webhook.rbs +20 -0
  106. data/sig/lib/mihari/enrichers/base.rbs +12 -0
  107. data/sig/lib/mihari/enrichers/ipinfo.rbs +16 -0
  108. data/sig/lib/mihari/errors.rbs +10 -0
  109. data/sig/lib/mihari/mixins/autonomous_system.rbs +14 -0
  110. data/sig/lib/mihari/mixins/configurable.rbs +26 -0
  111. data/sig/lib/mihari/mixins/configuration.rbs +45 -0
  112. data/sig/lib/mihari/mixins/disallowed_data_value.rbs +25 -0
  113. data/sig/lib/mihari/mixins/hash.rbs +14 -0
  114. data/sig/lib/mihari/mixins/refang.rbs +14 -0
  115. data/sig/lib/mihari/mixins/retriable.rbs +15 -0
  116. data/sig/lib/mihari/mixins/rule.rbs +41 -0
  117. data/sig/lib/mihari/models/alert.rbs +46 -0
  118. data/sig/lib/mihari/models/artifact.rbs +65 -0
  119. data/sig/lib/mihari/models/autonomous_system.rbs +14 -0
  120. data/sig/lib/mihari/models/dns.rbs +19 -0
  121. data/sig/lib/mihari/models/geolocation.rbs +15 -0
  122. data/sig/lib/mihari/models/reverse_dns.rbs +14 -0
  123. data/sig/lib/mihari/models/tag.rbs +5 -0
  124. data/sig/lib/mihari/models/tagging.rbs +4 -0
  125. data/sig/lib/mihari/models/whois.rbs +66 -0
  126. data/sig/lib/mihari/notifiers/base.rbs +18 -0
  127. data/sig/lib/mihari/notifiers/exception_notifier.rbs +75 -0
  128. data/sig/lib/mihari/notifiers/slack.rbs +50 -0
  129. data/sig/lib/mihari/status.rbs +25 -0
  130. data/sig/lib/mihari/structs/censys.rbs +50 -0
  131. data/sig/lib/mihari/structs/ipinfo.rbs +17 -0
  132. data/sig/lib/mihari/structs/onyphe.rbs +25 -0
  133. data/sig/lib/mihari/structs/shodan.rbs +28 -0
  134. data/sig/lib/mihari/type_checker.rbs +48 -0
  135. data/sig/lib/mihari/types.rbs +17 -0
  136. data/sig/lib/mihari/version.rbs +3 -0
  137. data/sig/lib/mihari/web/app.rbs +5 -0
  138. data/sig/lib/mihari.rbs +59 -0
  139. metadata +148 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9c1cbdf0570c25e2d89d7f6fd402b64991dfaebc75cf3cf5422a56504287ae9
4
- data.tar.gz: d5b7a0db7b49f245e3c949135011fb674e28a9d3c251e165f827e8f3d90673b1
3
+ metadata.gz: e4ce5b3ce24278b8141bf2078dce45d572846a4838a0dc00c34e695201c36d77
4
+ data.tar.gz: '0992223bccd1d9732e0cc9cb6063f822efef8f0db34a27a45ad829efc930a60f'
5
5
  SHA512:
6
- metadata.gz: e76a216dedbc1aec17748c37a1b874c2c825fed6f7716ef356a48ddf2861584da299c384737e588a48b67165874f495192bb42a4c20c2f29f4620f8b559d1a83
7
- data.tar.gz: 2f3e380b252ba238594ccacd2df8e362a62b9685aafeff34d6506e7301184cf5b38c4244db9498842f4aee9df109d7c43a9ad99cecc3b63616d333a7f5093333
6
+ metadata.gz: 26aa441c9e982df2a84e5d3f8cc5bc261b49b9dae618fc73384a116927481125b4a87dac8317a6fb319caf5523398020ebcf8973eee6229d128a377f1054c4db
7
+ data.tar.gz: bfee6864b187018a6a9f9b5f4c68cfdea496b36ebad0b796425642ed9b80b2f7c70c4d74ef16964838e16b2985acddb11d4b0c0a6c4cca73dfb93d7a1ff83875
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "vendor/rbs/gem_rbs_collection"]
2
+ path = vendor/rbs/gem_rbs_collection
3
+ url = https://github.com/ruby/gem_rbs_collection.git
data/Steepfile ADDED
@@ -0,0 +1,32 @@
1
+ target :lib do
2
+ signature "sig"
3
+ check "lib"
4
+
5
+ repo_path "vendor/rbs/gem_rbs_collection/gems"
6
+
7
+ library "date"
8
+ library "json"
9
+ library "logger"
10
+ library "monitor"
11
+ library "mutex_m"
12
+ library "pathname"
13
+ library "securerandom"
14
+ library "singleton"
15
+ library "time"
16
+ library "tsort"
17
+ library "uri"
18
+ library "resolv"
19
+ library "timeout"
20
+ library "socket"
21
+
22
+ library "rack"
23
+
24
+ library "actionpack"
25
+ library "actionview"
26
+ library "activejob"
27
+ library "activemodel"
28
+ library "activerecord"
29
+ library "activesupport"
30
+ library "parallel"
31
+ library "railties"
32
+ end
@@ -8,6 +8,7 @@ module Mihari
8
8
  class Base
9
9
  extend Dry::Initializer
10
10
 
11
+ include Mixins::AutonomousSystem
11
12
  include Mixins::Configurable
12
13
  include Mixins::Retriable
13
14
 
@@ -27,7 +28,7 @@ module Mihari
27
28
 
28
29
  # @return [String]
29
30
  def title
30
- self.class.to_s.split("::").last
31
+ self.class.to_s.split("::").last.to_s
31
32
  end
32
33
 
33
34
  # @return [String]
@@ -37,7 +38,7 @@ module Mihari
37
38
 
38
39
  # @return [String]
39
40
  def source
40
- self.class.to_s.split("::").last
41
+ self.class.to_s.split("::").last.to_s
41
42
  end
42
43
 
43
44
  # @return [Array<String>]
@@ -111,9 +112,7 @@ module Mihari
111
112
  #
112
113
  def enriched_artifacts
113
114
  @enriched_artifacts ||= unique_artifacts.map do |artifact|
114
- artifact.enrich_whois
115
- artifact.enrich_dns
116
- artifact.enrich_reverse_dns
115
+ artifact.enrich_all
117
116
  artifact
118
117
  end
119
118
  end
@@ -125,9 +124,9 @@ module Mihari
125
124
  #
126
125
  def set_enriched_artifacts
127
126
  retry_on_error { enriched_artifacts }
128
- rescue ArgumentError => _e
127
+ rescue ArgumentError => e
129
128
  klass = self.class.to_s.split("::").last.to_s
130
- raise Error, "Please configure #{klass} API settings properly"
129
+ raise Error, "Please configure #{klass} settings properly. (#{e})"
131
130
  end
132
131
 
133
132
  #
@@ -139,21 +138,7 @@ module Mihari
139
138
  @valid_emitters ||= Mihari.emitters.filter_map do |klass|
140
139
  emitter = klass.new
141
140
  emitter.valid? ? emitter : nil
142
- end
143
- end
144
-
145
- #
146
- # Normalize ASN value
147
- #
148
- # @param [String, Integer] asn
149
- #
150
- # @return [Integer]
151
- #
152
- def normalize_asn(asn)
153
- return asn if asn.is_a?(Integer)
154
- return asn.to_i unless asn.start_with?("AS")
155
-
156
- asn.delete_prefix("AS").to_i
141
+ end.compact
157
142
  end
158
143
  end
159
144
  end
@@ -26,6 +26,14 @@ module Mihari
26
26
 
27
27
  PAGE_SIZE = 20
28
28
 
29
+ #
30
+ # Search with pagination
31
+ #
32
+ # @param [String] query
33
+ # @param [Integer] page
34
+ #
35
+ # @return [Hash]
36
+ #
29
37
  def search_with_page(query, page: 1)
30
38
  api.host.search(query, page: page)
31
39
  rescue ::BinaryEdge::Error => e
@@ -34,6 +42,11 @@ module Mihari
34
42
  raise e
35
43
  end
36
44
 
45
+ #
46
+ # Search
47
+ #
48
+ # @return [Array<Hash>]
49
+ #
37
50
  def search
38
51
  responses = []
39
52
  (1..Float::INFINITY).each do |page|
@@ -16,6 +16,11 @@ module Mihari
16
16
 
17
17
  private
18
18
 
19
+ #
20
+ # Search
21
+ #
22
+ # @return [Array<String>]
23
+ #
19
24
  def search
20
25
  artifacts = []
21
26
 
@@ -35,6 +35,11 @@ module Mihari
35
35
  @api ||= ::PassiveCIRCL::API.new(username: Mihari.config.circl_passive_username, password: Mihari.config.circl_passive_password)
36
36
  end
37
37
 
38
+ #
39
+ # Passive DNS/SSL search
40
+ #
41
+ # @return [Array<String>]
42
+ #
38
43
  def search
39
44
  case @type
40
45
  when "domain"
@@ -46,6 +51,11 @@ module Mihari
46
51
  end
47
52
  end
48
53
 
54
+ #
55
+ # Passive DNS search
56
+ #
57
+ # @return [Array<String>]
58
+ #
49
59
  def passive_dns_search
50
60
  results = api.dns.query(@query)
51
61
  results.filter_map do |result|
@@ -54,6 +64,11 @@ module Mihari
54
64
  end.uniq
55
65
  end
56
66
 
67
+ #
68
+ # Passive SSL search
69
+ #
70
+ # @return [Array<String>]
71
+ #
57
72
  def passive_ssl_search
58
73
  result = api.ssl.cquery(@query)
59
74
  seen = result["seen"] || []
@@ -23,6 +23,11 @@ module Mihari
23
23
  @api ||= ::Crtsh::API.new
24
24
  end
25
25
 
26
+ #
27
+ # Search
28
+ #
29
+ # @return [Array<Hash>]
30
+ #
26
31
  def search
27
32
  exclude = exclude_expired ? "expired" : nil
28
33
  api.search(query, exclude: exclude)
@@ -20,6 +20,11 @@ module Mihari
20
20
  @api ||= ::DNPedia::API.new
21
21
  end
22
22
 
23
+ #
24
+ # Search
25
+ #
26
+ # @return [Array<String>]
27
+ #
23
28
  def search
24
29
  res = api.search(query)
25
30
  rows = res["rows"] || []
@@ -29,6 +29,11 @@ module Mihari
29
29
 
30
30
  private
31
31
 
32
+ #
33
+ # Check whether a type is valid or not
34
+ #
35
+ # @return [Boolean]
36
+ #
32
37
  def valid_type?
33
38
  type == "domain"
34
39
  end
@@ -37,6 +42,13 @@ module Mihari
37
42
  @api ||= ::DNSTwister::API.new
38
43
  end
39
44
 
45
+ #
46
+ # Check whether a domain is resolvable or not
47
+ #
48
+ # @param [String] domain
49
+ #
50
+ # @return [Boolean]
51
+ #
40
52
  def resolvable?(domain)
41
53
  Resolv.getaddress domain
42
54
  true
@@ -44,6 +56,11 @@ module Mihari
44
56
  false
45
57
  end
46
58
 
59
+ #
60
+ # Search
61
+ #
62
+ # @return [Array<String>]
63
+ #
47
64
  def search
48
65
  raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
49
66
 
@@ -33,11 +33,24 @@ module Mihari
33
33
  @api ||= ::Onyphe::API.new(Mihari.config.onyphe_api_key)
34
34
  end
35
35
 
36
+ #
37
+ # Search with pagination
38
+ #
39
+ # @param [String] query
40
+ # @param [Integer] page
41
+ #
42
+ # @return [Structs::Onyphe::Response]
43
+ #
36
44
  def search_with_page(query, page: 1)
37
45
  res = api.simple.datascan(query, page: page)
38
46
  Structs::Onyphe::Response.from_dynamic!(res)
39
47
  end
40
48
 
49
+ #
50
+ # Search
51
+ #
52
+ # @return [Array<Structs::Onyphe::Response>]
53
+ #
41
54
  def search
42
55
  responses = []
43
56
  (1..Float::INFINITY).each do |page|
@@ -60,10 +73,13 @@ module Mihari
60
73
  def build_artifact(result)
61
74
  as = AutonomousSystem.new(asn: normalize_asn(result.asn))
62
75
 
63
- geolocation = Geolocation.new(
64
- country: NormalizeCountry(result.country_code, to: :short),
65
- country_code: result.country_code
66
- )
76
+ geolocation = nil
77
+ unless result.country_code.nil?
78
+ geolocation = Geolocation.new(
79
+ country: NormalizeCountry(result.country_code, to: :short),
80
+ country_code: result.country_code
81
+ )
82
+ end
67
83
 
68
84
  Artifact.new(
69
85
  data: result.ip,
@@ -39,10 +39,20 @@ module Mihari
39
39
  @ip_client ||= ::OTX::IP.new(Mihari.config.otx_api_key)
40
40
  end
41
41
 
42
+ #
43
+ # Check whether a type is valid or not
44
+ #
45
+ # @return [Boolean]
46
+ #
42
47
  def valid_type?
43
48
  %w[ip domain].include? type
44
49
  end
45
50
 
51
+ #
52
+ # IP/domain search
53
+ #
54
+ # @return [Array<String>]
55
+ #
46
56
  def search
47
57
  case type
48
58
  when "domain"
@@ -54,6 +64,11 @@ module Mihari
54
64
  end
55
65
  end
56
66
 
67
+ #
68
+ # Domain search
69
+ #
70
+ # @return [Array<String>]
71
+ #
57
72
  def domain_search
58
73
  records = domain_client.get_passive_dns(query)
59
74
  records.filter_map do |record|
@@ -61,6 +76,11 @@ module Mihari
61
76
  end.uniq
62
77
  end
63
78
 
79
+ #
80
+ # IP search
81
+ #
82
+ # @return [Array<String>]
83
+ #
64
84
  def ip_search
65
85
  records = ip_client.get_passive_dns(query)
66
86
  records.filter_map do |record|
@@ -35,10 +35,20 @@ module Mihari
35
35
  @api ||= ::PassiveTotal::API.new(username: Mihari.config.passivetotal_username, api_key: Mihari.config.passivetotal_api_key)
36
36
  end
37
37
 
38
+ #
39
+ # Check whether a type is valid or not
40
+ #
41
+ # @return [Boolean]
42
+ #
38
43
  def valid_type?
39
44
  %w[ip domain mail hash].include? type
40
45
  end
41
46
 
47
+ #
48
+ # Passive DNS/SSL, reverse whois search
49
+ #
50
+ # @return [Array<String>]
51
+ #
42
52
  def search
43
53
  case type
44
54
  when "domain", "ip"
@@ -52,11 +62,21 @@ module Mihari
52
62
  end
53
63
  end
54
64
 
65
+ #
66
+ # Passive DNS search
67
+ #
68
+ # @return [Array<String>]
69
+ #
55
70
  def passive_dns_search
56
71
  res = api.dns.passive_unique(query)
57
72
  res["results"] || []
58
73
  end
59
74
 
75
+ #
76
+ # Reverse whois search
77
+ #
78
+ # @return [Array<String>]
79
+ #
60
80
  def reverse_whois_search
61
81
  res = api.whois.search(query: query, field: "email")
62
82
  results = res["results"] || []
@@ -65,6 +85,11 @@ module Mihari
65
85
  end.flatten.compact.uniq
66
86
  end
67
87
 
88
+ #
89
+ # Passive SSL search
90
+ #
91
+ # @return [Array<String>]
92
+ #
68
93
  def ssl_search
69
94
  res = api.ssl.history(query)
70
95
  results = res["results"] || []
@@ -35,10 +35,20 @@ module Mihari
35
35
  @api ||= ::Pulsedive::API.new(Mihari.config.pulsedive_api_key)
36
36
  end
37
37
 
38
+ #
39
+ # Check whether a type is valid or not
40
+ #
41
+ # @return [Boolean]
42
+ #
38
43
  def valid_type?
39
44
  %w[ip domain].include? type
40
45
  end
41
46
 
47
+ #
48
+ # Search
49
+ #
50
+ # @return [Array<String>]
51
+ #
42
52
  def search
43
53
  raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
44
54
 
@@ -22,6 +22,8 @@ module Mihari
22
22
  super(**kwargs)
23
23
 
24
24
  @source = id || UUIDTools::UUID.md5_create(UUIDTools::UUID_URL_NAMESPACE, title + description).to_s
25
+
26
+ validate_analyzer_configurations
25
27
  end
26
28
 
27
29
  ANALYZER_TO_CLASS = {
@@ -119,6 +121,22 @@ module Mihari
119
121
 
120
122
  raise ArgumentError, "#{analyzer_name} is not supported"
121
123
  end
124
+
125
+ #
126
+ # Validate configuration of analyzers
127
+ #
128
+ def validate_analyzer_configurations
129
+ queries.each do |params|
130
+ analyzer_name = params[:analyzer]
131
+ klass = get_analyzer_class(analyzer_name)
132
+
133
+ instance = klass.new("dummy")
134
+ unless instance.configured?
135
+ klass_name = klass.to_s.split("::").last
136
+ raise ArgumentError, "#{klass_name} is not configured correctly"
137
+ end
138
+ end
139
+ end
122
140
  end
123
141
  end
124
142
  end