mihari 5.0.1 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -1
  3. data/docker/Dockerfile +1 -1
  4. data/lib/mihari/analyzers/binaryedge.rb +9 -7
  5. data/lib/mihari/analyzers/censys.rb +3 -5
  6. data/lib/mihari/analyzers/circl.rb +4 -6
  7. data/lib/mihari/analyzers/crtsh.rb +6 -7
  8. data/lib/mihari/analyzers/dnpedia.rb +3 -7
  9. data/lib/mihari/analyzers/dnstwister.rb +3 -5
  10. data/lib/mihari/analyzers/feed.rb +12 -10
  11. data/lib/mihari/analyzers/greynoise.rb +3 -5
  12. data/lib/mihari/analyzers/onyphe.rb +3 -4
  13. data/lib/mihari/analyzers/otx.rb +1 -3
  14. data/lib/mihari/analyzers/passivetotal.rb +5 -7
  15. data/lib/mihari/analyzers/pulsedive.rb +5 -7
  16. data/lib/mihari/analyzers/shodan.rb +3 -9
  17. data/lib/mihari/analyzers/urlscan.rb +7 -6
  18. data/lib/mihari/analyzers/virustotal.rb +4 -6
  19. data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -5
  20. data/lib/mihari/analyzers/zoomeye.rb +4 -10
  21. data/lib/mihari/cli/database.rb +11 -0
  22. data/lib/mihari/cli/main.rb +10 -4
  23. data/lib/mihari/cli/rule.rb +11 -0
  24. data/lib/mihari/clients/base.rb +53 -0
  25. data/lib/mihari/clients/binaryedge.rb +33 -0
  26. data/lib/mihari/clients/censys.rb +42 -0
  27. data/lib/mihari/clients/circl.rb +59 -0
  28. data/lib/mihari/clients/crtsh.rb +31 -0
  29. data/lib/mihari/clients/dnpedia.rb +64 -0
  30. data/lib/mihari/clients/dnstwister.rb +40 -0
  31. data/lib/mihari/clients/greynoise.rb +29 -0
  32. data/lib/mihari/clients/misp.rb +24 -0
  33. data/lib/mihari/clients/onyphe.rb +23 -0
  34. data/lib/mihari/clients/otx.rb +29 -0
  35. data/lib/mihari/clients/passivetotal.rb +65 -0
  36. data/lib/mihari/clients/publsedive.rb +39 -0
  37. data/lib/mihari/clients/shodan.rb +30 -0
  38. data/lib/mihari/clients/the_hive.rb +28 -0
  39. data/lib/mihari/clients/urlscan.rb +31 -0
  40. data/lib/mihari/clients/virustotal.rb +56 -0
  41. data/lib/mihari/clients/zoomeye.rb +68 -0
  42. data/lib/mihari/commands/database.rb +28 -0
  43. data/lib/mihari/commands/{initializer.rb → rule.rb} +27 -6
  44. data/lib/mihari/commands/searcher.rb +5 -0
  45. data/lib/mihari/database.rb +8 -22
  46. data/lib/mihari/emitters/misp.rb +13 -20
  47. data/lib/mihari/emitters/the_hive.rb +3 -5
  48. data/lib/mihari/emitters/webhook.rb +2 -2
  49. data/lib/mihari/feed/reader.rb +14 -11
  50. data/lib/mihari/http.rb +29 -21
  51. data/lib/mihari/mixins/database.rb +2 -0
  52. data/lib/mihari/mixins/retriable.rb +3 -1
  53. data/lib/mihari/schemas/analyzer.rb +5 -4
  54. data/lib/mihari/version.rb +1 -1
  55. data/lib/mihari.rb +21 -0
  56. data/mihari.gemspec +14 -20
  57. metadata +61 -238
  58. data/lib/mihari/analyzers/clients/otx.rb +0 -36
  59. data/lib/mihari/commands/validator.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7944fcbb2ef6b1ff7fccbe5c8158bd21a186b05e8fae70a6700256dce10adbb
4
- data.tar.gz: 36605153506952b323be6e3a7646fd4446f280943fc6c587d7885e8eec413c33
3
+ metadata.gz: e19317302956178dc4302543d81a0920018aa384595f91c69dd70110086d575a
4
+ data.tar.gz: 80d6314c2df13a4a28ec71a0d4b358e74ab0ee9778d818658a997c1fd821f062
5
5
  SHA512:
6
- metadata.gz: ba53c1fb987ffd933017ccc64a3a72adc032de81a377e34684c4927304d295d85531ad11e796abd3c17489411fcf15eedd494d7ff7a8b7d0c53fdeb511eb5a8d
7
- data.tar.gz: 6dff687f32dfef7f0cc19b76cba77a6233ebbefa9b90f522f37092468370eb5abb0e7f185d86f74077944cb0c76609b01390e7878ca494a82419ac44e59d93e5
6
+ metadata.gz: b54bffc456bc114a2a8b52e5acbcc3f30d7571124fc9431fbda209bb57910eabe7950d86c50ef750c41d5df604a5aa08c9affb25d434db8a4f53d85ba8ae4921
7
+ data.tar.gz: 4bce535d8d6d2573102b0197984854b84628a08ab37855c2a7f7fb1574b701e6b4ca816d3b23b3719d7cde0b7de89753af3b386d43af39e422c7c06b1d65448c
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
- --format documentation
1
+ --format Fuubar
2
2
  --color
3
3
  --require spec_helper
data/docker/Dockerfile CHANGED
@@ -3,7 +3,7 @@ FROM ruby:3.1.3-alpine3.17
3
3
  RUN apk --no-cache add git build-base ruby-dev sqlite-dev postgresql-dev mysql-client mysql-dev && \
4
4
  gem install pg mysql2
5
5
 
6
- ARG MIHARI_VERSION=4.11.0
6
+ ARG MIHARI_VERSION=5.1.0
7
7
 
8
8
  RUN gem install mihari -v ${MIHARI_VERSION}
9
9
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "binaryedge"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class BinaryEdge < Base
@@ -44,8 +42,8 @@ module Mihari
44
42
  # @return [Hash]
45
43
  #
46
44
  def search_with_page(query, page: 1)
47
- api.host.search(query, page: page)
48
- rescue ::BinaryEdge::Error => e
45
+ client.search(query, page: page)
46
+ rescue UnsuccessfulStatusCodeError => e
49
47
  raise RetryableError, e if e.message.include?("Request time limit exceeded")
50
48
 
51
49
  raise e
@@ -58,7 +56,7 @@ module Mihari
58
56
  #
59
57
  def search
60
58
  responses = []
61
- (1..Float::INFINITY).each do |page|
59
+ (1..500).each do |page|
62
60
  res = search_with_page(query, page: page)
63
61
  total = res["total"].to_i
64
62
 
@@ -75,8 +73,12 @@ module Mihari
75
73
  %w[binaryedge_api_key]
76
74
  end
77
75
 
78
- def api
79
- @api ||= ::BinaryEdge::API.new(api_key)
76
+ #
77
+ #
78
+ # @return [Mihari::Clients::BinaryEdge]
79
+ #
80
+ def client
81
+ @client ||= Clients::BinaryEdge.new(api_key: api_key)
80
82
  end
81
83
  end
82
84
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "censysx"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class Censys < Base
@@ -42,7 +40,7 @@ module Mihari
42
40
 
43
41
  cursor = nil
44
42
  loop do
45
- response = api.search(query, cursor: cursor)
43
+ response = client.search(query, cursor: cursor)
46
44
  response = Structs::Censys::Response.from_dynamic!(response)
47
45
 
48
46
  artifacts << response_to_artifacts(response)
@@ -106,8 +104,8 @@ module Mihari
106
104
  %w[censys_id censys_secret]
107
105
  end
108
106
 
109
- def api
110
- @api ||= ::Censys::API.new(id, secret)
107
+ def client
108
+ @client ||= Clients::Censys.new(id: id, secret: secret)
111
109
  end
112
110
 
113
111
  def id?
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "passive_circl"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class CIRCL < Base
@@ -42,8 +40,8 @@ module Mihari
42
40
  %w[circl_passive_password circl_passive_username]
43
41
  end
44
42
 
45
- def api
46
- @api ||= ::PassiveCIRCL::API.new(username: username, password: password)
43
+ def client
44
+ @client ||= Clients::CIRCL.new(username: username, password: password)
47
45
  end
48
46
 
49
47
  #
@@ -68,7 +66,7 @@ module Mihari
68
66
  # @return [Array<String>]
69
67
  #
70
68
  def passive_dns_search
71
- results = api.dns.query(@query)
69
+ results = client.dns_query(@query)
72
70
  results.filter_map do |result|
73
71
  type = result["rrtype"]
74
72
  (type == "A") ? result["rdata"] : nil
@@ -81,7 +79,7 @@ module Mihari
81
79
  # @return [Array<String>]
82
80
  #
83
81
  def passive_ssl_search
84
- result = api.ssl.cquery(@query)
82
+ result = client.ssl_cquery(@query)
85
83
  seen = result["seen"] || []
86
84
  seen.uniq
87
85
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "crtsh"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class Crtsh < Base
@@ -21,8 +19,11 @@ module Mihari
21
19
 
22
20
  private
23
21
 
24
- def api
25
- @api ||= ::Crtsh::API.new
22
+ #
23
+ # @return [Mihari::Clients::Crtsh]
24
+ #
25
+ def client
26
+ @client ||= Mihari::Clients::Crtsh.new
26
27
  end
27
28
 
28
29
  #
@@ -32,9 +33,7 @@ module Mihari
32
33
  #
33
34
  def search
34
35
  exclude = exclude_expired ? "expired" : nil
35
- api.search(query, exclude: exclude)
36
- rescue ::Crtsh::Error => _e
37
- []
36
+ client.search(query, exclude: exclude)
38
37
  end
39
38
  end
40
39
  end
@@ -1,22 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dnpedia"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class DNPedia < Base
8
6
  param :query
9
7
 
10
- option :tags, default: proc { [] }
11
-
12
8
  def artifacts
13
9
  search || []
14
10
  end
15
11
 
16
12
  private
17
13
 
18
- def api
19
- @api ||= ::DNPedia::API.new
14
+ def client
15
+ @client ||= Clients::DNPedia.new
20
16
  end
21
17
 
22
18
  #
@@ -25,7 +21,7 @@ module Mihari
25
21
  # @return [Array<Mihari::Artifact>]
26
22
  #
27
23
  def search
28
- res = api.search(query)
24
+ res = client.search(query)
29
25
  rows = res["rows"] || []
30
26
  rows.map do |row|
31
27
  data = [row["name"], row["zoneid"]].join(".")
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dnstwister"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class DNSTwister < Base
@@ -35,8 +33,8 @@ module Mihari
35
33
  type == "domain"
36
34
  end
37
35
 
38
- def api
39
- @api ||= ::DNSTwister::API.new
36
+ def client
37
+ @client ||= Clients::DNSTwister.new
40
38
  end
41
39
 
42
40
  #
@@ -61,7 +59,7 @@ module Mihari
61
59
  def search
62
60
  raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
63
61
 
64
- res = api.fuzz(query)
62
+ res = client.fuzz(query)
65
63
  fuzzy_domains = res["fuzzy_domains"] || []
66
64
  domains = fuzzy_domains.map { |domain| domain["domain"] }
67
65
  Parallel.map(domains) do |domain|
@@ -8,26 +8,28 @@ module Mihari
8
8
  class Feed < Base
9
9
  param :query
10
10
 
11
- option :http_request_method, default: proc { "GET" }
12
- option :http_request_headers, default: proc { {} }
13
- option :http_request_payload, default: proc { {} }
14
- option :http_request_payload_type, default: proc {}
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 {}
15
16
 
16
17
  option :selector, default: proc { "" }
17
18
 
18
19
  def artifacts
19
- Mihari::Feed::Parser.new(data).parse selector
20
+ Mihari::Feed::Parser.new(results).parse selector
20
21
  end
21
22
 
22
23
  private
23
24
 
24
- def data
25
+ def results
25
26
  reader = Mihari::Feed::Reader.new(
26
27
  query,
27
- http_request_method: http_request_method,
28
- http_request_headers: http_request_headers,
29
- http_request_payload: http_request_payload,
30
- http_request_payload_type: http_request_payload_type
28
+ method: method,
29
+ headers: headers,
30
+ params: params,
31
+ json: json,
32
+ data: data
31
33
  )
32
34
  reader.read
33
35
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "greynoise"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class GreyNoise < Base
@@ -31,8 +29,8 @@ module Mihari
31
29
  %w[greynoise_api_key]
32
30
  end
33
31
 
34
- def api
35
- @api ||= ::GreyNoise::API.new(key: api_key)
32
+ def client
33
+ @client ||= Clients::GreyNoise.new(api_key: api_key)
36
34
  end
37
35
 
38
36
  #
@@ -41,7 +39,7 @@ module Mihari
41
39
  # @return [Hash]
42
40
  #
43
41
  def search
44
- api.experimental.gnql(query, size: PAGE_SIZE)
42
+ client.gnql_search(query, size: PAGE_SIZE)
45
43
  end
46
44
 
47
45
  #
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "onyphe"
4
3
  require "normalize_country"
5
4
 
6
5
  module Mihari
@@ -37,8 +36,8 @@ module Mihari
37
36
  %w[onyphe_api_key]
38
37
  end
39
38
 
40
- def api
41
- @api ||= ::Onyphe::API.new(api_key)
39
+ def client
40
+ @client ||= Clients::Onyphe.new(api_key: api_key)
42
41
  end
43
42
 
44
43
  #
@@ -50,7 +49,7 @@ module Mihari
50
49
  # @return [Structs::Onyphe::Response]
51
50
  #
52
51
  def search_with_page(query, page: 1)
53
- res = api.simple.datascan(query, page: page)
52
+ res = client.datascan(query, page: page)
54
53
  Structs::Onyphe::Response.from_dynamic!(res)
55
54
  end
56
55
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "mihari/analyzers/clients/otx"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class OTX < Base
@@ -35,7 +33,7 @@ module Mihari
35
33
  end
36
34
 
37
35
  def client
38
- @client ||= Mihari::Analyzers::Clients::OTX.new(api_key)
36
+ @client ||= Mihari::Clients::OTX.new(api_key: api_key)
39
37
  end
40
38
 
41
39
  #
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "passivetotal"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class PassiveTotal < Base
@@ -42,8 +40,8 @@ module Mihari
42
40
  %w[passivetotal_username passivetotal_api_key]
43
41
  end
44
42
 
45
- def api
46
- @api ||= ::PassiveTotal::API.new(username: username, api_key: api_key)
43
+ def client
44
+ @client ||= Clients::PassiveTotal.new(username: username, api_key: api_key)
47
45
  end
48
46
 
49
47
  #
@@ -79,7 +77,7 @@ module Mihari
79
77
  # @return [Array<String>]
80
78
  #
81
79
  def passive_dns_search
82
- res = api.dns.passive_unique(query)
80
+ res = client.passive_dns_search(query)
83
81
  res["results"] || []
84
82
  end
85
83
 
@@ -89,7 +87,7 @@ module Mihari
89
87
  # @return [Array<Mihari::Artifact>]
90
88
  #
91
89
  def reverse_whois_search
92
- res = api.whois.search(query: query, field: "email")
90
+ res = client.reverse_whois_search(query: query, field: "email")
93
91
  results = res["results"] || []
94
92
  results.map do |result|
95
93
  data = result["domain"]
@@ -103,7 +101,7 @@ module Mihari
103
101
  # @return [Array<Mihari::Artifact>]
104
102
  #
105
103
  def ssl_search
106
- res = api.ssl.history(query)
104
+ res = client.ssl_search(query)
107
105
  results = res["results"] || []
108
106
  results.map do |result|
109
107
  data = result["ipAddresses"]
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pulsedive"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class Pulsedive < Base
@@ -34,8 +32,8 @@ module Mihari
34
32
  %w[pulsedive_api_key]
35
33
  end
36
34
 
37
- def api
38
- @api ||= ::Pulsedive::API.new(api_key)
35
+ def client
36
+ @client ||= Clients::PulseDive.new(api_key: api_key)
39
37
  end
40
38
 
41
39
  #
@@ -55,12 +53,12 @@ module Mihari
55
53
  def search
56
54
  raise InvalidInputError, "#{query}(type: #{type || "unknown"}) is not supported." unless valid_type?
57
55
 
58
- indicator = api.indicator.get_by_value(query)
56
+ indicator = client.get_indicator(query)
59
57
  iid = indicator["iid"]
60
58
 
61
- properties = api.indicator.get_properties_by_id(iid)
59
+ properties = client.get_properties(iid)
62
60
  (properties["dns"] || []).filter_map do |property|
63
- if ["A", "PTR"].include?(property["name"])
61
+ if %w[A PTR].include?(property["name"])
64
62
  nil
65
63
  else
66
64
  data = property["value"]
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "shodan"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class Shodan < Base
@@ -37,8 +35,8 @@ module Mihari
37
35
  %w[shodan_api_key]
38
36
  end
39
37
 
40
- def api
41
- @api ||= ::Shodan::API.new(key: api_key)
38
+ def client
39
+ @client ||= Clients::Shodan.new(api_key: api_key)
42
40
  end
43
41
 
44
42
  #
@@ -50,11 +48,7 @@ module Mihari
50
48
  # @return [Hash]
51
49
  #
52
50
  def search_with_page(query, page: 1)
53
- api.host.search(query, page: page)
54
- rescue ::Shodan::Error => e
55
- raise RetryableError, e if e.message.include?("request timed out")
56
-
57
- raise e
51
+ client.search(query, page: page)
58
52
  end
59
53
 
60
54
  #
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "urlscan"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class Urlscan < Base
@@ -20,7 +18,10 @@ module Mihari
20
18
  def initialize(*args, **kwargs)
21
19
  super
22
20
 
23
- raise InvalidInputError, "allowed_data_types should be any of url, domain and ip." unless valid_alllowed_data_types?
21
+ unless valid_alllowed_data_types?
22
+ raise InvalidInputError,
23
+ "allowed_data_types should be any of url, domain and ip."
24
+ end
24
25
 
25
26
  @api_key = kwargs[:api_key] || Mihari.config.urlscan_api_key
26
27
  end
@@ -44,8 +45,8 @@ module Mihari
44
45
  %w[urlscan_api_key]
45
46
  end
46
47
 
47
- def api
48
- @api ||= ::UrlScan::API.new(api_key)
48
+ def client
49
+ @client ||= Clients::UrlScan.new(api_key: api_key)
49
50
  end
50
51
 
51
52
  #
@@ -54,7 +55,7 @@ module Mihari
54
55
  # @return [Structs::Urlscan::Response]
55
56
  #
56
57
  def search_with_search_after(search_after: nil)
57
- res = api.search(query, size: SIZE, search_after: search_after)
58
+ res = client.search(query, size: SIZE, search_after: search_after)
58
59
  Structs::Urlscan::Response.from_dynamic! res
59
60
  end
60
61
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "virustotal"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class VirusTotal < Base
@@ -33,8 +31,8 @@ module Mihari
33
31
  %w[virustotal_api_key]
34
32
  end
35
33
 
36
- def api
37
- @api = ::VirusTotal::API.new(key: api_key)
34
+ def client
35
+ @client = Clients::VirusTotal.new(api_key: api_key)
38
36
  end
39
37
 
40
38
  #
@@ -68,7 +66,7 @@ module Mihari
68
66
  # @return [Array<Mihari::Artifact>]
69
67
  #
70
68
  def domain_search
71
- res = api.domain.resolutions(query)
69
+ res = client.domain_search(query)
72
70
 
73
71
  data = res["data"] || []
74
72
  data.filter_map do |item|
@@ -83,7 +81,7 @@ module Mihari
83
81
  # @return [Array<Mihari::Artifact>]
84
82
  #
85
83
  def ip_search
86
- res = api.ip_address.resolutions(query)
84
+ res = client.ip_search(query)
87
85
 
88
86
  data = res["data"] || []
89
87
  data.filter_map do |item|
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "virustotal"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class VirusTotalIntelligence < Base
@@ -40,8 +38,8 @@ module Mihari
40
38
  #
41
39
  # @return [::VirusTotal::API]
42
40
  #
43
- def api
44
- @api = ::VirusTotal::API.new(key: api_key)
41
+ def client
42
+ @client = Clients::VirusTotal.new(api_key: api_key)
45
43
  end
46
44
 
47
45
  #
@@ -54,7 +52,8 @@ module Mihari
54
52
  responses = []
55
53
 
56
54
  loop do
57
- response = Structs::VirusTotalIntelligence::Response.from_dynamic!(api.intelligence.search(query, cursor: cursor))
55
+ response = Structs::VirusTotalIntelligence::Response.from_dynamic!(client.intel_search(query,
56
+ cursor: cursor))
58
57
  responses << response
59
58
 
60
59
  break if response.meta.cursor.nil?
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "zoomeye"
4
-
5
3
  module Mihari
6
4
  module Analyzers
7
5
  class ZoomEye < Base
@@ -48,8 +46,8 @@ module Mihari
48
46
  %w[zoomeye_api_key]
49
47
  end
50
48
 
51
- def api
52
- @api ||= ::ZoomEye::API.new(api_key: api_key)
49
+ def client
50
+ @client ||= Clients::ZoomEye.new(api_key: api_key)
53
51
  end
54
52
 
55
53
  #
@@ -83,9 +81,7 @@ module Mihari
83
81
  # @return [Hash, nil]
84
82
  #
85
83
  def _host_search(query, page: 1)
86
- api.host.search(query, page: page)
87
- rescue ::ZoomEye::Error => _e
88
- nil
84
+ client.host_search(query, page: page)
89
85
  end
90
86
 
91
87
  #
@@ -118,9 +114,7 @@ module Mihari
118
114
  # @return [Hash, nil]
119
115
  #
120
116
  def _web_search(query, page: 1)
121
- api.web.search(query, page: page)
122
- rescue ::ZoomEye::Error => _e
123
- nil
117
+ client.web_search(query, page: page)
124
118
  end
125
119
 
126
120
  #
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mihari/commands/database"
4
+
5
+ module Mihari
6
+ module CLI
7
+ class Database < Base
8
+ include Mihari::Commands::Database
9
+ end
10
+ end
11
+ end
@@ -3,23 +3,29 @@
3
3
  require "thor"
4
4
 
5
5
  # Commands
6
- require "mihari/commands/initializer"
7
6
  require "mihari/commands/searcher"
8
- require "mihari/commands/validator"
9
7
  require "mihari/commands/version"
10
8
  require "mihari/commands/web"
9
+ require "mihari/commands/database"
11
10
 
12
11
  # CLIs
13
12
  require "mihari/cli/base"
14
13
 
14
+ require "mihari/cli/database"
15
+ require "mihari/cli/rule"
16
+
15
17
  module Mihari
16
18
  module CLI
17
19
  class Main < Base
18
20
  include Mihari::Commands::Searcher
19
21
  include Mihari::Commands::Version
20
22
  include Mihari::Commands::Web
21
- include Mihari::Commands::Validator
22
- include Mihari::Commands::Initializer
23
+
24
+ desc "db", "Sub commands for DB"
25
+ subcommand "db", Database
26
+
27
+ desc "rule", "Sub commands for rule"
28
+ subcommand "rule", Rule
23
29
  end
24
30
  end
25
31
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mihari/commands/rule"
4
+
5
+ module Mihari
6
+ module CLI
7
+ class Rule < Base
8
+ include Mihari::Commands::Rule
9
+ end
10
+ end
11
+ end