mihari 5.6.1 → 5.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/frontend/package-lock.json +173 -176
  3. data/frontend/package.json +9 -9
  4. data/lib/mihari/{base.rb → actor.rb} +16 -2
  5. data/lib/mihari/analyzers/base.rb +5 -10
  6. data/lib/mihari/analyzers/censys.rb +1 -1
  7. data/lib/mihari/analyzers/hunterhow.rb +1 -1
  8. data/lib/mihari/analyzers/passivetotal.rb +1 -1
  9. data/lib/mihari/analyzers/pulsedive.rb +1 -1
  10. data/lib/mihari/analyzers/securitytrails.rb +1 -1
  11. data/lib/mihari/analyzers/urlscan.rb +1 -1
  12. data/lib/mihari/analyzers/virustotal.rb +5 -5
  13. data/lib/mihari/analyzers/zoomeye.rb +3 -3
  14. data/lib/mihari/clients/crtsh.rb +2 -2
  15. data/lib/mihari/clients/passivetotal.rb +4 -4
  16. data/lib/mihari/clients/securitytrails.rb +3 -3
  17. data/lib/mihari/commands/rule.rb +2 -11
  18. data/lib/mihari/commands/search.rb +1 -1
  19. data/lib/mihari/emitters/base.rb +13 -24
  20. data/lib/mihari/emitters/database.rb +7 -9
  21. data/lib/mihari/emitters/misp.rb +14 -38
  22. data/lib/mihari/emitters/slack.rb +14 -11
  23. data/lib/mihari/emitters/the_hive.rb +16 -44
  24. data/lib/mihari/emitters/webhook.rb +31 -21
  25. data/lib/mihari/enrichers/base.rb +1 -6
  26. data/lib/mihari/enrichers/whois.rb +1 -1
  27. data/lib/mihari/models/alert.rb +75 -73
  28. data/lib/mihari/models/artifact.rb +182 -180
  29. data/lib/mihari/models/autonomous_system.rb +22 -20
  30. data/lib/mihari/models/cpe.rb +21 -19
  31. data/lib/mihari/models/dns.rb +24 -22
  32. data/lib/mihari/models/geolocation.rb +22 -20
  33. data/lib/mihari/models/port.rb +21 -19
  34. data/lib/mihari/models/reverse_dns.rb +21 -19
  35. data/lib/mihari/models/rule.rb +67 -65
  36. data/lib/mihari/models/tag.rb +5 -3
  37. data/lib/mihari/models/tagging.rb +5 -3
  38. data/lib/mihari/models/whois.rb +18 -16
  39. data/lib/mihari/rule.rb +352 -0
  40. data/lib/mihari/schemas/analyzer.rb +94 -87
  41. data/lib/mihari/schemas/emitter.rb +9 -5
  42. data/lib/mihari/schemas/enricher.rb +8 -4
  43. data/lib/mihari/schemas/mixins.rb +15 -0
  44. data/lib/mihari/schemas/rule.rb +3 -10
  45. data/lib/mihari/services/alert_builder.rb +1 -1
  46. data/lib/mihari/services/alert_proxy.rb +10 -6
  47. data/lib/mihari/services/alert_runner.rb +4 -4
  48. data/lib/mihari/services/rule_builder.rb +3 -3
  49. data/lib/mihari/services/rule_runner.rb +5 -5
  50. data/lib/mihari/structs/binaryedge.rb +1 -1
  51. data/lib/mihari/structs/censys.rb +6 -6
  52. data/lib/mihari/structs/config.rb +1 -1
  53. data/lib/mihari/structs/greynoise.rb +5 -5
  54. data/lib/mihari/structs/hunterhow.rb +3 -3
  55. data/lib/mihari/structs/onyphe.rb +5 -5
  56. data/lib/mihari/structs/shodan.rb +6 -6
  57. data/lib/mihari/structs/urlscan.rb +3 -3
  58. data/lib/mihari/structs/virustotal_intelligence.rb +3 -3
  59. data/lib/mihari/version.rb +1 -1
  60. data/lib/mihari/web/endpoints/alerts.rb +4 -4
  61. data/lib/mihari/web/endpoints/artifacts.rb +6 -6
  62. data/lib/mihari/web/endpoints/rules.rb +10 -17
  63. data/lib/mihari/web/endpoints/tags.rb +2 -2
  64. data/lib/mihari/web/public/assets/{index-9cc489e6.js → index-28d4c79d.js} +48 -48
  65. data/lib/mihari/web/public/index.html +1 -1
  66. data/lib/mihari.rb +6 -8
  67. data/mihari.gemspec +1 -2
  68. data/requirements.txt +1 -1
  69. metadata +8 -22
  70. data/lib/mihari/analyzers/rule.rb +0 -232
  71. data/lib/mihari/services/rule_proxy.rb +0 -182
@@ -19,8 +19,8 @@
19
19
  "@fortawesome/vue-fontawesome": "^3.0.3",
20
20
  "@vueuse/core": "^10.5.0",
21
21
  "@vueuse/router": "^10.5.0",
22
- "ace-builds": "^1.30.0",
23
- "axios": "^1.5.1",
22
+ "ace-builds": "^1.31.0",
23
+ "axios": "^1.6.0",
24
24
  "bulma": "^0.9.4",
25
25
  "bulma-helpers": "^0.4.3",
26
26
  "dayjs": "^1.11.10",
@@ -30,21 +30,21 @@
30
30
  "ts-dedent": "^2.2.0",
31
31
  "url-parse": "^1.5.10",
32
32
  "uuidv4": "^6.2.13",
33
- "vue": "^3.3.6",
33
+ "vue": "^3.3.7",
34
34
  "vue-concurrency": "4.0.1",
35
35
  "vue-json-pretty": "^2.2.4",
36
36
  "vue-router": "^4.2.5",
37
37
  "vue3-ace-editor": "^2.2.3"
38
38
  },
39
39
  "devDependencies": {
40
- "@redocly/cli": "1.3.0",
40
+ "@redocly/cli": "1.4.0",
41
41
  "@rushstack/eslint-patch": "^1.5.1",
42
42
  "@tsconfig/node20": "^20.1.2",
43
43
  "@types/jsdom": "^21.1.4",
44
- "@types/node": "^20.8.7",
44
+ "@types/node": "^20.8.9",
45
45
  "@types/url-parse": "^1.4.10",
46
- "@typescript-eslint/eslint-plugin": "^6.8.0",
47
- "@typescript-eslint/parser": "^6.8.0",
46
+ "@typescript-eslint/eslint-plugin": "^6.9.0",
47
+ "@typescript-eslint/parser": "^6.9.0",
48
48
  "@vitejs/plugin-vue": "^4.4.0",
49
49
  "@vue/eslint-config-prettier": "^8.0.0",
50
50
  "@vue/eslint-config-typescript": "^12.0.0",
@@ -54,7 +54,7 @@
54
54
  "eslint-config-prettier": "^9.0.0",
55
55
  "eslint-plugin-prettier": "^5.0.1",
56
56
  "eslint-plugin-simple-import-sort": "^10.0.0",
57
- "eslint-plugin-vue": "^9.17.0",
57
+ "eslint-plugin-vue": "^9.18.1",
58
58
  "husky": "^8.0.3",
59
59
  "jsdom": "^22.1.0",
60
60
  "npm-run-all": "^4.1.5",
@@ -62,6 +62,6 @@
62
62
  "typescript": "~5.2.2",
63
63
  "vite": "^4.5.0",
64
64
  "vitest": "^0.34.6",
65
- "vue-tsc": "^1.8.19"
65
+ "vue-tsc": "^1.8.22"
66
66
  }
67
67
  }
@@ -4,7 +4,12 @@ module Mihari
4
4
  #
5
5
  # Base class for Analyzer, Emitter and Enricher
6
6
  #
7
- class Base
7
+ class Actor
8
+ include Dry::Monads[:result, :try]
9
+
10
+ include Mixins::Configurable
11
+ include Mixins::Retriable
12
+
8
13
  # @return [Hash]
9
14
  attr_reader :options
10
15
 
@@ -43,6 +48,15 @@ module Mihari
43
48
  options[:timeout]
44
49
  end
45
50
 
51
+ def validate_configuration!
52
+ return if configured?
53
+
54
+ joined = configuration_keys.join(", ")
55
+ be = (configuration_keys.length > 1) ? "are" : "is"
56
+ message = "#{self.class.class_key} is not configured correctly. #{joined} #{be} missing."
57
+ raise ConfigurationError, message
58
+ end
59
+
46
60
  class << self
47
61
  #
48
62
  # @return [String]
@@ -62,7 +76,7 @@ module Mihari
62
76
  # @return [Array<String>]
63
77
  #
64
78
  def class_keys
65
- ([class_key] + [class_key_aliases]).flatten.compact
79
+ ([class_key] + [class_key_aliases]).flatten.compact.map(&:downcase)
66
80
  end
67
81
  end
68
82
  end
@@ -2,12 +2,7 @@
2
2
 
3
3
  module Mihari
4
4
  module Analyzers
5
- class Base < Mihari::Base
6
- include Dry::Monads[:result, :try]
7
-
8
- include Mixins::Configurable
9
- include Mixins::Retriable
10
-
5
+ class Base < Actor
11
6
  # @return [String]
12
7
  attr_reader :query
13
8
 
@@ -45,7 +40,7 @@ module Mihari
45
40
  Mihari.config.ignore_error
46
41
  end
47
42
 
48
- # @return [Array<String>, Array<Mihari::Artifact>]
43
+ # @return [Array<String>, Array<Mihari::Models::Artifact>]
49
44
  def artifacts
50
45
  raise NotImplementedError, "You must implement #{self.class}##{__method__}"
51
46
  end
@@ -55,14 +50,14 @@ module Mihari
55
50
  # - Convert data (string) into an artifact
56
51
  # - Reject an invalid artifact
57
52
  #
58
- # @return [Array<Mihari::Artifact>]
53
+ # @return [Array<Mihari::Models::Artifact>]
59
54
  #
60
55
  def normalized_artifacts
61
56
  retry_on_error(times: retry_times, interval: retry_interval, exponential_backoff: retry_exponential_backoff) do
62
57
  artifacts.compact.sort.map do |artifact|
63
58
  # No need to set data_type manually
64
59
  # It is set automatically in #initialize
65
- artifact = artifact.is_a?(Artifact) ? artifact : Artifact.new(data: artifact)
60
+ artifact = artifact.is_a?(Models::Artifact) ? artifact : Models::Artifact.new(data: artifact)
66
61
  artifact.source = self.class.class_key
67
62
  artifact
68
63
  end.select(&:valid?).uniq(&:data)
@@ -70,7 +65,7 @@ module Mihari
70
65
  end
71
66
 
72
67
  #
73
- # @return [Dry::Monads::Result::Success<Array<Mihari::Artifact>>, Dry::Monads::Result::Failure]
68
+ # @return [Dry::Monads::Result::Success<Array<Mihari::Models::Artifact>>, Dry::Monads::Result::Failure]
74
69
  #
75
70
  def result
76
71
  Try[StandardError] { normalized_artifacts }.to_result
@@ -24,7 +24,7 @@ module Mihari
24
24
  end
25
25
 
26
26
  #
27
- # @return [Array<Mihari::Artifact>]
27
+ # @return [Array<Mihari::Models::Artifact>]
28
28
  #
29
29
  def artifacts
30
30
  client.search_with_pagination(query, pagination_limit: pagination_limit).map do |res|
@@ -27,7 +27,7 @@ module Mihari
27
27
  end
28
28
 
29
29
  #
30
- # @return [Array<Mihari::Artifact>]
30
+ # @return [Array<Mihari::Models::Artifact>]
31
31
  #
32
32
  def artifacts
33
33
  client.search_with_pagination(
@@ -54,7 +54,7 @@ module Mihari
54
54
  #
55
55
  # @return [Array<String>, nil]
56
56
  #
57
- def key_aliases
57
+ def class_key_aliases
58
58
  ["pt"]
59
59
  end
60
60
  end
@@ -35,7 +35,7 @@ module Mihari
35
35
  nil
36
36
  else
37
37
  data = property["value"]
38
- Artifact.new(data: data, metadata: property)
38
+ Models::Artifact.new(data: data, metadata: property)
39
39
  end
40
40
  end
41
41
  end
@@ -48,7 +48,7 @@ module Mihari
48
48
  #
49
49
  # @return [Array<String>, nil]
50
50
  #
51
- def key_aliases
51
+ def class_key_aliases
52
52
  ["st"]
53
53
  end
54
54
  end
@@ -29,7 +29,7 @@ module Mihari
29
29
  end
30
30
 
31
31
  def artifacts
32
- # @type [Array<Mihari::Artifact>]
32
+ # @type [Array<Mihari::Models::Artifact>]
33
33
  artifacts = client.search_with_pagination(query, pagination_limit: pagination_limit).map(&:artifacts).flatten
34
34
 
35
35
  artifacts.select do |artifact|
@@ -43,7 +43,7 @@ module Mihari
43
43
  #
44
44
  # @return [Array<String>, nil]
45
45
  #
46
- def key_aliases
46
+ def class_key_aliases
47
47
  ["vt"]
48
48
  end
49
49
  end
@@ -66,7 +66,7 @@ module Mihari
66
66
  #
67
67
  # Domain search
68
68
  #
69
- # @return [Array<Mihari::Artifact>]
69
+ # @return [Array<Mihari::Models::Artifact>]
70
70
  #
71
71
  def domain_search
72
72
  res = client.domain_search(query)
@@ -74,14 +74,14 @@ module Mihari
74
74
  data = res["data"] || []
75
75
  data.filter_map do |item|
76
76
  data = item.dig("attributes", "ip_address")
77
- data.nil? ? nil : Artifact.new(data: data, metadata: item)
77
+ data.nil? ? nil : Models::Artifact.new(data: data, metadata: item)
78
78
  end
79
79
  end
80
80
 
81
81
  #
82
82
  # IP search
83
83
  #
84
- # @return [Array<Mihari::Artifact>]
84
+ # @return [Array<Mihari::Models::Artifact>]
85
85
  #
86
86
  def ip_search
87
87
  res = client.ip_search(query)
@@ -89,7 +89,7 @@ module Mihari
89
89
  data = res["data"] || []
90
90
  data.filter_map do |item|
91
91
  data = item.dig("attributes", "host_name")
92
- Artifact.new(data: data, metadata: item)
92
+ Models::Artifact.new(data: data, metadata: item)
93
93
  end.uniq
94
94
  end
95
95
  end
@@ -65,7 +65,7 @@ module Mihari
65
65
  #
66
66
  # @param [Hash] response
67
67
  #
68
- # @return [Array<Mihari::Artifact>]
68
+ # @return [Array<Mihari::Models::Artifact>]
69
69
  #
70
70
  def convert(res)
71
71
  matches = res["matches"] || []
@@ -73,9 +73,9 @@ module Mihari
73
73
  data = match["ip"]
74
74
 
75
75
  if data.is_a?(Array)
76
- data.map { |d| Artifact.new(data: d, metadata: match) }
76
+ data.map { |d| Models::Artifact.new(data: d, metadata: match) }
77
77
  else
78
- Artifact.new(data: data, metadata: match)
78
+ Models::Artifact.new(data: data, metadata: match)
79
79
  end
80
80
  end.flatten
81
81
  end
@@ -19,7 +19,7 @@ module Mihari
19
19
  # @param [String, nil] match "=", "ILIKE", "LIKE", "single", "any" or nil
20
20
  # @param [String, nil] exclude "expired" or nil
21
21
  #
22
- # @return [Array<Mihari::Artifact>]
22
+ # @return [Array<Mihari::Models::Artifact>]
23
23
  #
24
24
  def search(identity, match: nil, exclude: nil)
25
25
  params = { identity: identity, match: match, exclude: exclude, output: "json" }.compact
@@ -29,7 +29,7 @@ module Mihari
29
29
 
30
30
  parsed.map do |result|
31
31
  values = result["name_value"].to_s.lines.map(&:chomp)
32
- values.map { |value| Artifact.new(data: value, metadata: result) }
32
+ values.map { |value| Models::Artifact.new(data: value, metadata: result) }
33
33
  end.flatten
34
34
  end
35
35
  end
@@ -39,7 +39,7 @@ module Mihari
39
39
  #
40
40
  # @param [String] query
41
41
  #
42
- # @return [Array<Mihari::Artifact>]
42
+ # @return [Array<Mihari::Models::Artifact>]
43
43
  #
44
44
  def reverse_whois_search(query)
45
45
  params = {
@@ -50,7 +50,7 @@ module Mihari
50
50
  results = res["results"] || []
51
51
  results.map do |result|
52
52
  data = result["domain"]
53
- Artifact.new(data: data, metadata: result)
53
+ Models::Artifact.new(data: data, metadata: result)
54
54
  end.flatten
55
55
  end
56
56
 
@@ -59,7 +59,7 @@ module Mihari
59
59
  #
60
60
  # @param [String] query
61
61
  #
62
- # @return [Array<Mihari::Artifact>]
62
+ # @return [Array<Mihari::Models::Artifact>]
63
63
  #
64
64
  def ssl_search(query)
65
65
  params = { query: query }
@@ -67,7 +67,7 @@ module Mihari
67
67
  results = res["results"] || []
68
68
  results.map do |result|
69
69
  data = result["ipAddresses"]
70
- data.map { |d| Artifact.new(data: d, metadata: result) }
70
+ data.map { |d| Models::Artifact.new(data: d, metadata: result) }
71
71
  end.flatten
72
72
  end
73
73
 
@@ -36,13 +36,13 @@ module Mihari
36
36
  #
37
37
  # @param [String] query
38
38
  #
39
- # @return [Array<Mihari::Artifact>]
39
+ # @return [Array<Mihari::Models::Artifact>]
40
40
  #
41
41
  def ip_search(query)
42
42
  records = search_by_ip(query)
43
43
  records.filter_map do |record|
44
44
  data = record["hostname"]
45
- Artifact.new(data: data, metadata: record)
45
+ Models::Artifact.new(data: data, metadata: record)
46
46
  end
47
47
  end
48
48
 
@@ -57,7 +57,7 @@ module Mihari
57
57
  records = search_by_mail(query)
58
58
  records.filter_map do |record|
59
59
  data = record["hostname"]
60
- Artifact.new(data: data, metadata: record)
60
+ Models::Artifact.new(data: data, metadata: record)
61
61
  end
62
62
  end
63
63
 
@@ -17,10 +17,7 @@ module Mihari
17
17
  # @param [String] path
18
18
  #
19
19
  def validate(path)
20
- res = Dry::Monads::Try[ValidationError] do
21
- Services::RuleProxy.from_yaml File.read(path)
22
- end
23
-
20
+ res = Dry::Monads::Try[ValidationError] { Mihari::Rule.from_yaml File.read(path) }
24
21
  rule = res.value!
25
22
  puts rule.data.to_yaml
26
23
  end
@@ -42,13 +39,6 @@ module Mihari
42
39
  end
43
40
 
44
41
  no_commands do
45
- #
46
- # @return [Mihari::Services::Rule]
47
- #
48
- def rule
49
- Services::RuleProxy.from_yaml File.read(File.expand_path("../templates/rule.yml.erb", __dir__))
50
- end
51
-
52
42
  #
53
43
  # Create a new rule
54
44
  #
@@ -58,6 +48,7 @@ module Mihari
58
48
  # @return [nil]
59
49
  #
60
50
  def initialize_rule(path, files = Dry::Files.new)
51
+ rule = Mihari::Rule.from_yaml File.read(File.expand_path("../templates/rule.yml.erb", __dir__))
61
52
  files.write(path, rule.yaml)
62
53
  end
63
54
  end
@@ -32,7 +32,7 @@ module Mihari
32
32
 
33
33
  no_commands do
34
34
  #
35
- # @param [Mihari::Services::RuleProxy] rule
35
+ # @param [Mihari::Services::RuleRunner] rule
36
36
  #
37
37
  def check_diff(rule)
38
38
  force_overwrite = options["force_overwrite"] || false
@@ -2,49 +2,38 @@
2
2
 
3
3
  module Mihari
4
4
  module Emitters
5
- class Base < Mihari::Base
6
- include Dry::Monads[:result, :try]
7
-
8
- include Mixins::Configurable
9
- include Mixins::Retriable
10
-
11
- # @return [Array<Mihari::Artifact>]
12
- attr_reader :artifacts
13
-
14
- # @return [Mihari::Services::Rule]
5
+ class Base < Actor
6
+ # @return [Mihari::Rule]
15
7
  attr_reader :rule
16
8
 
17
9
  #
18
- # @param [Array<Mihari::Artifact>] artifacts
19
- # @param [Mihari::Services::RuleProxy] rule
10
+ # @param [Mihari::Rule] rule
20
11
  # @param [Hash, nil] options
21
12
  # @param [Hash] **_params
22
13
  #
23
- def initialize(artifacts:, rule:, options: nil, **_params)
14
+ def initialize(rule:, options: nil, **_params)
24
15
  super(options: options)
25
16
 
26
- @artifacts = artifacts
27
17
  @rule = rule
28
18
  end
29
19
 
30
- # @return [Boolean]
31
- def valid?
32
- raise NotImplementedError, "You must implement #{self.class}##{__method__}"
33
- end
34
-
35
- def result
20
+ #
21
+ # @param [Array<Mihari::Models::Artifact>] artifacts
22
+ #
23
+ def emit_result(artifacts)
36
24
  Try[StandardError] do
37
25
  retry_on_error(
38
26
  times: retry_times,
39
27
  interval: retry_interval,
40
28
  exponential_backoff: retry_exponential_backoff
41
- ) do
42
- emit
43
- end
29
+ ) { emit artifacts }
44
30
  end.to_result
45
31
  end
46
32
 
47
- def emit
33
+ #
34
+ # @param [Array<Mihari::Models::Artifact>] artifacts
35
+ #
36
+ def emit(artifacts)
48
37
  raise NotImplementedError, "You must implement #{self.class}##{__method__}"
49
38
  end
50
39
 
@@ -3,22 +3,20 @@
3
3
  module Mihari
4
4
  module Emitters
5
5
  class Database < Base
6
- def valid?
7
- configured?
8
- end
9
-
10
6
  #
11
7
  # Create an alert
12
8
  #
13
- # @return [Mihari::Alert, nil]
9
+ # @param [Array<Mihari::Models::Artifact>] artifacts
10
+ #
11
+ # @return [Mihari::Models::Alert, nil]
14
12
  #
15
- def emit
13
+ def emit(artifacts)
16
14
  return if artifacts.empty?
17
15
 
18
- tags = rule.tags.filter_map { |name| Tag.find_or_create_by(name: name) }.uniq
19
- taggings = tags.map { |tag| Tagging.new(tag_id: tag.id) }
16
+ tags = rule.tags.filter_map { |name| Models::Tag.find_or_create_by(name: name) }.uniq
17
+ taggings = tags.map { |tag| Models::Tagging.new(tag_id: tag.id) }
20
18
 
21
- alert = Alert.new(artifacts: artifacts, taggings: taggings, rule_id: rule.id)
19
+ alert = Models::Alert.new(artifacts: artifacts, taggings: taggings, rule_id: rule.id)
22
20
  alert.save
23
21
  alert
24
22
  end
@@ -9,50 +9,39 @@ module Mihari
9
9
  # @return [String, nil]
10
10
  attr_reader :api_key
11
11
 
12
- # @return [Array<Mihari::Artifact>]
13
- attr_reader :artifacts
14
-
15
12
  # @return [Mihari::Services::Rule]
16
13
  attr_reader :rule
17
14
 
15
+ # @return [Array<Mihari::Models::Artifact>]
16
+ attr_accessor :artifacts
17
+
18
18
  #
19
- # @param [Array<Mihari::Artifact>] artifacts
20
19
  # @param [Mihari::Services::Rule] rule
21
20
  # @param [Hash, nil] options
22
21
  # @param [Hash] **params
23
22
  #
24
- def initialize(artifacts:, rule:, options: nil, **params)
25
- super(artifacts: artifacts, rule: rule, options: options)
23
+ def initialize(rule:, options: nil, **params)
24
+ super(rule: rule, options: options)
26
25
 
27
26
  @url = params[:url] || Mihari.config.misp_url
28
27
  @api_key = params[:api_key] || Mihari.config.misp_api_key
28
+
29
+ @artifacts = []
29
30
  end
30
31
 
32
+ #
31
33
  # @return [Boolean]
32
- def valid?
33
- unless url? && api_key?
34
- Mihari.logger.info("MISP URL is not set") unless url?
35
- Mihari.logger.info("MISP API key is not set") unless api_key?
36
- return false
37
- end
38
-
39
- unless ping?
40
- Mihari.logger.info("MISP URL (#{url}) is not reachable")
41
- return false
42
- end
43
-
44
- true
34
+ #
35
+ def configured?
36
+ api_key? && url?
45
37
  end
46
38
 
47
39
  #
48
40
  # Create a MISP event
49
41
  #
50
- # @param [Arra<Mihari::Artifact>] artifacts
51
- # @param [Mihari::Services::Rule] rule
52
- #
53
- # @return [::MISP::Event]
42
+ # @param [Array<Mihari::Models::Artifact>] artifacts
54
43
  #
55
- def emit
44
+ def emit(artifacts)
56
45
  return if artifacts.empty?
57
46
 
58
47
  client.create_event({
@@ -77,7 +66,7 @@ module Mihari
77
66
  #
78
67
  # Build a MISP attribute
79
68
  #
80
- # @param [Mihari::Artifact] artifact
69
+ # @param [Mihari::Models::Artifact] artifact
81
70
  #
82
71
  # @return [Hash]
83
72
  #
@@ -143,19 +132,6 @@ module Mihari
143
132
  def api_key?
144
133
  !api_key.nil? && !api_key.empty?
145
134
  end
146
-
147
- #
148
- # Check whether a URL is reachable or not
149
- #
150
- # @return [Boolean]
151
- #
152
- def ping?
153
- base_url = url.end_with?("/") ? url[0..-2] : url
154
- login_url = "#{base_url}/users/login"
155
-
156
- http = Net::Ping::HTTP.new(login_url)
157
- http.ping?
158
- end
159
135
  end
160
136
  end
161
137
  end
@@ -131,18 +131,22 @@ module Mihari
131
131
  # @return [String]
132
132
  attr_reader :username
133
133
 
134
+ # @return [Array<Mihari::Models::Artifact>]
135
+ attr_accessor :artifacts
136
+
134
137
  #
135
- # @param [Array<Mihari::Artifact>] artifacts
136
138
  # @param [Mihari::Services::Rule] rule
137
139
  # @param [Hash, nil] options
138
140
  # @param [Hash] **params
139
141
  #
140
- def initialize(artifacts:, rule:, options: nil, **params)
141
- super(artifacts: artifacts, rule: rule, options: options)
142
+ def initialize(rule:, options: nil, **params)
143
+ super(rule: rule, options: options)
142
144
 
143
145
  @webhook_url = params[:webhook_url] || Mihari.config.slack_webhook_url
144
146
  @channel = params[:channel] || Mihari.config.slack_channel || DEFAULT_CHANNEL
145
147
  @username = DEFAULT_USERNAME
148
+
149
+ @artifacts = []
146
150
  end
147
151
 
148
152
  #
@@ -154,12 +158,10 @@ module Mihari
154
158
  !webhook_url.nil?
155
159
  end
156
160
 
157
- #
158
- # Check webhook URL is set. Alias of #webhook_url?
159
161
  #
160
162
  # @return [Boolean]
161
163
  #
162
- def valid?
164
+ def configured?
163
165
  webhook_url?
164
166
  end
165
167
 
@@ -211,19 +213,20 @@ module Mihari
211
213
  ].join("\n")
212
214
  end
213
215
 
214
- def emit
216
+ #
217
+ # @param [Array<Mihari::Models::Artifact>] artifacts
218
+ #
219
+ def emit(artifacts)
215
220
  return if artifacts.empty?
216
221
 
222
+ @artifacts = artifacts
223
+
217
224
  notifier.post(text: text, attachments: attachments, mrkdwn: true)
218
225
  end
219
226
 
220
227
  def configuration_keys
221
228
  %w[slack_webhook_url slack_channel]
222
229
  end
223
-
224
- def configured?
225
- valid?
226
- end
227
230
  end
228
231
  end
229
232
  end