mihari 4.9.0 → 4.10.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: 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