mihari 4.9.0 → 4.10.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85756e55047ef3bde95c50c1ac3c474adbd29828bf1f95618f3aac85638a1752
4
- data.tar.gz: babe64cf74a96f659057b06ac3b5864b6faa2c3ec9b7e3f0f9b57bce7dd635a8
3
+ metadata.gz: 54ef0421cb5da34c8174fe0fdc3b43d310770dca779dd51fac284a678b86fc0a
4
+ data.tar.gz: 6b24c7b37c00f7ebed9ee0fcfbfb66b95d7d60ea7c7792a40be32607bdda07fe
5
5
  SHA512:
6
- metadata.gz: 5c15c65a8952c1fbcf695feba8add8a7fc962eaac9ca426a18dd510663573dc9fe6b27472ca0edcd1ff9fb86b68a49ce8c459e3a7d90eabe9dbbe1e4506181d8
7
- data.tar.gz: aceb04f0f6e78af7f0df2293d78a4d4d20bcf1827e70d45e3f425e38b128c5f9194dbdac608b29b44852af77b626ccbdd03583e7170d5330a2b584c7cbdca55b
6
+ metadata.gz: 941a6e47d53a2287d793fe28fab3e6e9295076ed39e50fcf8f55e6cdca102381ae425b3db603acdfea9b28e438a7f57627ed793be1efcb0093d83b17ac128535
7
+ data.tar.gz: 25055c04746f33620e0c762f1d79d6407d8a9156d47820c2129ed4b72e926e7cf2d3ea275ff546046bb5b9ce82fe069b222d56f5b69700eb44179f83d80c058c
@@ -72,10 +72,22 @@ module Mihari
72
72
  #
73
73
  # @param [Mihari::Emitters::Base] emitter
74
74
  #
75
- # @return [nil]
75
+ # @return [Mihari::Alert, nil]
76
76
  #
77
77
  def run_emitter(emitter)
78
- emitter.run(title: title, description: description, artifacts: enriched_artifacts, source: source, tags: tags)
78
+ return if enriched_artifacts.empty?
79
+
80
+ alert_or_something = emitter.run(
81
+ title: title,
82
+ description: description,
83
+ artifacts: enriched_artifacts,
84
+ source: source,
85
+ tags: tags
86
+ )
87
+
88
+ Mihari.logger.info "Emission by #{emitter.class} is succedded"
89
+
90
+ alert_or_something
79
91
  rescue StandardError => e
80
92
  Mihari.logger.info "Emission by #{emitter.class} is failed: #{e}"
81
93
  end
@@ -44,7 +44,7 @@ module Mihari
44
44
  data = Mihari::Entities::Alert.represent(alert)
45
45
  puts JSON.pretty_generate(data.as_json)
46
46
  else
47
- Mihari.logger.info "There is no new artifact"
47
+ Mihari.logger.info "No new alert created in the database"
48
48
  end
49
49
 
50
50
  # record a rule
@@ -6,7 +6,7 @@ module Mihari
6
6
  module Emitters
7
7
  class MISP < Base
8
8
  # @return [String, nil]
9
- attr_reader :api_endpoint
9
+ attr_reader :url
10
10
 
11
11
  # @return [String, nil]
12
12
  attr_reader :api_key
@@ -14,18 +14,29 @@ module Mihari
14
14
  def initialize(*args, **kwargs)
15
15
  super(*args, **kwargs)
16
16
 
17
- @api_endpoint = kwargs[:api_endpoint] || Mihari.config.misp_api_endpoint
17
+ @url = kwargs[:url] || kwargs[:api_endpoint] || Mihari.config.misp_url
18
18
  @api_key = kwargs[:api_key] || Mihari.config.misp_api_key
19
19
 
20
20
  ::MISP.configure do |config|
21
- config.api_endpoint = api_endpoint
21
+ config.api_endpoint = url
22
22
  config.api_key = api_key
23
23
  end
24
24
  end
25
25
 
26
26
  # @return [Boolean]
27
27
  def valid?
28
- api_endpoint? && api_key? && ping?
28
+ unless url? && api_key?
29
+ Mihari.logger.info("MISP URL is not set") unless url?
30
+ Mihari.logger.info("MISP API key is not set") unless api_key?
31
+ return false
32
+ end
33
+
34
+ unless ping?
35
+ Mihari.logger.info("MISP URL (#{url}) is not reachable")
36
+ return false
37
+ end
38
+
39
+ true
29
40
  end
30
41
 
31
42
  def emit(title:, artifacts:, tags: [], **_options)
@@ -47,7 +58,7 @@ module Mihari
47
58
  private
48
59
 
49
60
  def configuration_keys
50
- %w[misp_api_endpoint misp_api_key]
61
+ %w[misp_url misp_api_key]
51
62
  end
52
63
 
53
64
  #
@@ -103,12 +114,12 @@ module Mihari
103
114
  end
104
115
 
105
116
  #
106
- # Check whether an API endpoint is set or not
117
+ # Check whether a URL is set or not
107
118
  #
108
119
  # @return [Boolean]
109
120
  #
110
- def api_endpoint?
111
- !api_endpoint.nil? && !api_endpoint.empty?
121
+ def url?
122
+ !url.nil? && !url.empty?
112
123
  end
113
124
 
114
125
  #
@@ -121,15 +132,15 @@ module Mihari
121
132
  end
122
133
 
123
134
  #
124
- # Check whether an API endpoint is reachable or not
135
+ # Check whether a URL is reachable or not
125
136
  #
126
137
  # @return [Boolean]
127
138
  #
128
139
  def ping?
129
- base_url = api_endpoint.end_with?("/") ? api_endpoint[0..-2] : api_endpoint
130
- url = "#{base_url}/users/login"
140
+ base_url = url.end_with?("/") ? url[0..-2] : url
141
+ login_url = "#{base_url}/users/login"
131
142
 
132
- http = Net::Ping::HTTP.new(url)
143
+ http = Net::Ping::HTTP.new(login_url)
133
144
  http.ping?
134
145
  end
135
146
  end
@@ -6,7 +6,7 @@ module Mihari
6
6
  module Emitters
7
7
  class TheHive < Base
8
8
  # @return [String, nil]
9
- attr_reader :api_endpoint
9
+ attr_reader :url
10
10
 
11
11
  # @return [String, nil]
12
12
  attr_reader :api_key
@@ -17,14 +17,25 @@ module Mihari
17
17
  def initialize(*args, **kwargs)
18
18
  super(*args, **kwargs)
19
19
 
20
- @api_endpoint = kwargs[:api_endpoint] || Mihari.config.thehive_api_endpoint
20
+ @url = kwargs[:url] || kwargs[:api_endpoint] || Mihari.config.thehive_url
21
21
  @api_key = kwargs[:api_key] || Mihari.config.thehive_api_key
22
22
  @api_version = kwargs[:api_version] || Mihari.config.thehive_api_version
23
23
  end
24
24
 
25
25
  # @return [Boolean]
26
26
  def valid?
27
- api_endpont? && api_key? && ping?
27
+ unless url? && api_key?
28
+ Mihari.logger.info("TheHive URL is not set") unless url?
29
+ Mihari.logger.info("TheHive API key is not set") unless api_key?
30
+ return false
31
+ end
32
+
33
+ unless ping?
34
+ Mihari.logger.info("TheHive URL (#{url}) is not reachable")
35
+ return false
36
+ end
37
+
38
+ true
28
39
  end
29
40
 
30
41
  def emit(title:, description:, artifacts:, tags: [], **_options)
@@ -57,20 +68,20 @@ module Mihari
57
68
  private
58
69
 
59
70
  def configuration_keys
60
- %w[thehive_api_endpoint thehive_api_key]
71
+ %w[thehive_url thehive_api_key]
61
72
  end
62
73
 
63
74
  def api
64
- @api ||= Hachi::API.new(api_endpoint: api_endpoint, api_key: api_key, api_version: normalized_api_version)
75
+ @api ||= Hachi::API.new(api_endpoint: url, api_key: api_key, api_version: normalized_api_version)
65
76
  end
66
77
 
67
78
  #
68
- # Check whether an API endpoint is set or not
79
+ # Check whether a URL is set or not
69
80
  #
70
81
  # @return [Boolean]
71
82
  #
72
- def api_endpont?
73
- !api_endpoint.nil?
83
+ def url?
84
+ !url.nil?
74
85
  end
75
86
 
76
87
  #
@@ -83,7 +94,10 @@ module Mihari
83
94
  end
84
95
 
85
96
  def payload(title:, description:, artifacts:, tags: [])
86
- return v4_payload(title: title, description: description, artifacts: artifacts, tags: tags) if normalized_api_version.nil?
97
+ if normalized_api_version.nil?
98
+ return v4_payload(title: title, description: description, artifacts: artifacts,
99
+ tags: tags)
100
+ end
87
101
 
88
102
  v5_payload(title: title, description: description, artifacts: artifacts, tags: tags)
89
103
  end
@@ -92,7 +106,9 @@ module Mihari
92
106
  {
93
107
  title: title,
94
108
  description: description,
95
- artifacts: artifacts.map { |artifact| { data: artifact.data, data_type: artifact.data_type, message: description } },
109
+ artifacts: artifacts.map do |artifact|
110
+ { data: artifact.data, data_type: artifact.data_type, message: description }
111
+ end,
96
112
  tags: tags,
97
113
  type: "external",
98
114
  source: "mihari"
@@ -103,7 +119,9 @@ module Mihari
103
119
  {
104
120
  title: title,
105
121
  description: description,
106
- observables: artifacts.map { |artifact| { data: artifact.data, data_type: artifact.data_type, message: description } },
122
+ observables: artifacts.map do |artifact|
123
+ { data: artifact.data, data_type: artifact.data_type, message: description }
124
+ end,
107
125
  tags: tags,
108
126
  type: "external",
109
127
  source: "mihari",
@@ -112,23 +130,23 @@ module Mihari
112
130
  end
113
131
 
114
132
  #
115
- # Check whether an API endpoint is reachable or not
133
+ # Check whether a URL is reachable or not
116
134
  #
117
135
  # @return [Boolean]
118
136
  #
119
137
  def ping?
120
- base_url = api_endpoint.end_with?("/") ? api_endpoint[0..-2] : api_endpoint
138
+ base_url = url.end_with?("/") ? url[0..-2] : url
121
139
 
122
140
  if normalized_api_version.nil?
123
141
  # for v4
124
- base_url = api_endpoint.end_with?("/") ? api_endpoint[0..-2] : api_endpoint
125
- url = "#{base_url}/index.html"
142
+ base_url = url.end_with?("/") ? url[0..-2] : url
143
+ public_url = "#{base_url}/index.html"
126
144
  else
127
145
  # for v5
128
- url = "#{base_url}/api/v1/status/public"
146
+ public_url = "#{base_url}/api/v1/status/public"
129
147
  end
130
148
 
131
- http = Net::Ping::HTTP.new(url)
149
+ http = Net::Ping::HTTP.new(public_url)
132
150
 
133
151
  # use GET for v5
134
152
  http.get_request = true if normalized_api_version
@@ -9,12 +9,14 @@ module Mihari
9
9
  MISP = Dry::Schema.Params do
10
10
  required(:emitter).value(Types::String.enum("misp"))
11
11
  optional(:api_endpoint).value(:string)
12
+ optional(:url).value(:string)
12
13
  optional(:api_key).value(:string)
13
14
  end
14
15
 
15
16
  TheHive = Dry::Schema.Params do
16
17
  required(:emitter).value(Types::String.enum("the_hive"))
17
18
  optional(:api_endpoint).value(:string)
19
+ optional(:url).value(:string)
18
20
  optional(:api_key).value(:string)
19
21
  optional(:api_version).value(Types::String.enum("v4", "v5")).default("v4")
20
22
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "4.9.0"
4
+ VERSION = "4.10.0"
5
5
  end
data/lib/mihari.rb CHANGED
@@ -84,7 +84,8 @@ module Mihari
84
84
 
85
85
  setting :ipinfo_api_key, default: ENV.fetch("IPINFO_API_KEY", nil)
86
86
 
87
- setting :misp_api_endpoint, default: ENV.fetch("MISP_API_ENDPOINT", nil)
87
+ # TODO: deprecate MISP_API_ENDPOINT
88
+ setting :misp_url, default: ENV.fetch("MISP_URL", nil) || ENV.fetch("MISP_API_ENDPOINT", nil)
88
89
  setting :misp_api_key, default: ENV.fetch("MISP_API_KEY", nil)
89
90
 
90
91
  setting :onyphe_api_key, default: ENV.fetch("ONYPHE_API_KEY", nil)
@@ -105,7 +106,8 @@ module Mihari
105
106
 
106
107
  setting :spyse_api_key, default: ENV.fetch("SPYSE_API_KEY", nil)
107
108
 
108
- setting :thehive_api_endpoint, default: ENV.fetch("THEHIVE_API_ENDPOINT", nil)
109
+ # TODO: deprecate THEHIVE_API_ENDPOINT
110
+ setting :thehive_url, default: ENV.fetch("THEHIVE_URL", nil) || ENV.fetch("THEHIVE_API_ENDPOINT", nil)
109
111
  setting :thehive_api_key, default: ENV.fetch("THEHIVE_API_KEY", nil)
110
112
  setting :thehive_api_version, default: ENV.fetch("THEHIVE_API_VERSION", nil)
111
113
 
data/mihari.gemspec CHANGED
@@ -40,7 +40,7 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency "rspec", "~> 3.11"
41
41
  spec.add_development_dependency "simplecov-lcov", "~> 0.8.0"
42
42
  spec.add_development_dependency "standard", "~> 1.16"
43
- spec.add_development_dependency "steep", "~> 1.1"
43
+ spec.add_development_dependency "steep", "~> 1.2"
44
44
  spec.add_development_dependency "timecop", "~> 0.9"
45
45
  spec.add_development_dependency "vcr", "~> 6.1"
46
46
  spec.add_development_dependency "webmock", "~> 3.18"
@@ -54,11 +54,11 @@ Gem::Specification.new do |spec|
54
54
  spec.add_dependency "dnpedia", "0.1.0"
55
55
  spec.add_dependency "dnstwister", "0.1.0"
56
56
  spec.add_dependency "dotenv", "2.8.1"
57
- spec.add_dependency "dry-configurable", "0.15.0"
57
+ spec.add_dependency "dry-configurable", "0.16.0"
58
58
  spec.add_dependency "dry-container", "0.11.0"
59
59
  spec.add_dependency "dry-files", "0.3.0"
60
60
  spec.add_dependency "dry-initializer", "3.1.1"
61
- spec.add_dependency "dry-schema", "1.10.5"
61
+ spec.add_dependency "dry-schema", "1.10.6"
62
62
  spec.add_dependency "dry-struct", "1.4.0"
63
63
  spec.add_dependency "dry-validation", "1.8.1"
64
64
  spec.add_dependency "email_address", "0.2.4"
@@ -88,10 +88,9 @@ Gem::Specification.new do |spec|
88
88
  spec.add_dependency "rack-cors", "1.1.1"
89
89
  spec.add_dependency "securitytrails", "1.0.0"
90
90
  spec.add_dependency "semantic_logger", "4.11.0"
91
- spec.add_dependency "sentry-ruby", "5.4.2"
91
+ spec.add_dependency "sentry-ruby", "5.5.0"
92
92
  spec.add_dependency "shodanx", "0.2.1"
93
93
  spec.add_dependency "slack-notifier", "2.4.0"
94
- spec.add_dependency "spysex", "0.2.0"
95
94
  spec.add_dependency "sqlite3", "1.5.0"
96
95
  spec.add_dependency "thor", "1.2.1"
97
96
  spec.add_dependency "urlscan", "0.8.0"
@@ -2,7 +2,7 @@ module Mihari
2
2
  module Emitters
3
3
  class MISP < Base
4
4
 
5
- attr_reader api_endpiont: String?
5
+ attr_reader url: String?
6
6
 
7
7
  attr_reader api_key: String?
8
8
 
@@ -16,7 +16,7 @@ module Mihari
16
16
 
17
17
  private
18
18
 
19
- def configuration_keys: () -> ::Array["misp_api_endpoint" | "misp_api_key"]
19
+ def configuration_keys: () -> ::Array["misp_url" | "misp_api_key"]
20
20
 
21
21
  def build_attribute: (Mihari::Artifact artifact) -> untyped
22
22
 
@@ -24,7 +24,7 @@ module Mihari
24
24
 
25
25
  def to_misp_type: (type: String `type`, value: String value) -> String?
26
26
 
27
- def api_endpoint?: () -> bool
27
+ def url?: () -> bool
28
28
 
29
29
  def api_key?: () -> bool
30
30
 
@@ -1,7 +1,7 @@
1
1
  module Mihari
2
2
  module Emitters
3
3
  class TheHive < Base
4
- attr_reader api_endpiont: String?
4
+ attr_reader url: String?
5
5
 
6
6
  attr_reader api_key: String?
7
7
 
@@ -16,12 +16,12 @@ module Mihari
16
16
 
17
17
  private
18
18
 
19
- def configuration_keys: () -> ::Array["thehive_api_endpoint" | "thehive_api_key"]
19
+ def configuration_keys: () -> ::Array["thehive_url" | "thehive_api_key"]
20
20
 
21
21
  def api: () -> untyped
22
22
 
23
23
  # @return [true, false]
24
- def api_endpont?: () -> bool
24
+ def url?: () -> bool
25
25
 
26
26
  # @return [true, false]
27
27
  def api_key?: () -> bool
data/sig/lib/mihari.rbs CHANGED
@@ -5,7 +5,7 @@ class Configuration
5
5
  attr_accessor circl_passive_password (): String?
6
6
  attr_accessor circl_passive_username (): String?
7
7
  attr_accessor ipinfo_api_key (): String?
8
- attr_accessor misp_api_endpoint (): String?
8
+ attr_accessor misp_url (): String?
9
9
  attr_accessor misp_api_key (): String?
10
10
  attr_accessor onyphe_api_key (): String?
11
11
  attr_accessor otx_api_key (): String?
@@ -17,7 +17,7 @@ class Configuration
17
17
  attr_accessor slack_channel (): String?
18
18
  attr_accessor slack_webhook_url (): String?
19
19
  attr_accessor spyse_api_key (): String?
20
- attr_accessor thehive_api_endpoint (): String?
20
+ attr_accessor thehive_url (): String?
21
21
  attr_accessor thehive_api_key (): String?
22
22
  attr_accessor thehive_api_version (): String?
23
23
  attr_accessor urlscan_api_key (): String?
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: 4.9.0
4
+ version: 4.10.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: 2022-10-01 00:00:00.000000000 Z
11
+ date: 2022-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -198,14 +198,14 @@ dependencies:
198
198
  requirements:
199
199
  - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: '1.1'
201
+ version: '1.2'
202
202
  type: :development
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: '1.1'
208
+ version: '1.2'
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: timecop
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -380,14 +380,14 @@ dependencies:
380
380
  requirements:
381
381
  - - '='
382
382
  - !ruby/object:Gem::Version
383
- version: 0.15.0
383
+ version: 0.16.0
384
384
  type: :runtime
385
385
  prerelease: false
386
386
  version_requirements: !ruby/object:Gem::Requirement
387
387
  requirements:
388
388
  - - '='
389
389
  - !ruby/object:Gem::Version
390
- version: 0.15.0
390
+ version: 0.16.0
391
391
  - !ruby/object:Gem::Dependency
392
392
  name: dry-container
393
393
  requirement: !ruby/object:Gem::Requirement
@@ -436,14 +436,14 @@ dependencies:
436
436
  requirements:
437
437
  - - '='
438
438
  - !ruby/object:Gem::Version
439
- version: 1.10.5
439
+ version: 1.10.6
440
440
  type: :runtime
441
441
  prerelease: false
442
442
  version_requirements: !ruby/object:Gem::Requirement
443
443
  requirements:
444
444
  - - '='
445
445
  - !ruby/object:Gem::Version
446
- version: 1.10.5
446
+ version: 1.10.6
447
447
  - !ruby/object:Gem::Dependency
448
448
  name: dry-struct
449
449
  requirement: !ruby/object:Gem::Requirement
@@ -856,14 +856,14 @@ dependencies:
856
856
  requirements:
857
857
  - - '='
858
858
  - !ruby/object:Gem::Version
859
- version: 5.4.2
859
+ version: 5.5.0
860
860
  type: :runtime
861
861
  prerelease: false
862
862
  version_requirements: !ruby/object:Gem::Requirement
863
863
  requirements:
864
864
  - - '='
865
865
  - !ruby/object:Gem::Version
866
- version: 5.4.2
866
+ version: 5.5.0
867
867
  - !ruby/object:Gem::Dependency
868
868
  name: shodanx
869
869
  requirement: !ruby/object:Gem::Requirement
@@ -892,20 +892,6 @@ dependencies:
892
892
  - - '='
893
893
  - !ruby/object:Gem::Version
894
894
  version: 2.4.0
895
- - !ruby/object:Gem::Dependency
896
- name: spysex
897
- requirement: !ruby/object:Gem::Requirement
898
- requirements:
899
- - - '='
900
- - !ruby/object:Gem::Version
901
- version: 0.2.0
902
- type: :runtime
903
- prerelease: false
904
- version_requirements: !ruby/object:Gem::Requirement
905
- requirements:
906
- - - '='
907
- - !ruby/object:Gem::Version
908
- version: 0.2.0
909
895
  - !ruby/object:Gem::Dependency
910
896
  name: sqlite3
911
897
  requirement: !ruby/object:Gem::Requirement