mihari 5.5.0 → 5.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/docs/analyzers/binaryedge.md +1 -1
  3. data/docs/analyzers/censys.md +1 -1
  4. data/docs/analyzers/circl.md +1 -1
  5. data/docs/analyzers/crtsh.md +1 -1
  6. data/docs/analyzers/dnstwister.md +1 -1
  7. data/docs/analyzers/greynoise.md +1 -1
  8. data/docs/analyzers/hunterhow.md +1 -1
  9. data/docs/analyzers/index.md +29 -15
  10. data/docs/analyzers/onyphe.md +1 -1
  11. data/docs/analyzers/otx.md +2 -2
  12. data/docs/analyzers/passivetotal.md +6 -2
  13. data/docs/analyzers/pulsedive.md +2 -2
  14. data/docs/analyzers/securitytrails.md +6 -2
  15. data/docs/analyzers/shodan.md +1 -1
  16. data/docs/analyzers/urlscan.md +3 -3
  17. data/docs/analyzers/virustotal.md +6 -2
  18. data/docs/analyzers/virustotal_intelligence.md +8 -4
  19. data/docs/analyzers/zoomeye.md +5 -0
  20. data/docs/emitters/hive.md +1 -1
  21. data/docs/emitters/slack.md +0 -5
  22. data/docs/enrichers/google_public_dns.md +1 -1
  23. data/docs/enrichers/ipinfo.md +2 -2
  24. data/docs/enrichers/shodan.md +4 -4
  25. data/docs/enrichers/whois.md +1 -1
  26. data/docs/rule.md +1 -4
  27. data/docs/usage.md +5 -2
  28. data/frontend/package-lock.json +3 -3
  29. data/frontend/src/components/ErrorMessage.vue +0 -1
  30. data/frontend/src/components/alert/Alerts.vue +0 -1
  31. data/frontend/src/components/alert/AlertsWithPagination.vue +0 -1
  32. data/frontend/src/components/alert/AlertsWrapper.vue +0 -6
  33. data/frontend/src/components/alert/Form.vue +1 -3
  34. data/frontend/src/components/artifact/Artifact.vue +0 -17
  35. data/frontend/src/components/artifact/ArtifactWrapper.vue +0 -2
  36. data/frontend/src/components/artifact/WhoisRecord.vue +0 -3
  37. data/frontend/src/components/config/ConfigsWrapper.vue +0 -2
  38. data/frontend/src/components/rule/EditRule.vue +0 -3
  39. data/frontend/src/components/rule/EditRuleWrapper.vue +0 -2
  40. data/frontend/src/components/rule/Form.vue +1 -3
  41. data/frontend/src/components/rule/NewRule.vue +0 -3
  42. data/frontend/src/components/rule/Rule.vue +1 -7
  43. data/frontend/src/components/rule/RuleWrapper.vue +0 -2
  44. data/frontend/src/components/rule/RulesWrapper.vue +0 -6
  45. data/frontend/src/swagger.yaml +254 -254
  46. data/lib/mihari/analyzers/base.rb +4 -41
  47. data/lib/mihari/analyzers/circl.rb +1 -1
  48. data/lib/mihari/analyzers/crtsh.rb +1 -1
  49. data/lib/mihari/analyzers/dnstwister.rb +1 -1
  50. data/lib/mihari/analyzers/otx.rb +1 -1
  51. data/lib/mihari/analyzers/passivetotal.rb +10 -1
  52. data/lib/mihari/analyzers/pulsedive.rb +2 -2
  53. data/lib/mihari/analyzers/rule.rb +24 -59
  54. data/lib/mihari/analyzers/securitytrails.rb +10 -1
  55. data/lib/mihari/analyzers/virustotal.rb +11 -2
  56. data/lib/mihari/analyzers/virustotal_intelligence.rb +16 -0
  57. data/lib/mihari/analyzers/zoomeye.rb +2 -2
  58. data/lib/mihari/base.rb +69 -0
  59. data/lib/mihari/cli/main.rb +36 -0
  60. data/lib/mihari/clients/base.rb +2 -2
  61. data/lib/mihari/clients/binaryedge.rb +3 -5
  62. data/lib/mihari/clients/censys.rb +3 -3
  63. data/lib/mihari/clients/circl.rb +5 -4
  64. data/lib/mihari/clients/crtsh.rb +3 -2
  65. data/lib/mihari/clients/dnstwister.rb +3 -2
  66. data/lib/mihari/clients/greynoise.rb +2 -2
  67. data/lib/mihari/clients/hunterhow.rb +2 -2
  68. data/lib/mihari/clients/misp.rb +1 -1
  69. data/lib/mihari/clients/onyphe.rb +2 -2
  70. data/lib/mihari/clients/otx.rb +4 -3
  71. data/lib/mihari/clients/passivetotal.rb +5 -4
  72. data/lib/mihari/clients/publsedive.rb +4 -3
  73. data/lib/mihari/clients/securitytrails.rb +5 -3
  74. data/lib/mihari/clients/shodan.rb +2 -2
  75. data/lib/mihari/clients/the_hive.rb +1 -1
  76. data/lib/mihari/clients/urlscan.rb +4 -4
  77. data/lib/mihari/clients/virustotal.rb +2 -2
  78. data/lib/mihari/clients/zoomeye.rb +2 -2
  79. data/lib/mihari/commands/alert.rb +6 -33
  80. data/lib/mihari/commands/rule.rb +7 -12
  81. data/lib/mihari/commands/search.rb +10 -38
  82. data/lib/mihari/constants.rb +3 -3
  83. data/lib/mihari/emitters/base.rb +3 -33
  84. data/lib/mihari/emitters/database.rb +1 -1
  85. data/lib/mihari/enrichers/base.rb +2 -33
  86. data/lib/mihari/enrichers/google_public_dns.rb +9 -0
  87. data/lib/mihari/schemas/analyzer.rb +24 -24
  88. data/lib/mihari/schemas/emitter.rb +6 -13
  89. data/lib/mihari/schemas/enricher.rb +4 -11
  90. data/lib/mihari/schemas/options.rb +27 -0
  91. data/lib/mihari/schemas/rule.rb +2 -2
  92. data/lib/mihari/services/alert_runner.rb +1 -1
  93. data/lib/mihari/services/rule_runner.rb +1 -11
  94. data/lib/mihari/types.rb +1 -14
  95. data/lib/mihari/version.rb +1 -1
  96. data/lib/mihari/web/public/assets/{index-33165282.css → index-56fc2187.css} +1 -1
  97. data/lib/mihari/web/public/assets/{index-b5d817a3.js → index-9cc489e6.js} +2 -2
  98. data/lib/mihari/web/public/index.html +2 -2
  99. data/lib/mihari.rb +67 -37
  100. data/mihari.gemspec +1 -0
  101. data/mkdocs.yml +0 -3
  102. metadata +20 -4
@@ -7,12 +7,13 @@ module Mihari
7
7
  # @param [String] base_url
8
8
  # @param [String, nil] api_key
9
9
  # @param [Hash] headers
10
+ # @param [Integer, nil] timeout
10
11
  #
11
- def initialize(base_url = "https://otx.alienvault.com", api_key:, headers: {})
12
- raise(ArgumentError, "'api_key' argument is required") unless api_key
12
+ def initialize(base_url = "https://otx.alienvault.com", api_key:, headers: {}, timeout: nil)
13
+ raise(ArgumentError, "api_key is required") unless api_key
13
14
 
14
15
  headers["x-otx-api-key"] = api_key
15
- super(base_url, headers: headers)
16
+ super(base_url, headers: headers, timeout: timeout)
16
17
  end
17
18
 
18
19
  #
@@ -10,14 +10,15 @@ module Mihari
10
10
  # @param [String, nil] username
11
11
  # @param [String, nil] api_key
12
12
  # @param [Hash] headers
13
+ # @param [Integer, nil] timeout
13
14
  #
14
- def initialize(base_url = "https://api.passivetotal.org", username:, api_key:, headers: {})
15
- raise(ArgumentError, "'username' argument is required") if username.nil?
16
- raise(ArgumentError, "'api_key' argument is required") if api_key.nil?
15
+ def initialize(base_url = "https://api.passivetotal.org", username:, api_key:, headers: {}, timeout: nil)
16
+ raise(ArgumentError, "username is required") if username.nil?
17
+ raise(ArgumentError, "api_key is required") if api_key.nil?
17
18
 
18
19
  headers["authorization"] = "Basic #{Base64.strict_encode64("#{username}:#{api_key}")}"
19
20
 
20
- super(base_url, headers: headers)
21
+ super(base_url, headers: headers, timeout: timeout)
21
22
  end
22
23
 
23
24
  #
@@ -10,13 +10,14 @@ module Mihari
10
10
  # @param [String] base_url
11
11
  # @param [String, nil] api_key
12
12
  # @param [Hash] headers
13
+ # @param [Integer, nil] timeout
13
14
  #
14
- def initialize(base_url = "https://pulsedive.com", api_key:, headers: {})
15
- super(base_url, headers: headers)
15
+ def initialize(base_url = "https://pulsedive.com", api_key:, headers: {}, timeout: nil)
16
+ raise(ArgumentError, "api_key is required") unless api_key
16
17
 
17
18
  @api_key = api_key
18
19
 
19
- raise(ArgumentError, "'api_key' argument is required") unless api_key
20
+ super(base_url, headers: headers, timeout: timeout)
20
21
  end
21
22
 
22
23
  #
@@ -7,12 +7,14 @@ module Mihari
7
7
  # @param [String] base_url
8
8
  # @param [String, nil] api_key
9
9
  # @param [Hash] headers
10
+ # @param [Integer, nil] timeout
10
11
  #
11
- def initialize(base_url = "https://api.securitytrails.com", api_key:, headers: {})
12
- raise(ArgumentError, "'api_key' argument is required") unless api_key
12
+ def initialize(base_url = "https://api.securitytrails.com", api_key:, headers: {}, timeout: nil)
13
+ raise(ArgumentError, "api_key is required") unless api_key
13
14
 
14
15
  headers["apikey"] = api_key
15
- super(base_url, headers: headers)
16
+
17
+ super(base_url, headers: headers, timeout: timeout)
16
18
  end
17
19
 
18
20
  #
@@ -19,10 +19,10 @@ module Mihari
19
19
  base_url = "https://api.shodan.io",
20
20
  api_key:,
21
21
  headers: {},
22
- pagination_interval: 0,
22
+ pagination_interval: Mihari.config.pagination_interval,
23
23
  timeout: nil
24
24
  )
25
- raise(ArgumentError, "'api_key' argument is required") unless api_key
25
+ raise(ArgumentError, "api_key is required") unless api_key
26
26
 
27
27
  super(base_url, headers: headers, pagination_interval: pagination_interval, timeout: timeout)
28
28
 
@@ -11,7 +11,7 @@ module Mihari
11
11
  # @param [Integer, nil] timeout
12
12
  #
13
13
  def initialize(base_url, api_key:, api_version:, headers: {}, timeout: nil)
14
- raise(ArgumentError, "'api_key' argument is required") unless api_key
14
+ raise(ArgumentError, "api_key is required") unless api_key
15
15
 
16
16
  base_url += "/#{api_version}" unless api_version.nil?
17
17
  headers["authorization"] = "Bearer #{api_key}"
@@ -7,17 +7,17 @@ module Mihari
7
7
  # @param [String] base_url
8
8
  # @param [String, nil] api_key
9
9
  # @param [Hash] headers
10
- # @param [Interval, nil] interval
11
- # @param [Interval, nil] timeout
10
+ # @param [Integer, nil] interval
11
+ # @param [Integer, nil] timeout
12
12
  #
13
13
  def initialize(
14
14
  base_url = "https://urlscan.io",
15
15
  api_key:,
16
16
  headers: {},
17
- pagination_interval: 0,
17
+ pagination_interval: Mihari.config.pagination_interval,
18
18
  timeout: nil
19
19
  )
20
- raise(ArgumentError, "'api_key' argument is required") if api_key.nil?
20
+ raise(ArgumentError, "api_key is required") if api_key.nil?
21
21
 
22
22
  headers["api-key"] = api_key
23
23
 
@@ -14,10 +14,10 @@ module Mihari
14
14
  base_url = "https://www.virustotal.com",
15
15
  api_key:,
16
16
  headers: {},
17
- pagination_interval: 0,
17
+ pagination_interval: Mihari.config.pagination_interval,
18
18
  timeout: nil
19
19
  )
20
- raise(ArgumentError, "'api_key' argument is required") if api_key.nil?
20
+ raise(ArgumentError, "api_key is required") if api_key.nil?
21
21
 
22
22
  headers["x-apikey"] = api_key
23
23
 
@@ -18,10 +18,10 @@ module Mihari
18
18
  base_url = "https://api.zoomeye.org",
19
19
  api_key:,
20
20
  headers: {},
21
- pagination_interval: 0,
21
+ pagination_interval: Mihari.config.pagination_interval,
22
22
  timeout: nil
23
23
  )
24
- raise(ArgumentError, "'api_key' argument is required") unless api_key
24
+ raise(ArgumentError, "api_key is required") unless api_key
25
25
 
26
26
  headers["api-key"] = api_key
27
27
  super(base_url, headers: headers, pagination_interval: pagination_interval, timeout: timeout)
@@ -14,30 +14,14 @@ module Mihari
14
14
  #
15
15
  def add(path)
16
16
  Mihari::Database.with_db_connection do
17
- builder = Mihari::Services::AlertBuilder.new(path)
17
+ builder = Services::AlertBuilder.new(path)
18
18
 
19
19
  run_proxy_l = ->(proxy) { run_proxy proxy }
20
- check_nil_l = ->(alert_or_nil) { check_nil alert_or_nil }
20
+ result = builder.result.bind(run_proxy_l)
21
21
 
22
- result = builder.result.bind(run_proxy_l).bind(check_nil_l)
23
-
24
- if result.success?
25
- alert = result.value!
26
- data = Mihari::Entities::Alert.represent(alert)
27
- puts JSON.pretty_generate(data.as_json)
28
- return
29
- end
30
-
31
- failure = result.failure
32
- case failure
33
- when ValidationError
34
- Mihari.logger.error "Failed to parse the input as an alert:"
35
- Mihari.logger.error JSON.pretty_generate(failure.errors.to_h)
36
- when StandardError
37
- raise failure
38
- else
39
- Mihari.logger.info failure
40
- end
22
+ alert = result.value!
23
+ data = Entities::Alert.represent(alert)
24
+ puts JSON.pretty_generate(data.as_json)
41
25
  end
42
26
  end
43
27
 
@@ -47,21 +31,10 @@ module Mihari
47
31
  #
48
32
  def run_proxy(proxy)
49
33
  Dry::Monads::Try[StandardError] do
50
- runner = Mihari::Services::AlertRunner.new(proxy)
34
+ runner = Services::AlertRunner.new(proxy)
51
35
  runner.run
52
36
  end.to_result
53
37
  end
54
-
55
- #
56
- # @param [Mihari::Alert, nil] alert_or_nil
57
- #
58
- def check_nil(alert_or_nil)
59
- if alert_or_nil.nil?
60
- Failure "There is no new artifact found"
61
- else
62
- Success alert_or_nil
63
- end
64
- end
65
38
  end
66
39
  end
67
40
  end
@@ -8,7 +8,7 @@ module Mihari
8
8
  class << self
9
9
  def included(thor)
10
10
  thor.class_eval do
11
- include Dry::Monads[:result, :try]
11
+ include Dry::Monads[:try, :result]
12
12
 
13
13
  desc "validate [PATH]", "Validate a rule file"
14
14
  #
@@ -18,16 +18,11 @@ module Mihari
18
18
  #
19
19
  def validate(path)
20
20
  res = Dry::Monads::Try[ValidationError] do
21
- Services::RuleProxy.from_yaml(File.read(path))
22
- end.fmap do |rule|
23
- Mihari.logger.info "Valid format. The input is parsed as the following:"
24
- Mihari.logger.info rule.data.to_yaml
21
+ Services::RuleProxy.from_yaml File.read(path)
25
22
  end
26
23
 
27
- return unless res.error?
28
-
29
- Mihari.logger.error "Failed to parse the input as a rule:"
30
- Mihari.logger.error JSON.pretty_generate(res.exception.errors.to_h)
24
+ rule = res.value!
25
+ puts rule.data.to_yaml
31
26
  end
32
27
 
33
28
  desc "init [PATH]", "Initialize a new rule file"
@@ -43,14 +38,14 @@ module Mihari
43
38
 
44
39
  initialize_rule path
45
40
 
46
- Mihari.logger.info "A new rule file has been initialized: #{path}."
41
+ puts "A new rule file has been initialized: #{path}."
47
42
  end
48
43
 
49
44
  no_commands do
50
45
  #
51
46
  # @return [Mihari::Services::Rule]
52
47
  #
53
- def rule_template
48
+ def rule
54
49
  Services::RuleProxy.from_yaml File.read(File.expand_path("../templates/rule.yml.erb", __dir__))
55
50
  end
56
51
 
@@ -63,7 +58,7 @@ module Mihari
63
58
  # @return [nil]
64
59
  #
65
60
  def initialize_rule(path, files = Dry::Files.new)
66
- files.write(path, rule_template.yaml)
61
+ files.write(path, rule.yaml)
67
62
  end
68
63
  end
69
64
  end
@@ -6,10 +6,10 @@ module Mihari
6
6
  class << self
7
7
  def included(thor)
8
8
  thor.class_eval do
9
- include Dry::Monads[:result, :try]
9
+ include Dry::Monads[:try, :result]
10
10
 
11
- desc "search [PATH_OR_ID]", "Search by a rule"
12
- method_option :force_overwrite, type: :boolean, aliases: "-f", desc: "Force an overwrite the rule"
11
+ desc "search [PATH_OR_ID]", "Search by a rule (Outputs null if there is no new finding)"
12
+ method_option :force_overwrite, type: :boolean, aliases: "-f", desc: "Force overwriting a rule"
13
13
  #
14
14
  # Search by a rule
15
15
  #
@@ -21,27 +21,12 @@ module Mihari
21
21
 
22
22
  check_diff_l = ->(rule) { check_diff rule }
23
23
  update_and_run_l = ->(runner) { update_and_run runner }
24
- check_nil_l = ->(alert_or_nil) { check_nil alert_or_nil }
25
24
 
26
- result = builder.result.bind(check_diff_l).bind(update_and_run_l).bind(check_nil_l)
25
+ result = builder.result.bind(check_diff_l).bind(update_and_run_l)
27
26
 
28
- if result.success?
29
- alert = result.value!
30
- data = Mihari::Entities::Alert.represent(alert)
31
- puts JSON.pretty_generate(data.as_json)
32
- return
33
- end
34
-
35
- failure = result.failure
36
- case failure
37
- when ValidationError
38
- Mihari.logger.error "Failed to parse the input as a rule:"
39
- Mihari.logger.error JSON.pretty_generate(failure.errors.to_h)
40
- when StandardError
41
- raise failure
42
- else
43
- Mihari.logger.info failure
44
- end
27
+ alert = result.value!
28
+ data = Entities::Alert.represent(alert)
29
+ puts JSON.pretty_generate(data.as_json)
45
30
  end
46
31
  end
47
32
 
@@ -51,27 +36,14 @@ module Mihari
51
36
  #
52
37
  def check_diff(rule)
53
38
  force_overwrite = options["force_overwrite"] || false
54
- runner = Services::RuleRunner.new(rule, force_overwrite: force_overwrite)
55
- message = "There is a diff in the rule (#{rule.id}). Are you sure you want to overwrite the rule? (y/n)"
39
+ message = "There is a diff in the rule. Are you sure you want to overwrite the rule? (y/n)"
40
+ runner = Services::RuleRunner.new(rule)
56
41
 
57
- if runner.diff? && !force_overwrite && !yes?(message)
58
- return Failure("Stop overwriting the rule (#{rule.id})")
59
- end
42
+ exit 0 if runner.diff? && !force_overwrite && !yes?(message)
60
43
 
61
44
  Success runner
62
45
  end
63
46
 
64
- #
65
- # @param [Mihari::Alert, nil] alert_or_nil
66
- #
67
- def check_nil(alert_or_nil)
68
- if alert_or_nil.nil?
69
- Failure "There is no new artifact found"
70
- else
71
- Success alert_or_nil
72
- end
73
- end
74
-
75
47
  #
76
48
  # @param [Mihari::Services::RuleRunner] runner
77
49
  #
@@ -2,11 +2,11 @@
2
2
 
3
3
  module Mihari
4
4
  # @return [Array<String>]
5
- DEFAULT_DATA_TYPES = %w[hash ip domain url mail].freeze
5
+ DEFAULT_DATA_TYPES = Types::DataTypes.values.freeze
6
6
 
7
7
  # @return [Array<Hash>]
8
- DEFAULT_EMITTERS = %w[database misp slack the_hive].map { |name| { emitter: name } }.freeze
8
+ DEFAULT_EMITTERS = %w[database].map { |name| { emitter: name } }.freeze
9
9
 
10
10
  # @return [Array<Hash>]
11
- DEFAULT_ENRICHERS = %w[whois ipinfo shodan google_public_dns].map { |name| { enricher: name } }.freeze
11
+ DEFAULT_ENRICHERS = Mihari.enricher_to_class.keys.map { |name| { enricher: name.downcase } }.freeze
12
12
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Mihari
4
4
  module Emitters
5
- class Base
5
+ class Base < Mihari::Base
6
6
  include Dry::Monads[:result, :try]
7
7
 
8
8
  include Mixins::Configurable
@@ -14,9 +14,6 @@ module Mihari
14
14
  # @return [Mihari::Services::Rule]
15
15
  attr_reader :rule
16
16
 
17
- # @return [Hash]
18
- attr_reader :options
19
-
20
17
  #
21
18
  # @param [Array<Mihari::Artifact>] artifacts
22
19
  # @param [Mihari::Services::RuleProxy] rule
@@ -24,37 +21,10 @@ module Mihari
24
21
  # @param [Hash] **_params
25
22
  #
26
23
  def initialize(artifacts:, rule:, options: nil, **_params)
24
+ super(options: options)
25
+
27
26
  @artifacts = artifacts
28
27
  @rule = rule
29
- @options = options || {}
30
- end
31
-
32
- #
33
- # @return [Integer]
34
- #
35
- def retry_interval
36
- options[:retry_interval] || Mihari.config.retry_interval
37
- end
38
-
39
- #
40
- # @return [Boolean]
41
- #
42
- def retry_exponential_backoff
43
- options[:retry_exponential_backoff] || Mihari.config.retry_exponential_backoff
44
- end
45
-
46
- #
47
- # @return [Integer]
48
- #
49
- def retry_times
50
- options[:retry_times] || Mihari.config.retry_times
51
- end
52
-
53
- #
54
- # @return [Integer, nil]
55
- #
56
- def timeout
57
- options[:timeout]
58
28
  end
59
29
 
60
30
  # @return [Boolean]
@@ -13,7 +13,7 @@ module Mihari
13
13
  # @return [Mihari::Alert, nil]
14
14
  #
15
15
  def emit
16
- return nil if artifacts.empty?
16
+ return if artifacts.empty?
17
17
 
18
18
  tags = rule.tags.filter_map { |name| Tag.find_or_create_by(name: name) }.uniq
19
19
  taggings = tags.map { |tag| Tagging.new(tag_id: tag.id) }
@@ -2,45 +2,14 @@
2
2
 
3
3
  module Mihari
4
4
  module Enrichers
5
- class Base
5
+ class Base < Mihari::Base
6
6
  include Mixins::Configurable
7
7
  include Mixins::Retriable
8
8
 
9
9
  include Dry::Monads[:result, :try]
10
10
 
11
- # @return [Hash]
12
- attr_reader :options
13
-
14
11
  def initialize(options: nil)
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]
12
+ super(options: options)
44
13
  end
45
14
 
46
15
  def query_result(value)
@@ -38,6 +38,15 @@ module Mihari
38
38
  nil
39
39
  end
40
40
 
41
+ class << self
42
+ #
43
+ # @return [String]
44
+ #
45
+ def class_key
46
+ "google_public_dns"
47
+ end
48
+ end
49
+
41
50
  private
42
51
 
43
52
  def http
@@ -2,37 +2,31 @@
2
2
 
3
3
  module Mihari
4
4
  module Schemas
5
- AnalyzerOptions = Dry::Schema.Params do
6
- optional(:pagination_interval).value(:integer).default(Mihari.config.pagination_interval)
7
- optional(:pagination_limit).value(:integer).default(Mihari.config.pagination_limit)
8
- optional(:retry_times).value(:integer).default(Mihari.config.retry_times)
9
- optional(:retry_interval).value(:integer).default(Mihari.config.retry_interval)
10
- optional(:retry_exponential_backoff).value(:bool).default(Mihari.config.retry_exponential_backoff)
11
- optional(:ignore_error).value(:bool).default(Mihari.config.ignore_error)
12
- optional(:timeout).value(:integer)
13
- end
14
-
15
- AnalyzerWithoutAPIKey = Dry::Schema.Params do
16
- required(:analyzer).value(Types::String.enum("dnstwister"))
17
- required(:query).value(:string)
18
- optional(:options).hash(AnalyzerOptions)
19
- end
20
-
21
- AnalyzerWithAPIKey = Dry::Schema.Params do
5
+ AnalyzerAPIKeyPagination = Dry::Schema.Params do
22
6
  required(:analyzer).value(
23
7
  Types::String.enum(
24
8
  "binaryedge",
25
9
  "greynoise",
26
10
  "onyphe",
11
+ "shodan",
12
+ "urlscan",
13
+ "virustotal_intelligence",
14
+ "vt_intel"
15
+ )
16
+ )
17
+ required(:query).value(:string)
18
+ optional(:api_key).value(:string)
19
+ optional(:options).hash(AnalyzerPaginationOptions)
20
+ end
21
+
22
+ AnalyzerAPIKey = Dry::Schema.Params do
23
+ required(:analyzer).value(
24
+ Types::String.enum(
27
25
  "otx",
28
26
  "pulsedive",
29
27
  "securitytrails",
30
- "shodan",
31
28
  "st",
32
- "urlscan",
33
- "virustotal_intelligence",
34
29
  "virustotal",
35
- "vt_intel",
36
30
  "vt"
37
31
  )
38
32
  )
@@ -41,12 +35,18 @@ module Mihari
41
35
  optional(:options).hash(AnalyzerOptions)
42
36
  end
43
37
 
38
+ DNSTwister = Dry::Schema.Params do
39
+ required(:analyzer).value(Types::String.enum("dnstwister"))
40
+ required(:query).value(:string)
41
+ optional(:options).hash(AnalyzerOptions)
42
+ end
43
+
44
44
  Censys = Dry::Schema.Params do
45
45
  required(:analyzer).value(Types::String.enum("censys"))
46
46
  required(:query).value(:string)
47
47
  optional(:id).value(:string)
48
48
  optional(:secret).value(:string)
49
- optional(:options).hash(AnalyzerOptions)
49
+ optional(:options).hash(AnalyzerPaginationOptions)
50
50
  end
51
51
 
52
52
  CIRCL = Dry::Schema.Params do
@@ -69,7 +69,7 @@ module Mihari
69
69
  required(:analyzer).value(Types::String.enum("zoomeye"))
70
70
  required(:query).value(:string)
71
71
  required(:type).value(Types::String.enum("host", "web"))
72
- optional(:options).hash(AnalyzerOptions)
72
+ optional(:options).hash(AnalyzerPaginationOptions)
73
73
  end
74
74
 
75
75
  Crtsh = Dry::Schema.Params do
@@ -85,7 +85,7 @@ module Mihari
85
85
  required(:start_time).value(:date)
86
86
  required(:end_time).value(:date)
87
87
  optional(:api_key).value(:string)
88
- optional(:options).hash(AnalyzerOptions)
88
+ optional(:options).hash(AnalyzerPaginationOptions)
89
89
  end
90
90
 
91
91
  Feed = Dry::Schema.Params do
@@ -3,38 +3,31 @@
3
3
  module Mihari
4
4
  module Schemas
5
5
  module Emitters
6
- EmitterOptions = Dry::Schema.Params do
7
- optional(:retry_times).value(:integer).default(Mihari.config.retry_times)
8
- optional(:retry_interval).value(:integer).default(Mihari.config.retry_interval)
9
- optional(:retry_exponential_backoff).value(:bool).default(Mihari.config.retry_exponential_backoff)
10
- optional(:timeout).value(:integer)
11
- end
12
-
13
6
  Database = Dry::Schema.Params do
14
7
  required(:emitter).value(Types::String.enum("database"))
15
- optional(:options).hash(EmitterOptions)
8
+ optional(:options).hash(Options)
16
9
  end
17
10
 
18
11
  MISP = Dry::Schema.Params do
19
12
  required(:emitter).value(Types::String.enum("misp"))
20
13
  optional(:url).value(:string)
21
14
  optional(:api_key).value(:string)
22
- optional(:options).hash(EmitterOptions)
15
+ optional(:options).hash(Options)
23
16
  end
24
17
 
25
18
  TheHive = Dry::Schema.Params do
26
- required(:emitter).value(Types::String.enum("the_hive"))
19
+ required(:emitter).value(Types::String.enum("thehive"))
27
20
  optional(:url).value(:string)
28
21
  optional(:api_key).value(:string)
29
22
  optional(:api_version).value(Types::String.enum("v4", "v5")).default("v4")
30
- optional(:options).hash(EmitterOptions)
23
+ optional(:options).hash(Options)
31
24
  end
32
25
 
33
26
  Slack = Dry::Schema.Params do
34
27
  required(:emitter).value(Types::String.enum("slack"))
35
28
  optional(:webhook_url).value(:string)
36
29
  optional(:channel).value(:string)
37
- optional(:options).hash(EmitterOptions)
30
+ optional(:options).hash(Options)
38
31
  end
39
32
 
40
33
  Webhook = Dry::Schema.Params do
@@ -43,7 +36,7 @@ module Mihari
43
36
  optional(:method).value(Types::HTTPRequestMethods).default("POST")
44
37
  optional(:headers).value(:hash).default({})
45
38
  optional(:template).value(:string)
46
- optional(:options).hash(EmitterOptions)
39
+ optional(:options).hash(Options)
47
40
  end
48
41
  end
49
42
  end
@@ -3,32 +3,25 @@
3
3
  module Mihari
4
4
  module Schemas
5
5
  module Enrichers
6
- EnricherOptions = Dry::Schema.Params do
7
- optional(:retry_times).value(:integer).default(Mihari.config.retry_times)
8
- optional(:retry_interval).value(:integer).default(Mihari.config.retry_interval)
9
- optional(:retry_exponential_backoff).value(:bool).default(Mihari.config.retry_exponential_backoff)
10
- optional(:timeout).value(:integer)
11
- end
12
-
13
6
  IPInfo = Dry::Schema.Params do
14
7
  required(:enricher).value(Types::String.enum("ipinfo"))
15
8
  optional(:api_key).value(:string)
16
- optional(:options).hash(EnricherOptions)
9
+ optional(:options).hash(Options)
17
10
  end
18
11
 
19
12
  Whois = Dry::Schema.Params do
20
13
  required(:enricher).value(Types::String.enum("whois"))
21
- optional(:options).hash(EnricherOptions)
14
+ optional(:options).hash(Options)
22
15
  end
23
16
 
24
17
  Shodan = Dry::Schema.Params do
25
18
  required(:enricher).value(Types::String.enum("shodan"))
26
- optional(:options).hash(EnricherOptions)
19
+ optional(:options).hash(Options)
27
20
  end
28
21
 
29
22
  GooglePublicDNS = Dry::Schema.Params do
30
23
  required(:enricher).value(Types::String.enum("google_public_dns"))
31
- optional(:options).hash(EnricherOptions)
24
+ optional(:options).hash(Options)
32
25
  end
33
26
  end
34
27
  end