hachi 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +10 -13
- data/.gitignore +5 -1
- data/README.md +10 -84
- data/hachi.gemspec +7 -5
- data/lib/hachi/api.rb +31 -7
- data/lib/hachi/awrence/methods.rb +66 -0
- data/lib/hachi/clients/alert.rb +9 -119
- data/lib/hachi/clients/artifact.rb +3 -38
- data/lib/hachi/clients/base.rb +28 -26
- data/lib/hachi/clients/case.rb +9 -102
- data/lib/hachi/clients/observable.rb +53 -0
- data/lib/hachi/clients/query.rb +18 -0
- data/lib/hachi/clients/user.rb +6 -16
- data/lib/hachi/version.rb +1 -1
- data/lib/hachi.rb +15 -6
- metadata +45 -23
- data/lib/hachi/models/alert.rb +0 -63
- data/lib/hachi/models/artifact.rb +0 -40
- data/lib/hachi/models/base.rb +0 -31
- data/lib/hachi/models/case.rb +0 -54
- data/lib/hachi/models/user.rb +0 -36
- data/samples/01_create_an_alert.rb +0 -17
- data/samples/02_search_artifacts.rb +0 -16
- data/samples/03_list_cases.rb +0 -16
- data/samples/04_merge_alerts.rb +0 -17
data/lib/hachi/clients/base.rb
CHANGED
@@ -7,11 +7,21 @@ require "uri"
|
|
7
7
|
module Hachi
|
8
8
|
module Clients
|
9
9
|
class Base
|
10
|
-
|
10
|
+
# @return [String]
|
11
|
+
attr_reader :api_endpoint
|
11
12
|
|
12
|
-
|
13
|
+
# @return [String]
|
14
|
+
attr_reader :api_key
|
15
|
+
|
16
|
+
# @return [String, nil]
|
17
|
+
attr_reader :api_version
|
18
|
+
|
19
|
+
include Hachi::Awrence::Methods
|
20
|
+
|
21
|
+
def initialize(api_endpoint:, api_key:, api_version:)
|
13
22
|
@api_endpoint = URI(api_endpoint)
|
14
23
|
@api_key = api_key
|
24
|
+
@api_version = api_version
|
15
25
|
end
|
16
26
|
|
17
27
|
def get(path, params: {}, &block)
|
@@ -27,6 +37,8 @@ module Hachi
|
|
27
37
|
url = url_for(path)
|
28
38
|
url.query = URI.encode_www_form(params) unless params.empty?
|
29
39
|
|
40
|
+
json = to_camelback_keys(json.compact) if json.is_a?(Hash)
|
41
|
+
|
30
42
|
post = Net::HTTP::Post.new(url)
|
31
43
|
post.body = json.is_a?(Hash) ? json.to_json : json.to_s
|
32
44
|
|
@@ -40,6 +52,8 @@ module Hachi
|
|
40
52
|
url = url_for(path)
|
41
53
|
url.query = URI.encode_www_form(params) unless params.empty?
|
42
54
|
|
55
|
+
json = to_camelback_keys(json.compact) if json.is_a?(Hash)
|
56
|
+
|
43
57
|
delete = Net::HTTP::Delete.new(url)
|
44
58
|
delete.body = json.is_a?(Hash) ? json.to_json : json.to_s
|
45
59
|
|
@@ -51,6 +65,8 @@ module Hachi
|
|
51
65
|
url = url_for(path)
|
52
66
|
url.query = URI.encode_www_form(params) unless params.empty?
|
53
67
|
|
68
|
+
json = to_camelback_keys(json.compact) if json.is_a?(Hash)
|
69
|
+
|
54
70
|
patch = Net::HTTP::Patch.new(url)
|
55
71
|
patch.body = json.is_a?(Hash) ? json.to_json : json.to_s
|
56
72
|
|
@@ -63,7 +79,11 @@ module Hachi
|
|
63
79
|
private
|
64
80
|
|
65
81
|
def base_url
|
66
|
-
|
82
|
+
if api_version.nil? || api_version.to_s.empty?
|
83
|
+
"#{api_endpoint.scheme}://#{api_endpoint.hostname}:#{api_endpoint.port}/api"
|
84
|
+
else
|
85
|
+
"#{api_endpoint.scheme}://#{api_endpoint.hostname}:#{api_endpoint.port}/api/#{api_version}"
|
86
|
+
end
|
67
87
|
end
|
68
88
|
|
69
89
|
def url_for(path)
|
@@ -73,13 +93,13 @@ module Hachi
|
|
73
93
|
def https_options
|
74
94
|
return nil if api_endpoint.scheme != "https"
|
75
95
|
|
76
|
-
if proxy = ENV
|
96
|
+
if proxy = ENV.fetch("HTTPS_PROXY") { ENV.fetch("https_proxy", nil) }
|
77
97
|
uri = URI(proxy)
|
78
98
|
{
|
79
99
|
proxy_address: uri.hostname,
|
80
100
|
proxy_port: uri.port,
|
81
101
|
proxy_from_env: false,
|
82
|
-
use_ssl: true
|
102
|
+
use_ssl: true
|
83
103
|
}
|
84
104
|
else
|
85
105
|
{ use_ssl: true }
|
@@ -87,12 +107,12 @@ module Hachi
|
|
87
107
|
end
|
88
108
|
|
89
109
|
def http_options
|
90
|
-
if proxy = ENV
|
110
|
+
if proxy = ENV.fetch("HTTP_PROXY") { ENV.fetch("http_proxy", nil) }
|
91
111
|
uri = URI(proxy)
|
92
112
|
{
|
93
113
|
proxy_address: uri.hostname,
|
94
114
|
proxy_port: uri.port,
|
95
|
-
proxy_from_env: false
|
115
|
+
proxy_from_env: false
|
96
116
|
}
|
97
117
|
else
|
98
118
|
{}
|
@@ -119,26 +139,8 @@ module Hachi
|
|
119
139
|
end
|
120
140
|
end
|
121
141
|
|
122
|
-
def validate_range(range)
|
123
|
-
return true if range == "all"
|
124
|
-
raise ArgumentError, "range should be 'all' or `from-to`" unless range.match?(/(\d+)-(\d+)/)
|
125
|
-
|
126
|
-
from, to = range.split("-").map(&:to_i)
|
127
|
-
return true if from < to
|
128
|
-
|
129
|
-
raise ArgumentError, "from should be smaller than to"
|
130
|
-
end
|
131
|
-
|
132
|
-
def _search(path, query:, range: "all", sort: nil)
|
133
|
-
validate_range range
|
134
|
-
|
135
|
-
query_string = build_query_string(range: range, sort: sort)
|
136
|
-
|
137
|
-
post("#{path}?#{query_string}", json: { query: query }) { |json| json }
|
138
|
-
end
|
139
|
-
|
140
142
|
def build_query_string(params)
|
141
|
-
URI.encode_www_form(params.
|
143
|
+
URI.encode_www_form(params.compact)
|
142
144
|
end
|
143
145
|
end
|
144
146
|
end
|
data/lib/hachi/clients/case.rb
CHANGED
@@ -3,15 +3,6 @@
|
|
3
3
|
module Hachi
|
4
4
|
module Clients
|
5
5
|
class Case < Base
|
6
|
-
#
|
7
|
-
# List cases
|
8
|
-
#
|
9
|
-
# @return [Array]
|
10
|
-
#
|
11
|
-
def list
|
12
|
-
get("/api/case") { |json| json }
|
13
|
-
end
|
14
|
-
|
15
6
|
#
|
16
7
|
# Get a case
|
17
8
|
#
|
@@ -20,7 +11,7 @@ module Hachi
|
|
20
11
|
# @return [Hash]
|
21
12
|
#
|
22
13
|
def get_by_id(id)
|
23
|
-
get("/
|
14
|
+
get("/case/#{id}") { |json| json }
|
24
15
|
end
|
25
16
|
|
26
17
|
#
|
@@ -31,114 +22,30 @@ module Hachi
|
|
31
22
|
# @return [String]
|
32
23
|
#
|
33
24
|
def delete_by_id(id)
|
34
|
-
delete("/
|
25
|
+
delete("/case/#{id}") { |json| json }
|
35
26
|
end
|
36
27
|
|
37
28
|
#
|
38
29
|
# Create a case
|
39
30
|
#
|
40
|
-
# @param [
|
41
|
-
# @param [String, nil] description
|
42
|
-
# @param [Integer, nil] severity
|
43
|
-
# @param [String, nil] start_date
|
44
|
-
# @param [String, nil] owner
|
45
|
-
# @param [Boolean, nil] flag
|
46
|
-
# @param [Intege, nil] tlp
|
47
|
-
# @param [String, nil] tags
|
48
|
-
#
|
49
|
-
# @return [Hash]
|
50
|
-
#
|
51
|
-
def create(title:, description:, severity: nil, start_date: nil, owner: nil, flag: nil, tlp: nil, tags: nil)
|
52
|
-
kase = Models::Case.new(
|
53
|
-
title: title,
|
54
|
-
description: description,
|
55
|
-
severity: severity,
|
56
|
-
start_date: start_date,
|
57
|
-
owner: owner,
|
58
|
-
flag: flag,
|
59
|
-
tlp: tlp,
|
60
|
-
tags: tags,
|
61
|
-
)
|
62
|
-
|
63
|
-
post("/api/case", json: kase.payload) { |json| json }
|
64
|
-
end
|
65
|
-
|
66
|
-
#
|
67
|
-
# Find cases
|
68
|
-
#
|
69
|
-
# @param [Hash] query
|
70
|
-
# @param [String] range
|
71
|
-
#
|
72
|
-
# @return [Hash]
|
73
|
-
#
|
74
|
-
def search(query, range: "all")
|
75
|
-
_search("/api/case/_search", query: query, range: range) { |json| json }
|
76
|
-
end
|
77
|
-
|
78
|
-
#
|
79
|
-
# Get list of cases linked to this case
|
80
|
-
#
|
81
|
-
# @param [String] id Case ID
|
82
|
-
#
|
83
|
-
# @return [Array]
|
84
|
-
#
|
85
|
-
def links(id)
|
86
|
-
get("/api/case/#{id}/links") { |json| json }
|
87
|
-
end
|
88
|
-
|
89
|
-
#
|
90
|
-
# Merge two cases
|
91
|
-
#
|
92
|
-
# @param [String] id1 Case ID
|
93
|
-
# @param [String] id2 Case ID
|
31
|
+
# @param [Hash] payload
|
94
32
|
#
|
95
33
|
# @return [Hash]
|
96
34
|
#
|
97
|
-
def
|
98
|
-
post("/
|
35
|
+
def create(**payload)
|
36
|
+
post("/case", json: payload) { |json| json }
|
99
37
|
end
|
100
38
|
|
101
39
|
#
|
102
40
|
# Update a case
|
103
41
|
#
|
104
|
-
# @param [String
|
105
|
-
# @param [
|
106
|
-
# @param [String, nil] description
|
107
|
-
# @param [String, nil] severity
|
108
|
-
# @param [String, nil] start_date
|
109
|
-
# @param [String, nil] owner
|
110
|
-
# @param [Boolean, nil] flag
|
111
|
-
# @param [Integer, nil] tlp
|
112
|
-
# @param [String, nil] tags
|
113
|
-
# @param [String, nil] status
|
114
|
-
# @param [String, nil] resolution_status
|
115
|
-
# @param [String, nil] impact_status
|
116
|
-
# @param [String, nil] summary
|
117
|
-
# @param [String, nil] end_date
|
118
|
-
# @param [String, nil] metrics
|
119
|
-
# @param [String, nil] custom_fields
|
42
|
+
# @param [String] id
|
43
|
+
# @param [Hash] payload
|
120
44
|
#
|
121
45
|
# @return [Hash]
|
122
46
|
#
|
123
|
-
def update(id,
|
124
|
-
|
125
|
-
title: title,
|
126
|
-
description: description,
|
127
|
-
severity: severity,
|
128
|
-
startDate: start_date,
|
129
|
-
owner: owner,
|
130
|
-
flag: flag,
|
131
|
-
tlp: tlp,
|
132
|
-
tags: tags,
|
133
|
-
status: status,
|
134
|
-
resolutionStatus: resolution_status,
|
135
|
-
impactStatus: impact_status,
|
136
|
-
summary: summary,
|
137
|
-
endDate: end_date,
|
138
|
-
metrics: metrics,
|
139
|
-
customFields: custom_fields
|
140
|
-
}.compact
|
141
|
-
patch("/api/case/#{id}", json: attributes) { |json| json }
|
47
|
+
def update(id, **payload)
|
48
|
+
patch("/case/#{id}", json: payload) { |json| json }
|
142
49
|
end
|
143
50
|
end
|
144
51
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hachi
|
4
|
+
module Clients
|
5
|
+
class Observable < Base
|
6
|
+
#
|
7
|
+
# Create an observable in a case
|
8
|
+
#
|
9
|
+
# @param [String] case_id Observable ID
|
10
|
+
# @param [Hash] payload
|
11
|
+
#
|
12
|
+
# @return [Hash]
|
13
|
+
#
|
14
|
+
def create_in_case(case_id, **payload)
|
15
|
+
post("/case/#{case_id}/observable", json: payload) { |json| json }
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Create an observable in an alert
|
20
|
+
#
|
21
|
+
# @param [String] alert_id Observable ID
|
22
|
+
# @param [Hash] payload
|
23
|
+
#
|
24
|
+
# @return [Hash]
|
25
|
+
#
|
26
|
+
def create_in_alert(alert_id, **payload)
|
27
|
+
post("/alert/#{alert_id}/observable", json: payload) { |json| json }
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Get an observable
|
32
|
+
#
|
33
|
+
# @param [String] id observable ID
|
34
|
+
#
|
35
|
+
# @return [Hash]
|
36
|
+
#
|
37
|
+
def get_by_id(id)
|
38
|
+
get("/observable/#{id}") { |json| json }
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Delete an observable
|
43
|
+
#
|
44
|
+
# @param [String] id observable ID
|
45
|
+
#
|
46
|
+
# @return [String]
|
47
|
+
#
|
48
|
+
def delete_by_id(id)
|
49
|
+
delete("/observable/#{id}") { |json| json }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hachi
|
4
|
+
module Clients
|
5
|
+
class Query < Base
|
6
|
+
#
|
7
|
+
# Query
|
8
|
+
#
|
9
|
+
# @param [Hash] payload
|
10
|
+
#
|
11
|
+
# @return [Hash]
|
12
|
+
#
|
13
|
+
def query(**payload)
|
14
|
+
post("/query", json: payload) { |json| json }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/hachi/clients/user.rb
CHANGED
@@ -9,7 +9,7 @@ module Hachi
|
|
9
9
|
# @return [Hash]
|
10
10
|
#
|
11
11
|
def current
|
12
|
-
get("/
|
12
|
+
get("/user/current") { |json| json }
|
13
13
|
end
|
14
14
|
|
15
15
|
#
|
@@ -20,7 +20,7 @@ module Hachi
|
|
20
20
|
# @return [Hash]
|
21
21
|
#
|
22
22
|
def get_by_id(id)
|
23
|
-
get("/
|
23
|
+
get("/user/#{id}") { |json| json }
|
24
24
|
end
|
25
25
|
|
26
26
|
#
|
@@ -31,28 +31,18 @@ module Hachi
|
|
31
31
|
# @return [String]
|
32
32
|
#
|
33
33
|
def delete_by_id(id)
|
34
|
-
delete("/
|
34
|
+
delete("/user/#{id}") { |json| json }
|
35
35
|
end
|
36
36
|
|
37
37
|
#
|
38
38
|
# Create a user
|
39
39
|
#
|
40
|
-
# @param [
|
41
|
-
# @param [String] name
|
42
|
-
# @param [Array<String>] roles
|
43
|
-
# @param [String] password
|
40
|
+
# @param [Hash] payload
|
44
41
|
#
|
45
42
|
# @return [Hash]
|
46
43
|
#
|
47
|
-
def create(
|
48
|
-
user
|
49
|
-
login: login,
|
50
|
-
name: name,
|
51
|
-
roles: roles,
|
52
|
-
password: password
|
53
|
-
)
|
54
|
-
|
55
|
-
post("/api/user", json: user.payload) { |json| json }
|
44
|
+
def create(**payload)
|
45
|
+
post("/user", json: payload) { |json| json }
|
56
46
|
end
|
57
47
|
end
|
58
48
|
end
|
data/lib/hachi/version.rb
CHANGED
data/lib/hachi.rb
CHANGED
@@ -2,20 +2,29 @@
|
|
2
2
|
|
3
3
|
require "hachi/version"
|
4
4
|
|
5
|
-
require "hachi/
|
5
|
+
require "hachi/awrence/methods"
|
6
6
|
|
7
|
-
require "hachi/
|
8
|
-
require "hachi/models/alert"
|
9
|
-
require "hachi/models/artifact"
|
10
|
-
require "hachi/models/case"
|
11
|
-
require "hachi/models/user"
|
7
|
+
require "hachi/api"
|
12
8
|
|
13
9
|
require "hachi/clients/base"
|
10
|
+
|
14
11
|
require "hachi/clients/alert"
|
15
12
|
require "hachi/clients/artifact"
|
16
13
|
require "hachi/clients/case"
|
14
|
+
require "hachi/clients/observable"
|
15
|
+
require "hachi/clients/query"
|
17
16
|
require "hachi/clients/user"
|
18
17
|
|
19
18
|
module Hachi
|
19
|
+
module Awrence
|
20
|
+
class << self
|
21
|
+
attr_writer :acronyms
|
22
|
+
|
23
|
+
def acronyms
|
24
|
+
@acronyms ||= {}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
20
29
|
class Error < StandardError; end
|
21
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hachi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.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:
|
11
|
+
date: 2022-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,28 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '2.
|
19
|
+
version: '2.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '2.
|
26
|
+
version: '2.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: coveralls_reborn
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
33
|
+
version: '0.24'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0.
|
40
|
+
version: '0.24'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dotenv
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.7'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.7'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,42 +72,56 @@ dependencies:
|
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '3.
|
75
|
+
version: '3.11'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.11'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov-lcov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.8.0
|
62
90
|
type: :development
|
63
91
|
prerelease: false
|
64
92
|
version_requirements: !ruby/object:Gem::Requirement
|
65
93
|
requirements:
|
66
94
|
- - "~>"
|
67
95
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
96
|
+
version: 0.8.0
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: vcr
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
72
100
|
requirements:
|
73
101
|
- - "~>"
|
74
102
|
- !ruby/object:Gem::Version
|
75
|
-
version: '6.
|
103
|
+
version: '6.1'
|
76
104
|
type: :development
|
77
105
|
prerelease: false
|
78
106
|
version_requirements: !ruby/object:Gem::Requirement
|
79
107
|
requirements:
|
80
108
|
- - "~>"
|
81
109
|
- !ruby/object:Gem::Version
|
82
|
-
version: '6.
|
110
|
+
version: '6.1'
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: webmock
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
86
114
|
requirements:
|
87
115
|
- - "~>"
|
88
116
|
- !ruby/object:Gem::Version
|
89
|
-
version: '3.
|
117
|
+
version: '3.14'
|
90
118
|
type: :development
|
91
119
|
prerelease: false
|
92
120
|
version_requirements: !ruby/object:Gem::Requirement
|
93
121
|
requirements:
|
94
122
|
- - "~>"
|
95
123
|
- !ruby/object:Gem::Version
|
96
|
-
version: '3.
|
124
|
+
version: '3.14'
|
97
125
|
description: A dead simple TheHive API wrapper.
|
98
126
|
email:
|
99
127
|
- manabu.niseki@gmail.com
|
@@ -113,22 +141,16 @@ files:
|
|
113
141
|
- hachi.gemspec
|
114
142
|
- lib/hachi.rb
|
115
143
|
- lib/hachi/api.rb
|
144
|
+
- lib/hachi/awrence/methods.rb
|
116
145
|
- lib/hachi/clients/alert.rb
|
117
146
|
- lib/hachi/clients/artifact.rb
|
118
147
|
- lib/hachi/clients/base.rb
|
119
148
|
- lib/hachi/clients/case.rb
|
149
|
+
- lib/hachi/clients/observable.rb
|
150
|
+
- lib/hachi/clients/query.rb
|
120
151
|
- lib/hachi/clients/user.rb
|
121
|
-
- lib/hachi/models/alert.rb
|
122
|
-
- lib/hachi/models/artifact.rb
|
123
|
-
- lib/hachi/models/base.rb
|
124
|
-
- lib/hachi/models/case.rb
|
125
|
-
- lib/hachi/models/user.rb
|
126
152
|
- lib/hachi/version.rb
|
127
153
|
- renovate.json
|
128
|
-
- samples/01_create_an_alert.rb
|
129
|
-
- samples/02_search_artifacts.rb
|
130
|
-
- samples/03_list_cases.rb
|
131
|
-
- samples/04_merge_alerts.rb
|
132
154
|
homepage: https://github.com/ninoseki/hachi
|
133
155
|
licenses:
|
134
156
|
- MIT
|
@@ -148,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
170
|
- !ruby/object:Gem::Version
|
149
171
|
version: '0'
|
150
172
|
requirements: []
|
151
|
-
rubygems_version: 3.2.
|
173
|
+
rubygems_version: 3.2.14
|
152
174
|
signing_key:
|
153
175
|
specification_version: 4
|
154
176
|
summary: A dead simple TheHive API wrapper.
|
data/lib/hachi/models/alert.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "date"
|
4
|
-
require "securerandom"
|
5
|
-
|
6
|
-
module Hachi
|
7
|
-
module Models
|
8
|
-
class Alert < Base
|
9
|
-
attr_reader :title, :description, :severity, :date, :tags, :tlp, :status, :type, :source, :source_ref, :artifacts, :follow
|
10
|
-
|
11
|
-
def initialize(title:, description:, type:, source:, severity: nil, date: nil, tags: nil, tlp: nil, status: nil, source_ref: nil, artifacts: nil, follow: nil)
|
12
|
-
@title = title
|
13
|
-
@description = description
|
14
|
-
@severity = severity
|
15
|
-
@date = date
|
16
|
-
@tags = tags
|
17
|
-
@tlp = tlp
|
18
|
-
@status = status
|
19
|
-
@type = type
|
20
|
-
@source = source
|
21
|
-
@source_ref = source_ref || SecureRandom.hex(10)
|
22
|
-
@artifacts = artifacts.nil? ? nil : artifacts.map { |a| Artifact.new(**a) }
|
23
|
-
@follow = follow
|
24
|
-
|
25
|
-
validate_date if date
|
26
|
-
validate_severity if severity
|
27
|
-
validate_status if status
|
28
|
-
validate_tlp if tlp
|
29
|
-
validate_artifacts if artifacts
|
30
|
-
end
|
31
|
-
|
32
|
-
def payload
|
33
|
-
{
|
34
|
-
title: title,
|
35
|
-
description: description,
|
36
|
-
severity: severity,
|
37
|
-
date: date,
|
38
|
-
tags: tags,
|
39
|
-
tlp: tlp,
|
40
|
-
status: status,
|
41
|
-
type: type,
|
42
|
-
source: source,
|
43
|
-
sourceRef: source_ref,
|
44
|
-
artifacts: artifacts&.map(&:payload),
|
45
|
-
follow: follow
|
46
|
-
}.compact
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def validate_date
|
52
|
-
DateTime.parse(date)
|
53
|
-
true
|
54
|
-
rescue ArgumentError => _e
|
55
|
-
raise ArgumentError, "date should be Date format"
|
56
|
-
end
|
57
|
-
|
58
|
-
def validate_artifacts
|
59
|
-
artifacts.each(&:validate_for_creation)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Hachi
|
4
|
-
module Models
|
5
|
-
class Artifact < Base
|
6
|
-
DATA_TYPES = %w(filename file fqdn hash uri_path ip domain mail autonomous-system registry mail_subject regexp user-agent other url).freeze
|
7
|
-
|
8
|
-
attr_reader :data, :data_type, :message, :tlp, :tags
|
9
|
-
|
10
|
-
def initialize(data:, data_type:, message: nil, tlp: nil, tags: nil)
|
11
|
-
@data = data
|
12
|
-
@data_type = data_type
|
13
|
-
@message = message
|
14
|
-
@tlp = tlp
|
15
|
-
@tags = tags
|
16
|
-
|
17
|
-
raise(ArgumentError, "data is required") unless data
|
18
|
-
raise(ArgumentError, "data_type is required") unless data_type
|
19
|
-
raise(ArgumentError, "invalid data type") unless DATA_TYPES.include?(data_type)
|
20
|
-
|
21
|
-
validate_tags if tags
|
22
|
-
validate_tlp if tlp
|
23
|
-
end
|
24
|
-
|
25
|
-
def payload
|
26
|
-
{
|
27
|
-
data: data,
|
28
|
-
dataType: data_type,
|
29
|
-
message: message,
|
30
|
-
tlp: tlp,
|
31
|
-
tags: tags
|
32
|
-
}.compact
|
33
|
-
end
|
34
|
-
|
35
|
-
def validate_for_creation
|
36
|
-
raise(ArgumentError, "message or tags is requried for artifact creation") unless message || tags
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|