mihari 5.0.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41784cbe3811a8f5f2a6a4de663ceaa03e2635c329c455b523e5fc55fda0c9e7
4
- data.tar.gz: '052987fcb8805a8f71a0716d5e0970b0c4c7451059dded4b5149679ccda6c999'
3
+ metadata.gz: 9481229c15756515053bbc91453db90d914e40e5f536d0b5aaad0f2b8fff5868
4
+ data.tar.gz: 1ea1f9caa3dbb1f945f4a3ba9f9af17c80c786594692de1564ca4f76692fa628
5
5
  SHA512:
6
- metadata.gz: f16447e83adb4630baf9587eecea0dbb6f580de23894d70fa2c1729483faa6dc1c86fe5de2bd782100f8cba89e2a50e7ce2f0ab675de822fe5fb767fb2c6f45f
7
- data.tar.gz: af70fcc510ed4fd6a434481a8372c56d20a54b605ee0b49425a1315531d2261db6df9588f1961ba34796728ff40f0ce188ad58e6c542f4c3644a8c8251b37eb5
6
+ metadata.gz: f13bb894b69d4c92b03afc30fcce1be95ba1af1b0cb963c553a328fb85f771c852ee5526af751a098dd4f1b69c60592f021a0e3ee7e40004856d1d4eabc53aba
7
+ data.tar.gz: 751ad7fc17f2db38961e835f8c9b2a325cbf82692df65ef29c638bcf3eec9cbc17905a39bcbcf5a53bcf477adbf6080a23aa40702b3fb5a55727038eefe9b09d
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
 
@@ -9,7 +9,6 @@ module Mihari
9
9
 
10
10
  include Mixins::AutonomousSystem
11
11
  include Mixins::Configurable
12
- include Mixins::Database
13
12
  include Mixins::Retriable
14
13
 
15
14
  # @return [Mihari::Structs::Rule, nil]
@@ -42,16 +41,14 @@ module Mihari
42
41
  raise ConfigurationError, "#{class_name} is not configured correctly"
43
42
  end
44
43
 
45
- with_db_connection do
46
- set_enriched_artifacts
44
+ set_enriched_artifacts
47
45
 
48
- responses = Parallel.map(valid_emitters) do |emitter|
49
- run_emitter emitter
50
- end
51
-
52
- # returns Mihari::Alert created by the database emitter
53
- responses.find { |res| res.is_a?(Mihari::Alert) }
46
+ responses = Parallel.map(valid_emitters) do |emitter|
47
+ run_emitter emitter
54
48
  end
49
+
50
+ # returns Mihari::Alert created by the database emitter
51
+ responses.find { |res| res.is_a?(Mihari::Alert) }
55
52
  end
56
53
 
57
54
  #
@@ -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
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mihari
4
+ module Commands
5
+ module Database
6
+ include Mixins::Database
7
+
8
+ def self.included(thor)
9
+ thor.class_eval do
10
+ desc "migrate", "Migrate DB schemas"
11
+ method_option :verbose, type: :boolean, default: true
12
+ #
13
+ # @param [String] direction
14
+ #
15
+ #
16
+ def migrate(direction = "up")
17
+ verbose = options["verbose"]
18
+ ActiveRecord::Migration.verbose = verbose
19
+
20
+ with_db_connection do
21
+ Mihari::Database.migrate(direction.to_sym)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -4,20 +4,41 @@ require "pathname"
4
4
 
5
5
  module Mihari
6
6
  module Commands
7
- module Initializer
7
+ module Rule
8
8
  def self.included(thor)
9
9
  thor.class_eval do
10
- desc "init", "Initialize a new rule"
11
- method_option :path, type: :string, default: "./rule.yml"
12
- def init
13
- path = options["path"]
10
+ desc "validate [PATH]", "Validate a rule file"
11
+ #
12
+ # Validate format of a rule
13
+ #
14
+ # @param [String] path
15
+ #
16
+ def validate(path)
17
+ rule = Structs::Rule.from_path_or_id(path)
14
18
 
19
+ begin
20
+ rule.validate!
21
+ Mihari.logger.info "Valid format. The input is parsed as the following:"
22
+ Mihari.logger.info rule.data.to_yaml
23
+ rescue RuleValidationError
24
+ nil
25
+ end
26
+ end
27
+
28
+ desc "init [PATH]", "Initialize a new rule file"
29
+ #
30
+ # Initialize a new rule file
31
+ #
32
+ # @param [String] path
33
+ #
34
+ #
35
+ def init(path = "./rule.yml")
15
36
  warning = "#{path} exists. Do you want to overwrite it? (y/n)"
16
37
  return if Pathname(path).exist? && !(yes? warning)
17
38
 
18
39
  initialize_rule path
19
40
 
20
- Mihari.logger.info "A new rule is initialized as #{path}."
41
+ Mihari.logger.info "A new rule is initialized: #{path}."
21
42
  end
22
43
 
23
44
  no_commands do
@@ -9,39 +9,49 @@ module Mihari
9
9
  def self.included(thor)
10
10
  thor.class_eval do
11
11
  desc "search [PATH]", "Search by a rule"
12
- method_option :yes, type: :boolean, aliases: "-y", desc: "yes to overwrite the rule in the database"
12
+ method_option :force_overwrite, type: :boolean, aliases: "-f", desc: "Force an overwrite the rule"
13
+ #
14
+ # Search by a rule
15
+ #
16
+ # @param [String] path_or_id
17
+ #
13
18
  def search(path_or_id)
14
- rule = Structs::Rule.from_path_or_id path_or_id
19
+ with_db_connection do
20
+ rule = Structs::Rule.from_path_or_id path_or_id
15
21
 
16
- # validate
17
- begin
18
- rule.validate!
19
- rescue RuleValidationError
20
- return
21
- end
22
+ # validate
23
+ begin
24
+ rule.validate!
25
+ rescue RuleValidationError
26
+ return
27
+ end
28
+
29
+ force_overwrite = options["force_overwrite"] || false
30
+
31
+ begin
32
+ rule_model = Mihari::Rule.find(rule.id)
33
+ has_change = rule_model.data != rule.data.deep_stringify_keys
34
+ has_change_and_not_force_overwrite = has_change & !force_overwrite
22
35
 
23
- # check update
24
- yes = options["yes"] || false
25
- unless yes
26
- with_db_connection do
27
- next if Mihari::Rule.find(rule.id).data == rule.data.deep_stringify_keys
28
- unless yes?("This operation will overwrite the rule in the database (Rule ID: #{rule.id}). Are you sure you want to update the rule? (y/n)")
36
+ if has_change_and_not_force_overwrite && !yes?("This operation will overwrite the rule in the database (Rule ID: #{rule.id}). Are you sure you want to update the rule? (y/n)")
29
37
  return
30
38
  end
39
+
40
+ # update the rule
41
+ rule.model.save
31
42
  rescue ActiveRecord::RecordNotFound
32
- next
43
+ # create a new rule
44
+ rule.model.save
33
45
  end
34
- end
35
- # update rule model
36
- rule.model.save
37
-
38
- with_error_notification do
39
- alert = rule.analyzer.run
40
- if alert
41
- data = Mihari::Entities::Alert.represent(alert)
42
- puts JSON.pretty_generate(data.as_json)
43
- else
44
- Mihari.logger.info "There is no new alert created in the database"
46
+
47
+ with_error_notification do
48
+ alert = rule.analyzer.run
49
+ if alert
50
+ data = Mihari::Entities::Alert.represent(alert)
51
+ puts JSON.pretty_generate(data.as_json)
52
+ else
53
+ Mihari.logger.info "There is no new alert created in the database"
54
+ end
45
55
  end
46
56
  end
47
57
  end
@@ -9,10 +9,6 @@ def env
9
9
  ENV["APP_ENV"] || ENV["RACK_ENV"]
10
10
  end
11
11
 
12
- def test_env?
13
- env == "test"
14
- end
15
-
16
12
  def development_env?
17
13
  env == "development"
18
14
  end
@@ -121,22 +117,24 @@ def adapter
121
117
  "sqlite3"
122
118
  end
123
119
 
120
+ #
121
+ # @return [Array<ActiveRecord::Migration>] schemas
122
+ #
123
+ def schemas
124
+ [V5Schema]
125
+ end
126
+
124
127
  module Mihari
125
128
  class Database
126
129
  class << self
127
- include Memist::Memoizable
128
-
129
130
  #
130
131
  # DB migraration
131
132
  #
132
133
  # @param [Symbol] direction
133
134
  #
134
135
  def migrate(direction)
135
- ActiveRecord::Migration.verbose = false
136
-
137
- [V5Schema].each { |schema| schema.migrate direction }
136
+ schemas.each { |schema| schema.migrate direction }
138
137
  end
139
- memoize :migrate unless test_env?
140
138
 
141
139
  #
142
140
  # Establish DB connection
@@ -153,10 +151,7 @@ module Mihari
153
151
  database: Mihari.config.database_url.path[1..]
154
152
  )
155
153
  end
156
-
157
154
  ActiveRecord::Base.logger = Logger.new($stdout) if development_env?
158
-
159
- migrate :up
160
155
  rescue StandardError => e
161
156
  Mihari.logger.error e
162
157
  end
@@ -169,15 +164,6 @@ module Mihari
169
164
 
170
165
  ActiveRecord::Base.clear_active_connections!
171
166
  end
172
-
173
- #
174
- # Destory DB
175
- #
176
- def destroy!
177
- return unless ActiveRecord::Base.connected?
178
-
179
- migrate :down
180
- end
181
167
  end
182
168
  end
183
169
  end
@@ -6,6 +6,8 @@ module Mihari
6
6
  def with_db_connection
7
7
  Mihari::Database.connect
8
8
  yield
9
+ rescue ActiveRecord::StatementInvalid
10
+ Mihari.logger.error("You haven't finished the DB migration! Please run 'mihari db migrate'.")
9
11
  ensure
10
12
  Mihari::Database.close
11
13
  end
@@ -164,8 +164,6 @@ module Mihari
164
164
  end
165
165
 
166
166
  class << self
167
- include Mixins::Database
168
-
169
167
  #
170
168
  # Load rule from YAML string
171
169
  #
@@ -209,11 +207,9 @@ module Mihari
209
207
  # @return [Mihari::Structs::Rule, nil]
210
208
  #
211
209
  def from_id(id)
212
- with_db_connection do
213
- return nil unless Mihari::Rule.exists?(id)
210
+ return nil unless Mihari::Rule.exists?(id)
214
211
 
215
- Structs::Rule.from_model Mihari::Rule.find(id)
216
- end
212
+ Structs::Rule.from_model Mihari::Rule.find(id)
217
213
  end
218
214
 
219
215
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "5.0.0"
4
+ VERSION = "5.1.0"
5
5
  end
data/mihari.gemspec CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency "bundler", "~> 2.4"
31
31
  spec.add_development_dependency "coveralls_reborn", "~> 0.27"
32
32
  spec.add_development_dependency "fakefs", "~> 2.4"
33
+ spec.add_development_dependency "fuubar", "~> 2.5"
33
34
  spec.add_development_dependency "mysql2", "~> 0.5"
34
35
  spec.add_development_dependency "overcommit", "~> 0.60"
35
36
  spec.add_development_dependency "pg", "~> 1.4"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mihari
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manabu Niseki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-19 00:00:00.000000000 Z
11
+ date: 2023-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: fuubar
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.5'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: mysql2
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -1066,10 +1080,12 @@ files:
1066
1080
  - lib/mihari/analyzers/virustotal_intelligence.rb
1067
1081
  - lib/mihari/analyzers/zoomeye.rb
1068
1082
  - lib/mihari/cli/base.rb
1083
+ - lib/mihari/cli/database.rb
1069
1084
  - lib/mihari/cli/main.rb
1070
- - lib/mihari/commands/initializer.rb
1085
+ - lib/mihari/cli/rule.rb
1086
+ - lib/mihari/commands/database.rb
1087
+ - lib/mihari/commands/rule.rb
1071
1088
  - lib/mihari/commands/searcher.rb
1072
- - lib/mihari/commands/validator.rb
1073
1089
  - lib/mihari/commands/version.rb
1074
1090
  - lib/mihari/commands/web.rb
1075
1091
  - lib/mihari/constants.rb
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Mihari
4
- module Commands
5
- module Validator
6
- def self.included(thor)
7
- thor.class_eval do
8
- desc "validate [PATH]", "Validate a rule file"
9
- #
10
- # Validate format of a rule
11
- #
12
- # @param [String] path
13
- #
14
- # @return [nil]
15
- #
16
- def validate(path)
17
- rule = Structs::Rule.from_path_or_id(path)
18
-
19
- begin
20
- rule.validate!
21
- Mihari.logger.info "Valid format. The input is parsed as the following:"
22
- Mihari.logger.info rule.data.to_yaml
23
- rescue RuleValidationError
24
- nil
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end