mihari 7.0.5 → 7.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: aca048c797a73db1c57f0a5ad5f29066fbfba69451c71df1a26c3ea57853a1e3
4
- data.tar.gz: 5ce2d298f325cc9d0ae50a98a6c18a64ec11cc06386504535c8ca647c7c68ad0
3
+ metadata.gz: 6930da0e95068ca8e30d1f226be5692e85375f796b7246cafdd2bec566d00ff7
4
+ data.tar.gz: 2bf34b1231bffcd88d402ffda335960ad929b1de91cd51b257c9c24f7b2fc16f
5
5
  SHA512:
6
- metadata.gz: ac1d6ab49351a2c9c60e703a5fe5fe0f94c84c4294271f297d529a781d3a87a37b515d090a78676bcaf3da225f03617f8900966d108e31557e86319a2407b00b
7
- data.tar.gz: f5aad0f8648783f4d3c3cc42a087f646358e5e93586cb394a2644e8f6c32a296b3668ea7758348c0dd55d4868527b4aa6a3d774ee113d5a4a14c39ae3ecd2857
6
+ metadata.gz: fd515cdbde67d10c3fcae14c8e45a7929a34931701be176c9f9a294d3db310f522a3e186aefe548d6f119c5c8552723114da4ee6f790dbbe0391138dca9cc00e
7
+ data.tar.gz: 5f4a3e1049ad55af018cf9ed2186dda49bd18517d37bc84cad6e6f60b10589834ac3bd1f09333e7f9773fab43442400c097c1063f1c304d5be5eb8991af7ec77
@@ -43,6 +43,9 @@ module Mihari
43
43
  rescue StandardError => e
44
44
  error = unwrap_error(e)
45
45
 
46
+ # Raise error if it's a Thor::Error to follow Thor's manner
47
+ raise error if error.is_a?(Thor::Error)
48
+ # Raise error if debug is set as true
46
49
  raise error if options["debug"]
47
50
 
48
51
  data = Entities::ErrorMessage.represent(
@@ -12,6 +12,20 @@ module Mihari
12
12
  thor.class_eval do
13
13
  include Concerns::DatabaseConnectable
14
14
 
15
+ no_commands do
16
+ #
17
+ # @param [String] q
18
+ # @param [Integer] page
19
+ # @param [Integer] limit
20
+ #
21
+ # @return [Mihari::Services::ResultValue]
22
+ #
23
+ def _search(q, page: 1, limit: 10)
24
+ filter = Structs::Filters::Search.new(q: q, page: page, limit: limit)
25
+ Services::AlertSearcher.result(filter).value!
26
+ end
27
+ end
28
+
15
29
  desc "create [PATH]", "Create an alert"
16
30
  around :with_db_connection
17
31
  #
@@ -40,8 +54,7 @@ module Mihari
40
54
  # @param [String] q
41
55
  #
42
56
  def list(q = "")
43
- filter = Structs::Filters::Search.new(q: q, page: options["page"], limit: options["limit"])
44
- value = Services::AlertSearcher.result(filter).value!
57
+ value = _search(q, page: options["page"], limit: options["limit"])
45
58
  data = Entities::AlertsWithPagination.represent(
46
59
  results: value.results,
47
60
  total: value.total,
@@ -51,6 +64,28 @@ module Mihari
51
64
  puts JSON.pretty_generate(data.as_json)
52
65
  end
53
66
 
67
+ desc "list-transform QUERY", "List/search alerts with transformation"
68
+ around :with_db_connection
69
+ method_option :template, type: :string, required: true, aliases: "-t",
70
+ description: "Jbuilder template itself or a path to a template file"
71
+ method_option :page, type: :numeric, default: 1
72
+ method_option :limit, type: :numeric, default: 10
73
+ #
74
+ # @param [String] q
75
+ #
76
+ def list_transform(q = "")
77
+ value = _search(q, page: options["page"], limit: options["limit"])
78
+ puts Services::JbuilderRenderer.call(
79
+ options["template"],
80
+ {
81
+ results: value.results,
82
+ total: value.total,
83
+ current_page: value.filter[:page].to_i,
84
+ page_size: value.filter[:limit].to_i
85
+ }
86
+ )
87
+ end
88
+
54
89
  desc "get [ID]", "Get an alert"
55
90
  around :with_db_connection
56
91
  #
@@ -11,6 +11,20 @@ module Mihari
11
11
  thor.class_eval do
12
12
  include Concerns::DatabaseConnectable
13
13
 
14
+ no_commands do
15
+ #
16
+ # @param [String] q
17
+ # @param [Integer] page
18
+ # @param [Integer] limit
19
+ #
20
+ # @return [Mihari::Services::ResultValue]
21
+ #
22
+ def _search(q, page: 1, limit: 10)
23
+ filter = Structs::Filters::Search.new(q: q, page: page, limit: limit)
24
+ Services::ArtifactSearcher.result(filter).value!
25
+ end
26
+ end
27
+
14
28
  desc "list [QUERY]", "List/search artifacts"
15
29
  around :with_db_connection
16
30
  method_option :page, type: :numeric, default: 1
@@ -19,8 +33,7 @@ module Mihari
19
33
  # @param [String] q
20
34
  #
21
35
  def list(q = "")
22
- filter = Structs::Filters::Search.new(q: q, page: options["page"], limit: options["limit"])
23
- value = Services::ArtifactSearcher.result(filter).value!
36
+ value = _search(q, page: options["page"], limit: options["limit"])
24
37
  data = Entities::ArtifactsWithPagination.represent(
25
38
  results: value.results,
26
39
  total: value.total,
@@ -30,6 +43,28 @@ module Mihari
30
43
  puts JSON.pretty_generate(data.as_json)
31
44
  end
32
45
 
46
+ desc "list-transform QUERY", "List/search artifacts with transformation"
47
+ around :with_db_connection
48
+ method_option :template, type: :string, required: true, aliases: "-t",
49
+ description: "Jbuilder template itself or a path to a template file"
50
+ method_option :page, type: :numeric, default: 1
51
+ method_option :limit, type: :numeric, default: 10
52
+ #
53
+ # @param [String] q
54
+ #
55
+ def list_transform(q = "")
56
+ value = _search(q, page: options["page"], limit: options["limit"])
57
+ puts Services::JbuilderRenderer.call(
58
+ options["template"],
59
+ {
60
+ results: value.results,
61
+ total: value.total,
62
+ current_page: value.filter[:page].to_i,
63
+ page_size: value.filter[:limit].to_i
64
+ }
65
+ )
66
+ end
67
+
33
68
  desc "get [ID]", "Get an artifact"
34
69
  around :with_db_connection
35
70
  #
@@ -9,7 +9,7 @@ module Mihari
9
9
  class << self
10
10
  def included(thor)
11
11
  thor.class_eval do
12
- desc "list", "List config"
12
+ desc "list", "List configs"
13
13
  def list
14
14
  configs = Services::ConfigSearcher.call
15
15
  data = configs.map { |config| Entities::Config.represent(config) }
@@ -12,6 +12,20 @@ module Mihari
12
12
  thor.class_eval do
13
13
  include Concerns::DatabaseConnectable
14
14
 
15
+ no_commands do
16
+ #
17
+ # @param [String] q
18
+ # @param [Integer] page
19
+ # @param [Integer] limit
20
+ #
21
+ # @return [Mihari::Services::ResultValue]
22
+ #
23
+ def _search(q, page: 1, limit: 10)
24
+ filter = Structs::Filters::Search.new(q: q, page: page, limit: limit)
25
+ Services::RuleSearcher.result(filter).value!
26
+ end
27
+ end
28
+
15
29
  desc "validate [PATH]", "Validate a rule file"
16
30
  #
17
31
  # Validate format of a rule
@@ -44,8 +58,7 @@ module Mihari
44
58
  # @param [String] q
45
59
  #
46
60
  def list(q = "")
47
- filter = Structs::Filters::Search.new(q: q, page: options["page"], limit: options["limit"])
48
- value = Services::RuleSearcher.result(filter).value!
61
+ value = _search(q, page: options["page"], limit: options["limit"])
49
62
  data = Entities::RulesWithPagination.represent(
50
63
  results: value.results,
51
64
  total: value.total,
@@ -55,6 +68,28 @@ module Mihari
55
68
  puts JSON.pretty_generate(data.as_json)
56
69
  end
57
70
 
71
+ desc "list-transform QUERY", "List/search rules with transformation"
72
+ around :with_db_connection
73
+ method_option :template, type: :string, required: true, aliases: "-t",
74
+ description: "Jbuilder template itself or a path to a template file"
75
+ method_option :page, type: :numeric, default: 1
76
+ method_option :limit, type: :numeric, default: 10
77
+ #
78
+ # @param [String] q
79
+ #
80
+ def list_transform(q = "")
81
+ value = _search(q, page: options["page"], limit: options["limit"])
82
+ puts Services::JbuilderRenderer.call(
83
+ options["template"],
84
+ {
85
+ results: value.results,
86
+ total: value.total,
87
+ current_page: value.filter[:page].to_i,
88
+ page_size: value.filter[:limit].to_i
89
+ }
90
+ )
91
+ end
92
+
58
93
  desc "get [ID]", "Get a rule"
59
94
  around :with_db_connection
60
95
  def get(id)
@@ -11,6 +11,20 @@ module Mihari
11
11
  thor.class_eval do
12
12
  include Concerns::DatabaseConnectable
13
13
 
14
+ no_commands do
15
+ #
16
+ # @param [String] q
17
+ # @param [Integer] page
18
+ # @param [Integer] limit
19
+ #
20
+ # @return [Mihari::Services::ResultValue]
21
+ #
22
+ def _search(q, page: 1, limit: 10)
23
+ filter = Structs::Filters::Search.new(q: q, page: page, limit: limit)
24
+ Services::TagSearcher.result(filter).value!
25
+ end
26
+ end
27
+
14
28
  desc "list", "List/search tags"
15
29
  around :with_db_connection
16
30
  method_option :page, type: :numeric, default: 1
@@ -19,8 +33,7 @@ module Mihari
19
33
  # @param [String] q
20
34
  #
21
35
  def list(q = "")
22
- filter = Structs::Filters::Search.new(q: q, page: options["page"], limit: options["limit"])
23
- value = Services::TagSearcher.result(filter).value!
36
+ value = _search(q, page: options["page"], limit: options["limit"])
24
37
  data = Entities::TagsWithPagination.represent(
25
38
  results: value.results,
26
39
  total: value.total,
@@ -30,6 +43,28 @@ module Mihari
30
43
  puts JSON.pretty_generate(data.as_json)
31
44
  end
32
45
 
46
+ desc "list-transform QUERY", "List/search tags with transformation"
47
+ around :with_db_connection
48
+ method_option :template, type: :string, required: true, aliases: "-t",
49
+ description: "Jbuilder template itself or a path to a template file"
50
+ method_option :page, type: :numeric, default: 1
51
+ method_option :limit, type: :numeric, default: 10
52
+ #
53
+ # @param [String] q
54
+ #
55
+ def list_transform(q = "")
56
+ value = _search(q, page: options["page"], limit: options["limit"])
57
+ puts Services::JbuilderRenderer.call(
58
+ options["template"],
59
+ {
60
+ results: value.results,
61
+ total: value.total,
62
+ current_page: value.filter[:page].to_i,
63
+ page_size: value.filter[:limit].to_i
64
+ }
65
+ )
66
+ end
67
+
33
68
  desc "delete [ID]", "Delete a tag"
34
69
  around :with_db_connection
35
70
  #
@@ -20,7 +20,7 @@ module Mihari
20
20
  return true if RETRIABLE_ERRORS.any? { |klass| error.is_a? klass }
21
21
 
22
22
  case error
23
- when StatusCodeError
23
+ when StatusError
24
24
  error.status_code != 404
25
25
  else
26
26
  false
@@ -28,7 +28,7 @@ module Mihari
28
28
  def ip?
29
29
  Try[IPAddr::InvalidAddressError] do
30
30
  IPAddr.new(data).to_s == data
31
- end.to_result.value_or(false)
31
+ end.recover { false }.value!
32
32
  end
33
33
 
34
34
  # @return [Boolean]
@@ -36,7 +36,7 @@ module Mihari
36
36
  Try[Addressable::URI::InvalidURIError] do
37
37
  uri = Addressable::URI.parse("http://#{data}")
38
38
  uri.host == data && PublicSuffix.valid?(uri.host)
39
- end.to_result.value_or(false)
39
+ end.recover { false }.value!
40
40
  end
41
41
 
42
42
  # @return [Boolean]
@@ -44,7 +44,7 @@ module Mihari
44
44
  Try[Addressable::URI::InvalidURIError] do
45
45
  uri = Addressable::URI.parse(data)
46
46
  uri.scheme && uri.host && uri.path && PublicSuffix.valid?(uri.host)
47
- end.to_result.value_or(false)
47
+ end.recover { false }.value!
48
48
  end
49
49
 
50
50
  # @return [Boolean]
@@ -1,49 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "erb"
4
-
5
3
  module Mihari
6
4
  module Emitters
7
- class ERBTemplate < ERB
8
- class << self
9
- def template
10
- %{
11
- {
12
- "rule": {
13
- "id": "<%= @rule.id %>",
14
- "title": "<%= @rule.title %>",
15
- "description": "<%= @rule.description %>"
16
- },
17
- "artifacts": [
18
- <% @artifacts.each_with_index do |artifact, idx| %>
19
- "<%= artifact.data %>"
20
- <%= ',' if idx < (@artifacts.length - 1) %>
21
- <% end %>
22
- ],
23
- "tags": [
24
- <% @rule.tags.each_with_index do |tag, idx| %>
25
- "<%= tag.name %>"
26
- <%= ',' if idx < (@rule.tags.length - 1) %>
27
- <% end %>
28
- ]
29
- }
30
- }
31
- end
32
- end
33
-
34
- def initialize(artifacts:, rule:, options: {})
35
- @artifacts = artifacts
36
- @rule = rule
37
-
38
- @template = options.fetch(:template, self.class.template)
39
- super(@template)
40
- end
41
-
42
- def result
43
- super(binding)
44
- end
45
- end
46
-
47
5
  class Webhook < Base
48
6
  # @return [Addressable::URI, nil]
49
7
  attr_reader :url
@@ -54,12 +12,24 @@ module Mihari
54
12
  # @return [String]
55
13
  attr_reader :method
56
14
 
57
- # @return [String, nil]
15
+ # @return [String]
58
16
  attr_reader :template
59
17
 
60
18
  # @return [Array<Mihari::Models::Artifact>]
61
19
  attr_accessor :artifacts
62
20
 
21
+ DEFAULT_TEMPLATE = %{
22
+ json.rule do
23
+ json.id rule.id
24
+ json.title rule.title
25
+ json.description rule.description
26
+ end
27
+
28
+ json.artifacts artifacts.map(&:data)
29
+
30
+ json.tags rule.tags.map(&:name)
31
+ }
32
+
63
33
  #
64
34
  # @param [Mihari::Rule] rule
65
35
  # @param [Hash, nil] options
@@ -71,7 +41,7 @@ module Mihari
71
41
  @url = Addressable::URI.parse(params[:url])
72
42
  @headers = params[:headers] || {}
73
43
  @method = params[:method] || "POST"
74
- @template = params[:template]
44
+ @template = params[:template] || DEFAULT_TEMPLATE
75
45
 
76
46
  @artifacts = []
77
47
  end
@@ -114,15 +84,7 @@ module Mihari
114
84
  # @return [String]
115
85
  #
116
86
  def render
117
- options = {}
118
- options[:template] = File.read(template) unless template.nil?
119
-
120
- erb_template = ERBTemplate.new(
121
- artifacts: artifacts,
122
- rule: rule,
123
- options: options
124
- )
125
- erb_template.result
87
+ Services::JbuilderRenderer.call(template, { rule: rule, artifacts: artifacts })
126
88
  end
127
89
 
128
90
  #
data/lib/mihari/errors.rb CHANGED
@@ -37,9 +37,9 @@ module Mihari
37
37
  class IntegrityError < Error; end
38
38
 
39
39
  #
40
- # HTTP status code error
40
+ # HTTP status error
41
41
  #
42
- class StatusCodeError < ::HTTP::Error
42
+ class StatusError < ::HTTP::Error
43
43
  # @return [Integer]
44
44
  attr_reader :status_code
45
45
 
data/lib/mihari/http.rb CHANGED
@@ -11,7 +11,7 @@ module Mihari
11
11
  def wrap_response(response)
12
12
  return response if response.status.success?
13
13
 
14
- raise StatusCodeError.new(
14
+ raise StatusError.new(
15
15
  "Unsuccessful response code returned: #{response.code}",
16
16
  response.code,
17
17
  response.body.to_s
@@ -0,0 +1,31 @@
1
+ require "tilt/jbuilder"
2
+
3
+ module Mihari
4
+ module Services
5
+ #
6
+ # Jbuilder based JSON renderer
7
+ #
8
+ class JbuilderRenderer < Service
9
+ attr_reader :template
10
+
11
+ #
12
+ # @param [String] template
13
+ # @param [Hash] params
14
+ #
15
+ # @return [String]
16
+ #
17
+ def call(template, params = {})
18
+ @template = template
19
+
20
+ jbuilder_template = Tilt::JbuilderTemplate.new { template_string }
21
+ jbuilder_template.render(nil, params)
22
+ end
23
+
24
+ def template_string
25
+ return File.read(template) if Pathname(template).exist?
26
+
27
+ template
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "7.0.5"
4
+ VERSION = "7.1.0"
5
5
  end
@@ -36,7 +36,7 @@ module Mihari
36
36
 
37
37
  failure = result.failure
38
38
  case failure
39
- when Mihari::StatusCodeError
39
+ when Mihari::StatusError
40
40
  error!({ message: "IP:#{ip} not found" }, failure.status_code) if failure.status_code == 404
41
41
  error!({ message: "IP format invalid" }, failure.status_code) if failure.status_code == 422
42
42
  end