mihari 4.5.3 → 4.6.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 +4 -4
- data/lib/mihari/emitters/the_hive.rb +69 -10
- data/lib/mihari/emitters/webhook.rb +1 -1
- data/lib/mihari/schemas/emitter.rb +1 -0
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari.rb +49 -28
- data/mihari.gemspec +5 -5
- data/sig/lib/mihari/emitters/the_hive.rbs +4 -0
- data/sig/lib/mihari.rbs +1 -0
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f340898bd140d76041cde8c5cb266bcb379f056bac511fcd9de9a4dd20fc299
|
4
|
+
data.tar.gz: fb96310ecb6efb1dd5059feea692a8128bdff3610579473134653979c2f0512c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d9758d027fc056f52be261fb2d7c6fa81dc402d4f47c01a8e49c93e1bc084a501af74c0e51c73ac2967c7795529130f1c34801661f1a9935075e197eaf446b0
|
7
|
+
data.tar.gz: e48d29aa3756a260cc273f9b05e65aa28e6e9e67f377fcc9c4ff722931f7789f363478c9a33470aea41a1bd72a9c9e73c05b76583d52bdb80096c2fdaf627b54
|
@@ -11,11 +11,15 @@ module Mihari
|
|
11
11
|
# @return [String, nil]
|
12
12
|
attr_reader :api_key
|
13
13
|
|
14
|
+
# @return [String, nil]
|
15
|
+
attr_reader :api_version
|
16
|
+
|
14
17
|
def initialize(*args, **kwargs)
|
15
18
|
super(*args, **kwargs)
|
16
19
|
|
17
20
|
@api_endpoint = kwargs[:api_endpoint] || Mihari.config.thehive_api_endpoint
|
18
21
|
@api_key = kwargs[:api_key] || Mihari.config.thehive_api_key
|
22
|
+
@api_version = kwargs[:api_version] || Mihari.config.thehive_api_version
|
19
23
|
end
|
20
24
|
|
21
25
|
# @return [Boolean]
|
@@ -26,14 +30,28 @@ module Mihari
|
|
26
30
|
def emit(title:, description:, artifacts:, tags: [], **_options)
|
27
31
|
return if artifacts.empty?
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
payload = payload(title: title, description: description, artifacts: artifacts, tags: tags)
|
34
|
+
api.alert.create(**payload)
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Normalize API version for API client
|
39
|
+
#
|
40
|
+
# @param [String] version
|
41
|
+
#
|
42
|
+
# @return [String, nil]
|
43
|
+
#
|
44
|
+
def normalized_api_version
|
45
|
+
@normalized_api_version ||= [].tap do |out|
|
46
|
+
# v4 does not have version prefix in path (/api/)
|
47
|
+
# v5 has version prefix in path (/api/v1/)
|
48
|
+
table = {
|
49
|
+
"" => nil,
|
50
|
+
"v4" => nil,
|
51
|
+
"v5" => "v1"
|
52
|
+
}
|
53
|
+
out << table[api_version.to_s.downcase]
|
54
|
+
end.first
|
37
55
|
end
|
38
56
|
|
39
57
|
private
|
@@ -43,7 +61,7 @@ module Mihari
|
|
43
61
|
end
|
44
62
|
|
45
63
|
def api
|
46
|
-
@api ||= Hachi::API.new(api_endpoint: api_endpoint, api_key: api_key)
|
64
|
+
@api ||= Hachi::API.new(api_endpoint: api_endpoint, api_key: api_key, api_version: normalized_api_version)
|
47
65
|
end
|
48
66
|
|
49
67
|
#
|
@@ -64,6 +82,35 @@ module Mihari
|
|
64
82
|
!api_key.nil?
|
65
83
|
end
|
66
84
|
|
85
|
+
def payload(title:, description:, artifacts:, tags: [])
|
86
|
+
return v4_payload(title: title, description: description, artifacts: artifacts, tags: tags) if normalized_api_version.nil?
|
87
|
+
|
88
|
+
v5_payload(title: title, description: description, artifacts: artifacts, tags: tags)
|
89
|
+
end
|
90
|
+
|
91
|
+
def v4_payload(title:, description:, artifacts:, tags: [])
|
92
|
+
{
|
93
|
+
title: title,
|
94
|
+
description: description,
|
95
|
+
artifacts: artifacts.map { |artifact| { data: artifact.data, data_type: artifact.data_type, message: description } },
|
96
|
+
tags: tags,
|
97
|
+
type: "external",
|
98
|
+
source: "mihari"
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def v5_payload(title:, description:, artifacts:, tags: [])
|
103
|
+
{
|
104
|
+
title: title,
|
105
|
+
description: description,
|
106
|
+
observables: artifacts.map { |artifact| { data: artifact.data, data_type: artifact.data_type, message: description } },
|
107
|
+
tags: tags,
|
108
|
+
type: "external",
|
109
|
+
source: "mihari",
|
110
|
+
source_ref: "1"
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
67
114
|
#
|
68
115
|
# Check whether an API endpoint is reachable or not
|
69
116
|
#
|
@@ -71,9 +118,21 @@ module Mihari
|
|
71
118
|
#
|
72
119
|
def ping?
|
73
120
|
base_url = api_endpoint.end_with?("/") ? api_endpoint[0..-2] : api_endpoint
|
74
|
-
|
121
|
+
|
122
|
+
if normalized_api_version.nil?
|
123
|
+
# for v4
|
124
|
+
base_url = api_endpoint.end_with?("/") ? api_endpoint[0..-2] : api_endpoint
|
125
|
+
url = "#{base_url}/index.html"
|
126
|
+
else
|
127
|
+
# for v5
|
128
|
+
url = "#{base_url}/api/v1/status/public"
|
129
|
+
end
|
75
130
|
|
76
131
|
http = Net::Ping::HTTP.new(url)
|
132
|
+
|
133
|
+
# use GET for v5
|
134
|
+
http.get_request = true if normalized_api_version
|
135
|
+
|
77
136
|
http.ping?
|
78
137
|
end
|
79
138
|
end
|
@@ -11,7 +11,7 @@ module Mihari
|
|
11
11
|
def emit(title:, description:, artifacts:, source:, tags:)
|
12
12
|
return if artifacts.empty?
|
13
13
|
|
14
|
-
headers = {
|
14
|
+
headers = { "content-type": "application/x-www-form-urlencoded" }
|
15
15
|
headers["content-type"] = "application/json" if use_json_body?
|
16
16
|
|
17
17
|
emitter = Emitters::HTTP.new(uri: Mihari.config.webhook_url)
|
@@ -16,6 +16,7 @@ module Mihari
|
|
16
16
|
required(:emitter).value(Types::String.enum("the_hive"))
|
17
17
|
optional(:api_endpoint).value(:string)
|
18
18
|
optional(:api_key).value(:string)
|
19
|
+
optional(:api_version).value(Types::String.enum("v4", "v5")).default("v4")
|
19
20
|
end
|
20
21
|
|
21
22
|
Slack = Dry::Schema.Params do
|
data/lib/mihari/version.rb
CHANGED
data/lib/mihari.rb
CHANGED
@@ -71,34 +71,55 @@ end
|
|
71
71
|
module Mihari
|
72
72
|
extend Dry::Configurable
|
73
73
|
|
74
|
-
setting :binaryedge_api_key, default: ENV
|
75
|
-
|
76
|
-
setting :
|
77
|
-
setting :
|
78
|
-
|
79
|
-
setting :
|
80
|
-
setting :
|
81
|
-
|
82
|
-
setting :
|
83
|
-
|
84
|
-
setting :
|
85
|
-
|
86
|
-
setting :
|
87
|
-
|
88
|
-
setting :
|
89
|
-
setting :
|
90
|
-
|
91
|
-
setting :
|
92
|
-
|
93
|
-
setting :
|
94
|
-
|
95
|
-
setting :
|
96
|
-
setting :
|
97
|
-
|
98
|
-
setting :
|
99
|
-
|
100
|
-
setting :
|
101
|
-
|
74
|
+
setting :binaryedge_api_key, default: ENV.fetch("BINARYEDGE_API_KEY", nil)
|
75
|
+
|
76
|
+
setting :censys_id, default: ENV.fetch("CENSYS_ID", nil)
|
77
|
+
setting :censys_secret, default: ENV.fetch("CENSYS_SECRET", nil)
|
78
|
+
|
79
|
+
setting :circl_passive_password, default: ENV.fetch("CIRCL_PASSIVE_PASSWORD", nil)
|
80
|
+
setting :circl_passive_username, default: ENV.fetch("CIRCL_PASSIVE_USERNAME", nil)
|
81
|
+
|
82
|
+
setting :database, default: ENV.fetch("DATABASE", "mihari.db")
|
83
|
+
|
84
|
+
setting :greynoise_api_key, default: ENV.fetch("GREYNOISE_API_KEY", nil)
|
85
|
+
|
86
|
+
setting :ipinfo_api_key, default: ENV.fetch("IPINFO_API_KEY", nil)
|
87
|
+
|
88
|
+
setting :misp_api_endpoint, default: ENV.fetch("MISP_API_ENDPOINT", nil)
|
89
|
+
setting :misp_api_key, default: ENV.fetch("MISP_API_KEY", nil)
|
90
|
+
|
91
|
+
setting :onyphe_api_key, default: ENV.fetch("ONYPHE_API_KEY", nil)
|
92
|
+
|
93
|
+
setting :otx_api_key, default: ENV.fetch("OTX_API_KEY", nil)
|
94
|
+
|
95
|
+
setting :passivetotal_api_key, default: ENV.fetch("PASSIVETOTAL_API_KEY", nil)
|
96
|
+
setting :passivetotal_username, default: ENV.fetch("PASSIVETOTAL_USERNAME", nil)
|
97
|
+
|
98
|
+
setting :pulsedive_api_key, default: ENV.fetch("PULSEDIVE_API_KEY", nil)
|
99
|
+
|
100
|
+
setting :securitytrails_api_key, default: ENV.fetch("SECURITYTRAILS_API_KEY", nil)
|
101
|
+
|
102
|
+
setting :shodan_api_key, default: ENV.fetch("SHODAN_API_KEY", nil)
|
103
|
+
|
104
|
+
setting :slack_channel, default: ENV.fetch("SLACK_CHANNEL", nil)
|
105
|
+
setting :slack_webhook_url, default: ENV.fetch("SLACK_WEBHOOK_URL", nil)
|
106
|
+
|
107
|
+
setting :spyse_api_key, default: ENV.fetch("SPYSE_API_KEY", nil)
|
108
|
+
|
109
|
+
setting :thehive_api_endpoint, default: ENV.fetch("THEHIVE_API_ENDPOINT", nil)
|
110
|
+
setting :thehive_api_key, default: ENV.fetch("THEHIVE_API_KEY", nil)
|
111
|
+
setting :thehive_api_version, default: ENV.fetch("THEHIVE_API_VERSION", nil)
|
112
|
+
|
113
|
+
setting :urlscan_api_key, default: ENV.fetch("URLSCAN_API_KEY", nil)
|
114
|
+
|
115
|
+
setting :virustotal_api_key, default: ENV.fetch("VIRUSTOTAL_API_KEY", nil)
|
116
|
+
|
117
|
+
setting :webhook_url, default: ENV.fetch("WEBHOOK_URL", nil)
|
118
|
+
setting :webhook_use_json_body, constructor: ->(value = ENV.fetch("WEBHOOK_USE_JSON_BODY", nil)) { truthy?(value) }
|
119
|
+
|
120
|
+
setting :zoomeye_api_key, default: ENV.fetch("ZOOMEYE_API_KEY", nil)
|
121
|
+
|
122
|
+
setting :sentry_dsn, default: ENV.fetch("SENTRY_DSN", nil)
|
102
123
|
|
103
124
|
class << self
|
104
125
|
include Memist::Memoizable
|
data/mihari.gemspec
CHANGED
@@ -39,13 +39,13 @@ Gem::Specification.new do |spec|
|
|
39
39
|
spec.add_development_dependency "rerun", "~> 0.13"
|
40
40
|
spec.add_development_dependency "rspec", "~> 3.11"
|
41
41
|
spec.add_development_dependency "simplecov-lcov", "~> 0.8.0"
|
42
|
-
spec.add_development_dependency "standard", "~> 1.
|
42
|
+
spec.add_development_dependency "standard", "~> 1.12"
|
43
43
|
spec.add_development_dependency "steep", "~> 0.52"
|
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.14"
|
47
47
|
|
48
|
-
spec.add_dependency "activerecord", "7.0.
|
48
|
+
spec.add_dependency "activerecord", "7.0.3"
|
49
49
|
spec.add_dependency "addressable", "2.8.0"
|
50
50
|
spec.add_dependency "awrence", "2.0.1"
|
51
51
|
spec.add_dependency "binaryedge", "0.1.0"
|
@@ -61,13 +61,13 @@ Gem::Specification.new do |spec|
|
|
61
61
|
spec.add_dependency "dry-schema", "1.9.1"
|
62
62
|
spec.add_dependency "dry-struct", "1.4.0"
|
63
63
|
spec.add_dependency "dry-validation", "1.8.0"
|
64
|
-
spec.add_dependency "email_address", "0.2.
|
64
|
+
spec.add_dependency "email_address", "0.2.3"
|
65
65
|
spec.add_dependency "grape", "1.6.2"
|
66
66
|
spec.add_dependency "grape-entity", "0.10.1"
|
67
67
|
spec.add_dependency "grape-swagger", "1.4.2"
|
68
68
|
spec.add_dependency "grape-swagger-entity", "0.5.1"
|
69
69
|
spec.add_dependency "greynoise", "0.1.1"
|
70
|
-
spec.add_dependency "hachi", "
|
70
|
+
spec.add_dependency "hachi", "2.0.0"
|
71
71
|
spec.add_dependency "insensitive_hash", "0.3.3"
|
72
72
|
spec.add_dependency "jr-cli", "0.5.1"
|
73
73
|
spec.add_dependency "launchy", "2.5.0"
|
@@ -88,7 +88,7 @@ Gem::Specification.new do |spec|
|
|
88
88
|
spec.add_dependency "rack-contrib", "2.3.0"
|
89
89
|
spec.add_dependency "rack-cors", "1.1.1"
|
90
90
|
spec.add_dependency "securitytrails", "1.0.0"
|
91
|
-
spec.add_dependency "semantic_logger", "4.
|
91
|
+
spec.add_dependency "semantic_logger", "4.11.0"
|
92
92
|
spec.add_dependency "sentry-ruby", "5.3.0"
|
93
93
|
spec.add_dependency "shodanx", "0.2.1"
|
94
94
|
spec.add_dependency "slack-notifier", "2.4.0"
|
@@ -5,11 +5,15 @@ module Mihari
|
|
5
5
|
|
6
6
|
attr_reader api_key: String?
|
7
7
|
|
8
|
+
attr_reader api_version: String?
|
9
|
+
|
8
10
|
# @return [true, false]
|
9
11
|
def valid?: () -> bool
|
10
12
|
|
11
13
|
def emit: (title: untyped title, description: untyped description, artifacts: untyped artifacts, ?tags: untyped tags, **untyped _options) -> (nil | untyped)
|
12
14
|
|
15
|
+
def normalized_api_version: () -> String?
|
16
|
+
|
13
17
|
private
|
14
18
|
|
15
19
|
def configuration_keys: () -> ::Array["thehive_api_endpoint" | "thehive_api_key"]
|
data/sig/lib/mihari.rbs
CHANGED
@@ -19,6 +19,7 @@ class Configuration
|
|
19
19
|
attr_accessor spyse_api_key (): String?
|
20
20
|
attr_accessor thehive_api_endpoint (): String?
|
21
21
|
attr_accessor thehive_api_key (): String?
|
22
|
+
attr_accessor thehive_api_version (): String?
|
22
23
|
attr_accessor urlscan_api_key (): String?
|
23
24
|
attr_accessor virustotal_api_key (): String?
|
24
25
|
attr_accessor zoomeye_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.
|
4
|
+
version: 4.6.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-05-
|
11
|
+
date: 2022-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -184,14 +184,14 @@ dependencies:
|
|
184
184
|
requirements:
|
185
185
|
- - "~>"
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version: '1.
|
187
|
+
version: '1.12'
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version: '1.
|
194
|
+
version: '1.12'
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: steep
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -254,14 +254,14 @@ dependencies:
|
|
254
254
|
requirements:
|
255
255
|
- - '='
|
256
256
|
- !ruby/object:Gem::Version
|
257
|
-
version: 7.0.
|
257
|
+
version: 7.0.3
|
258
258
|
type: :runtime
|
259
259
|
prerelease: false
|
260
260
|
version_requirements: !ruby/object:Gem::Requirement
|
261
261
|
requirements:
|
262
262
|
- - '='
|
263
263
|
- !ruby/object:Gem::Version
|
264
|
-
version: 7.0.
|
264
|
+
version: 7.0.3
|
265
265
|
- !ruby/object:Gem::Dependency
|
266
266
|
name: addressable
|
267
267
|
requirement: !ruby/object:Gem::Requirement
|
@@ -478,14 +478,14 @@ dependencies:
|
|
478
478
|
requirements:
|
479
479
|
- - '='
|
480
480
|
- !ruby/object:Gem::Version
|
481
|
-
version: 0.2.
|
481
|
+
version: 0.2.3
|
482
482
|
type: :runtime
|
483
483
|
prerelease: false
|
484
484
|
version_requirements: !ruby/object:Gem::Requirement
|
485
485
|
requirements:
|
486
486
|
- - '='
|
487
487
|
- !ruby/object:Gem::Version
|
488
|
-
version: 0.2.
|
488
|
+
version: 0.2.3
|
489
489
|
- !ruby/object:Gem::Dependency
|
490
490
|
name: grape
|
491
491
|
requirement: !ruby/object:Gem::Requirement
|
@@ -562,14 +562,14 @@ dependencies:
|
|
562
562
|
requirements:
|
563
563
|
- - '='
|
564
564
|
- !ruby/object:Gem::Version
|
565
|
-
version:
|
565
|
+
version: 2.0.0
|
566
566
|
type: :runtime
|
567
567
|
prerelease: false
|
568
568
|
version_requirements: !ruby/object:Gem::Requirement
|
569
569
|
requirements:
|
570
570
|
- - '='
|
571
571
|
- !ruby/object:Gem::Version
|
572
|
-
version:
|
572
|
+
version: 2.0.0
|
573
573
|
- !ruby/object:Gem::Dependency
|
574
574
|
name: insensitive_hash
|
575
575
|
requirement: !ruby/object:Gem::Requirement
|
@@ -856,14 +856,14 @@ dependencies:
|
|
856
856
|
requirements:
|
857
857
|
- - '='
|
858
858
|
- !ruby/object:Gem::Version
|
859
|
-
version: 4.
|
859
|
+
version: 4.11.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: 4.
|
866
|
+
version: 4.11.0
|
867
867
|
- !ruby/object:Gem::Dependency
|
868
868
|
name: sentry-ruby
|
869
869
|
requirement: !ruby/object:Gem::Requirement
|