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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02c4e60250ffc8e40e4d0c08fd3721101ab943abdfeb1f73ec267cc345bc0dd2
4
- data.tar.gz: 5e65063ca7b9cc8c5b9c6d137abe6820abb6b179c3fb8582d1381d583eb27280
3
+ metadata.gz: 1f340898bd140d76041cde8c5cb266bcb379f056bac511fcd9de9a4dd20fc299
4
+ data.tar.gz: fb96310ecb6efb1dd5059feea692a8128bdff3610579473134653979c2f0512c
5
5
  SHA512:
6
- metadata.gz: 142cc9ec86582d37e7e5bd472f1a4f085582441e2204d406fa6ff9d2e94331cbc27513a410c00174950750e066ff9c53b100bd4cfe23039e4cb2be7d8f69ed33
7
- data.tar.gz: 49a02b02e298b94d8d847d74ea3389a3e873e72e17fdb93d1e5392992be05db73b37f6cea05ead35b04573400b6956e5b34d323008efb679fba60dcf53d6b372
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
- api.alert.create(
30
- title: title,
31
- description: description,
32
- artifacts: artifacts.map { |artifact| { data: artifact.data, data_type: artifact.data_type, message: description } },
33
- tags: tags,
34
- type: "external",
35
- source: "mihari"
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
- url = "#{base_url}/index.html"
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 = { 'content-type': "application/x-www-form-urlencoded" }
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mihari
4
- VERSION = "4.5.3"
4
+ VERSION = "4.6.0"
5
5
  end
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["BINARYEDGE_API_KEY"]
75
- setting :censys_id, default: ENV["CENSYS_ID"]
76
- setting :censys_secret, default: ENV["CENSYS_SECRET"]
77
- setting :circl_passive_password, default: ENV["CIRCL_PASSIVE_PASSWORD"]
78
- setting :circl_passive_username, default: ENV["CIRCL_PASSIVE_USERNAME"]
79
- setting :database, default: ENV["DATABASE"] || "mihari.db"
80
- setting :greynoise_api_key, default: ENV["GREYNOISE_API_KEY"]
81
- setting :ipinfo_api_key, default: ENV["IPINFO_API_KEY"]
82
- setting :misp_api_endpoint, default: ENV["MISP_API_ENDPOINT"]
83
- setting :misp_api_key, default: ENV["MISP_API_KEY"]
84
- setting :onyphe_api_key, default: ENV["ONYPHE_API_KEY"]
85
- setting :otx_api_key, default: ENV["OTX_API_KEY"]
86
- setting :passivetotal_api_key, default: ENV["PASSIVETOTAL_API_KEY"]
87
- setting :passivetotal_username, default: ENV["PASSIVETOTAL_USERNAME"]
88
- setting :pulsedive_api_key, default: ENV["PULSEDIVE_API_KEY"]
89
- setting :securitytrails_api_key, default: ENV["SECURITYTRAILS_API_KEY"]
90
- setting :shodan_api_key, default: ENV["SHODAN_API_KEY"]
91
- setting :slack_channel, default: ENV["SLACK_CHANNEL"]
92
- setting :slack_webhook_url, default: ENV["SLACK_WEBHOOK_URL"]
93
- setting :spyse_api_key, default: ENV["SPYSE_API_KEY"]
94
- setting :thehive_api_endpoint, default: ENV["THEHIVE_API_ENDPOINT"]
95
- setting :thehive_api_key, default: ENV["THEHIVE_API_KEY"]
96
- setting :urlscan_api_key, default: ENV["URLSCAN_API_KEY"]
97
- setting :virustotal_api_key, default: ENV["VIRUSTOTAL_API_KEY"]
98
- setting :webhook_url, default: ENV["WEBHOOK_URL"]
99
- setting :webhook_use_json_body, constructor: ->(value = ENV["WEBHOOK_USE_JSON_BODY"]) { truthy?(value) }
100
- setting :zoomeye_api_key, default: ENV["ZOOMEYE_API_KEY"]
101
- setting :sentry_dsn, default: ENV["SENTRY_DSN"]
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.11"
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.2.4"
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.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", "1.0.0"
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.10.0"
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.5.3
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-08 00:00:00.000000000 Z
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.11'
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.11'
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.2.4
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.2.4
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.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.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: 1.0.0
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: 1.0.0
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.10.0
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.10.0
866
+ version: 4.11.0
867
867
  - !ruby/object:Gem::Dependency
868
868
  name: sentry-ruby
869
869
  requirement: !ruby/object:Gem::Requirement