hachi 0.2.4 → 0.3.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/.travis.yml +1 -1
- data/README.md +22 -7
- data/hachi.gemspec +3 -3
- data/lib/hachi/api.rb +51 -8
- data/lib/hachi/clients/alert.rb +120 -0
- data/lib/hachi/clients/artifact.rb +41 -0
- data/lib/hachi/clients/base.rb +12 -0
- data/lib/hachi/clients/case.rb +103 -0
- data/lib/hachi/clients/user.rb +59 -0
- data/lib/hachi/models/user.rb +39 -0
- data/lib/hachi/version.rb +1 -1
- data/lib/hachi.rb +2 -0
- metadata +11 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '086d5b7a1c871c39a5913f99bc98e215bc2a51abba1ce645be1e8de47565ebcd'
|
|
4
|
+
data.tar.gz: db42c7b0091cf6a58f75a22df7591452a3a1f53c2e4b7bf8850cbc08ce4a2461
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6729860b84933e9b3d7100426a45394a3047f305c1eb323263f55d8219d1559e8cb6131b33b1407d129349b5733f012e6b8fa9a0073946968953dfb6d53640f9
|
|
7
|
+
data.tar.gz: 1b4ed73ac933cad2b503a2b9ee8a49eb92efaf046465aab04cb6192eb4547d58c4569c710dbb2917b77e94835b14afb12423d42c845dc4a3f933f4c6968bde55
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Hachi
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/rb/hachi)
|
|
4
|
-
[](https://travis-ci.com/ninoseki/hachi)
|
|
5
5
|
[](https://coveralls.io/github/ninoseki/hachi?branch=master)
|
|
6
6
|
[](https://www.codefactor.io/repository/github/ninoseki/hachi)
|
|
7
7
|
|
|
@@ -46,14 +46,14 @@ See `samples` for more.
|
|
|
46
46
|
| POST | /api/alert/_stats | Compute stats on alerts | N/A |
|
|
47
47
|
| POST | /api/alert | Create an alert | `#api.alert.create(title:, description:, severity: nil, date: nil, tags: nil, tlp: nil, status: nil, type:, source:, source_ref: nil, artifacts: nil, follow: nil)` |
|
|
48
48
|
| GET | /api/alert/:alertId | Get an alert | `#api.alert.get_by_id(id)` |
|
|
49
|
-
| PATCH | /api/alert/:alertId | Update an alert |
|
|
49
|
+
| PATCH | /api/alert/:alertId | Update an alert | `#api.alert.update(id, title:, description:, severity: nil, tags: nil, tlp: nil, artifacts: nil)` |
|
|
50
50
|
| DELETE | /api/alert/:alertId | Delete an alert | `#api.alert.delete_by_id(id)` |
|
|
51
|
-
| POST | /api/alert/:alertId/markAsRead | Mark an alert as read |
|
|
52
|
-
| POST | /api/alert/:alertId/markAsUnread | Mark an alert as unread |
|
|
53
|
-
| POST | /api/alert/:alertId/createCase | Create a case from an alert |
|
|
51
|
+
| POST | /api/alert/:alertId/markAsRead | Mark an alert as read | `#api.alert.mark_as_read(id)` |
|
|
52
|
+
| POST | /api/alert/:alertId/markAsUnread | Mark an alert as unread | `#api.alert.mark_as_unread(id)` |
|
|
53
|
+
| POST | /api/alert/:alertId/createCase | Create a case from an alert | `#api.alert.promote_to_case(id)` |
|
|
54
54
|
| POST | /api/alert/:alertId/follow | Follow an alert | N/A |
|
|
55
55
|
| POST | /api/alert/:alertId/unfollow | Unfollow an alert | N/A |
|
|
56
|
-
| POST | /api/alert/:alertId/merge/:caseId | Merge an alert in a case |
|
|
56
|
+
| POST | /api/alert/:alertId/merge/:caseId | Merge an alert in a case | `#api.alert.merge_into_case(*ids, case_id)` |
|
|
57
57
|
|
|
58
58
|
### Artifact(Observable)
|
|
59
59
|
|
|
@@ -81,7 +81,22 @@ See `samples` for more.
|
|
|
81
81
|
| PATCH | /api/case/:caseId | Update a case | N/A |
|
|
82
82
|
| DELETE | /api/case/:caseId | Remove a case | `#api.case.delete_by_id(id)` |
|
|
83
83
|
| GET | /api/case/:caseId/links | Get list of cases linked to this case | `#api.case.links(id)` |
|
|
84
|
-
| POST | /api/case/:caseId1/_merge/:caseId2 | Merge two cases |
|
|
84
|
+
| POST | /api/case/:caseId1/_merge/:caseId2 | Merge two cases | `#api.case.merge(id1, id2)` |
|
|
85
|
+
|
|
86
|
+
### User
|
|
87
|
+
|
|
88
|
+
| HTTP Method | URI | Action | API method |
|
|
89
|
+
|-------------|-----------------------------------|---------------------|------------------------------------------------------|
|
|
90
|
+
| GET | /api/logout | Logout | N/A |
|
|
91
|
+
| POST | /api/login | User login | N/A |
|
|
92
|
+
| GET | /api/user/current | Get current user | `#api.user.current` |
|
|
93
|
+
| POST | /api/user/_search | Find user | N/A |
|
|
94
|
+
| POST | /api/user | Create a user | `#api.user.create(login:, name:, roles:, password:)` |
|
|
95
|
+
| GET | /api/user/:userId | Get a user | `#api.user.get_by_id(id)` |
|
|
96
|
+
| DELETE | /api/user/:userId | Delete a case | `#api.user.delete_by_id(id)` |
|
|
97
|
+
| PATCH | /api/user/:userId | Update user details | N/A |
|
|
98
|
+
| POST | /api/user/:userId/password/set | Set password | N/A |
|
|
99
|
+
| POST | /api/user/:userId/password/change | Change password | N/A |
|
|
85
100
|
|
|
86
101
|
## License
|
|
87
102
|
|
data/hachi.gemspec
CHANGED
|
@@ -26,8 +26,8 @@ Gem::Specification.new do |spec|
|
|
|
26
26
|
|
|
27
27
|
spec.add_development_dependency "bundler", "~> 2.0"
|
|
28
28
|
spec.add_development_dependency "coveralls", "~> 0.8"
|
|
29
|
-
spec.add_development_dependency "rake", "~>
|
|
30
|
-
spec.add_development_dependency "rspec", "~> 3.
|
|
29
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
30
|
+
spec.add_development_dependency "rspec", "~> 3.9"
|
|
31
31
|
spec.add_development_dependency "vcr", "~> 5.0"
|
|
32
|
-
spec.add_development_dependency "webmock", "~> 3.
|
|
32
|
+
spec.add_development_dependency "webmock", "~> 3.7"
|
|
33
33
|
end
|
data/lib/hachi/api.rb
CHANGED
|
@@ -2,17 +2,60 @@
|
|
|
2
2
|
|
|
3
3
|
module Hachi
|
|
4
4
|
class API
|
|
5
|
-
|
|
6
|
-
attr_reader :
|
|
7
|
-
attr_reader :case
|
|
5
|
+
# @return [String] TheHive API endpoint
|
|
6
|
+
attr_reader :api_endpoint
|
|
8
7
|
|
|
8
|
+
# @return [String] TheHive API key
|
|
9
|
+
attr_reader :api_key
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
# @param [String, nil] api_endpoint TheHive API endpoint
|
|
13
|
+
# @param [String, nil] api_key TheHive API key
|
|
14
|
+
#
|
|
15
|
+
# @raise [ArgumentError] When given or an empty endpoint or key
|
|
16
|
+
#
|
|
9
17
|
def initialize(api_endpoint: ENV["THEHIVE_API_ENDPOINT"], api_key: ENV["THEHIVE_API_KEY"])
|
|
10
|
-
|
|
11
|
-
raise
|
|
18
|
+
@api_endpoint = api_endpoint
|
|
19
|
+
raise ArgumentError, "api_endpoint argument is required" unless api_endpoint
|
|
20
|
+
|
|
21
|
+
@api_key = api_key
|
|
22
|
+
raise ArgumentError, "api_key argument is required" unless api_key
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Alert API endpoint client
|
|
27
|
+
#
|
|
28
|
+
# @return [Clients::Alert]
|
|
29
|
+
#
|
|
30
|
+
def alert
|
|
31
|
+
@alert ||= Clients::Alert.new(api_endpoint: api_endpoint, api_key: api_key)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Artifact API endpoint client
|
|
36
|
+
#
|
|
37
|
+
# @return [Clients::Artifact]
|
|
38
|
+
#
|
|
39
|
+
def artifact
|
|
40
|
+
@artifact ||= Clients::Artifact.new(api_endpoint: api_endpoint, api_key: api_key)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# Case API endpoint client
|
|
45
|
+
#
|
|
46
|
+
# @return [Clients::Case]
|
|
47
|
+
#
|
|
48
|
+
def case
|
|
49
|
+
@case ||= Clients::Case.new(api_endpoint: api_endpoint, api_key: api_key)
|
|
50
|
+
end
|
|
12
51
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
52
|
+
#
|
|
53
|
+
# User API endpoint client
|
|
54
|
+
#
|
|
55
|
+
# @return [Clients::User]
|
|
56
|
+
#
|
|
57
|
+
def user
|
|
58
|
+
@user ||= Clients::User.new(api_endpoint: api_endpoint, api_key: api_key)
|
|
16
59
|
end
|
|
17
60
|
end
|
|
18
61
|
end
|
data/lib/hachi/clients/alert.rb
CHANGED
|
@@ -6,18 +6,55 @@ require "securerandom"
|
|
|
6
6
|
module Hachi
|
|
7
7
|
module Clients
|
|
8
8
|
class Alert < Base
|
|
9
|
+
#
|
|
10
|
+
# List alerts
|
|
11
|
+
#
|
|
12
|
+
# @return [Array]
|
|
13
|
+
#
|
|
9
14
|
def list
|
|
10
15
|
get("/api/alert") { |json| json }
|
|
11
16
|
end
|
|
12
17
|
|
|
18
|
+
#
|
|
19
|
+
# Get an alert
|
|
20
|
+
#
|
|
21
|
+
# @param [String] id Alert ID
|
|
22
|
+
#
|
|
23
|
+
# @return [Hash]
|
|
24
|
+
#
|
|
13
25
|
def get_by_id(id)
|
|
14
26
|
get("/api/alert/#{id}") { |json| json }
|
|
15
27
|
end
|
|
16
28
|
|
|
29
|
+
#
|
|
30
|
+
# Delete an alert
|
|
31
|
+
#
|
|
32
|
+
# @param [String] id Alert ID
|
|
33
|
+
#
|
|
34
|
+
# @return [String]
|
|
35
|
+
#
|
|
17
36
|
def delete_by_id(id)
|
|
18
37
|
delete("/api/alert/#{id}") { |json| json }
|
|
19
38
|
end
|
|
20
39
|
|
|
40
|
+
#
|
|
41
|
+
# Create an alert
|
|
42
|
+
#
|
|
43
|
+
# @param [String] title
|
|
44
|
+
# @param [String] description
|
|
45
|
+
# @param [String, nil] severity
|
|
46
|
+
# @param [String, nil] date
|
|
47
|
+
# @param [String, nil] tags
|
|
48
|
+
# @param [String, nil] tlp
|
|
49
|
+
# @param [String, nil] status
|
|
50
|
+
# @param [String, nil] type
|
|
51
|
+
# @param [String, nil] source
|
|
52
|
+
# @param [String, nil] source_ref
|
|
53
|
+
# @param [String, nil] artifacts
|
|
54
|
+
# @param [String, nil] follow
|
|
55
|
+
#
|
|
56
|
+
# @return [Hash]
|
|
57
|
+
#
|
|
21
58
|
def create(title:, description:, severity: nil, date: nil, tags: nil, tlp: nil, status: nil, type:, source:, source_ref: nil, artifacts: nil, follow: nil)
|
|
22
59
|
alert = Models::Alert.new(
|
|
23
60
|
title: title,
|
|
@@ -36,9 +73,92 @@ module Hachi
|
|
|
36
73
|
post("/api/alert", alert.payload) { |json| json }
|
|
37
74
|
end
|
|
38
75
|
|
|
76
|
+
#
|
|
77
|
+
# Find alerts
|
|
78
|
+
#
|
|
79
|
+
# @param [Hash] attributes
|
|
80
|
+
# @param [String] range
|
|
81
|
+
# @param [String, nil] sort
|
|
82
|
+
#
|
|
83
|
+
# @return [Array]
|
|
84
|
+
#
|
|
39
85
|
def search(attributes, range: "all", sort: nil)
|
|
40
86
|
_search("/api/alert/_search", attributes: attributes, range: range, sort: sort) { |json| json }
|
|
41
87
|
end
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Mark an alert as read
|
|
91
|
+
#
|
|
92
|
+
# @param [String] id Alert ID
|
|
93
|
+
#
|
|
94
|
+
# @return [Hash]
|
|
95
|
+
#
|
|
96
|
+
def mark_as_read(id)
|
|
97
|
+
post("/api/alert/#{id}/markAsRead") { |json| json }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
#
|
|
101
|
+
# Mark an alert as unread
|
|
102
|
+
#
|
|
103
|
+
# @param [String] id Alert ID
|
|
104
|
+
#
|
|
105
|
+
# @return [Hash] hash
|
|
106
|
+
#
|
|
107
|
+
def mark_as_unread(id)
|
|
108
|
+
post("/api/alert/#{id}/markAsUnread") { |json| json }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
#
|
|
112
|
+
# Create a case from an alert
|
|
113
|
+
#
|
|
114
|
+
# @param [String] id Alert ID
|
|
115
|
+
#
|
|
116
|
+
# @return [Hash]
|
|
117
|
+
#
|
|
118
|
+
def promote_to_case(id)
|
|
119
|
+
post("/api/alert/#{id}/createCase") { |json| json }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
#
|
|
123
|
+
# Merge an alert / alerts in a case
|
|
124
|
+
#
|
|
125
|
+
# @param [String, Array] *ids Alert ID(s)
|
|
126
|
+
# @param [String] case_id Case ID
|
|
127
|
+
#
|
|
128
|
+
# @return [Hash]
|
|
129
|
+
#
|
|
130
|
+
def merge_into_case(*ids, case_id)
|
|
131
|
+
params = {
|
|
132
|
+
alertIds: ids,
|
|
133
|
+
caseId: case_id
|
|
134
|
+
}
|
|
135
|
+
post("/api/alert/merge/_bulk", params) { |json| json }
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#
|
|
139
|
+
# Update an alert
|
|
140
|
+
#
|
|
141
|
+
# @param [String, nil] id
|
|
142
|
+
# @param [String, nil] title
|
|
143
|
+
# @param [String, nil] description
|
|
144
|
+
# @param [String, nil] severity
|
|
145
|
+
# @param [String, nil] tags
|
|
146
|
+
# @param [String, nil] tlp
|
|
147
|
+
# @param [String, nil] artifacts
|
|
148
|
+
#
|
|
149
|
+
# @return [Hash]
|
|
150
|
+
#
|
|
151
|
+
def update(id, title: nil, description: nil, severity: nil, tags: nil, tlp: nil, artifacts: nil)
|
|
152
|
+
attributes = {
|
|
153
|
+
title: title,
|
|
154
|
+
description: description,
|
|
155
|
+
severity: severity,
|
|
156
|
+
tags: tags,
|
|
157
|
+
tlp: tlp,
|
|
158
|
+
artifacts: artifacts,
|
|
159
|
+
}.compact
|
|
160
|
+
patch("/api/alert/#{id}", attributes) { |json| json }
|
|
161
|
+
end
|
|
42
162
|
end
|
|
43
163
|
end
|
|
44
164
|
end
|
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
module Hachi
|
|
4
4
|
module Clients
|
|
5
5
|
class Artifact < Base
|
|
6
|
+
#
|
|
7
|
+
# Create an artifact
|
|
8
|
+
#
|
|
9
|
+
# @param [String] case_id Artifact ID
|
|
10
|
+
# @param [String] data
|
|
11
|
+
# @param [String] data_type
|
|
12
|
+
# @param [String, nil] message
|
|
13
|
+
# @param [Integer, nil] tlp
|
|
14
|
+
# @param [Array<String>, nil] tags
|
|
15
|
+
#
|
|
16
|
+
# @return [Hash]
|
|
17
|
+
#
|
|
6
18
|
def create(case_id, data:, data_type:, message: nil, tlp: nil, tags: nil)
|
|
7
19
|
artifact = Models::Artifact.new(
|
|
8
20
|
data: data,
|
|
@@ -15,18 +27,47 @@ module Hachi
|
|
|
15
27
|
post("/api/case/#{case_id}/artifact", artifact.payload) { |json| json }
|
|
16
28
|
end
|
|
17
29
|
|
|
30
|
+
#
|
|
31
|
+
# Get an artifact
|
|
32
|
+
#
|
|
33
|
+
# @param [String] id Artifact ID
|
|
34
|
+
#
|
|
35
|
+
# @return [Hash]
|
|
36
|
+
#
|
|
18
37
|
def get_by_id(id)
|
|
19
38
|
get("/api/case/artifact/#{id}") { |json| json }
|
|
20
39
|
end
|
|
21
40
|
|
|
41
|
+
#
|
|
42
|
+
# Delete an artifact
|
|
43
|
+
#
|
|
44
|
+
# @param [String] id Artifact ID
|
|
45
|
+
#
|
|
46
|
+
# @return [String]
|
|
47
|
+
#
|
|
22
48
|
def delete_by_id(id)
|
|
23
49
|
delete("/api/case/artifact/#{id}") { |json| json }
|
|
24
50
|
end
|
|
25
51
|
|
|
52
|
+
#
|
|
53
|
+
# Find artifacts
|
|
54
|
+
#
|
|
55
|
+
# @param [Hash] attributes
|
|
56
|
+
# @param [String] range
|
|
57
|
+
#
|
|
58
|
+
# @return [Array]
|
|
59
|
+
#
|
|
26
60
|
def search(attributes, range: "all")
|
|
27
61
|
_search("/api/case/artifact/_search", attributes: attributes, range: range) { |json| json }
|
|
28
62
|
end
|
|
29
63
|
|
|
64
|
+
#
|
|
65
|
+
# Get list of similar observables
|
|
66
|
+
#
|
|
67
|
+
# @param [String] id Artifact ID
|
|
68
|
+
#
|
|
69
|
+
# @return [Array]
|
|
70
|
+
#
|
|
30
71
|
def similar(id)
|
|
31
72
|
get("/api/case/artifact/#{id}/similar") { |json| json }
|
|
32
73
|
end
|
data/lib/hachi/clients/base.rb
CHANGED
|
@@ -104,6 +104,18 @@ module Hachi
|
|
|
104
104
|
request(delete, &block)
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
+
def patch(path, params = {}, &block)
|
|
108
|
+
url = url_for(path)
|
|
109
|
+
|
|
110
|
+
patch = Net::HTTP::Patch.new(url)
|
|
111
|
+
patch.body = params.is_a?(Hash) ? params.to_json : params.to_s
|
|
112
|
+
|
|
113
|
+
patch.add_field "Content-Type", "application/json"
|
|
114
|
+
patch.add_field "Authorization", "Bearer #{api_key}"
|
|
115
|
+
|
|
116
|
+
request(patch, &block)
|
|
117
|
+
end
|
|
118
|
+
|
|
107
119
|
def validate_range(range)
|
|
108
120
|
return true if range == "all"
|
|
109
121
|
raise ArgumentError, "range should be 'all' or `from-to`" unless range.match?(/(\d+)-(\d+)/)
|
data/lib/hachi/clients/case.rb
CHANGED
|
@@ -3,18 +3,51 @@
|
|
|
3
3
|
module Hachi
|
|
4
4
|
module Clients
|
|
5
5
|
class Case < Base
|
|
6
|
+
#
|
|
7
|
+
# List cases
|
|
8
|
+
#
|
|
9
|
+
# @return [Array]
|
|
10
|
+
#
|
|
6
11
|
def list
|
|
7
12
|
get("/api/case") { |json| json }
|
|
8
13
|
end
|
|
9
14
|
|
|
15
|
+
#
|
|
16
|
+
# Get a case
|
|
17
|
+
#
|
|
18
|
+
# @param [String] id Case ID
|
|
19
|
+
#
|
|
20
|
+
# @return [Hash]
|
|
21
|
+
#
|
|
10
22
|
def get_by_id(id)
|
|
11
23
|
get("/api/case/#{id}") { |json| json }
|
|
12
24
|
end
|
|
13
25
|
|
|
26
|
+
#
|
|
27
|
+
# Delete a case
|
|
28
|
+
#
|
|
29
|
+
# @param [String] id Case ID
|
|
30
|
+
#
|
|
31
|
+
# @return [String]
|
|
32
|
+
#
|
|
14
33
|
def delete_by_id(id)
|
|
15
34
|
delete("/api/case/#{id}") { |json| json }
|
|
16
35
|
end
|
|
17
36
|
|
|
37
|
+
#
|
|
38
|
+
# Create a case
|
|
39
|
+
#
|
|
40
|
+
# @param [String, nil] title
|
|
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
|
+
#
|
|
18
51
|
def create(title:, description:, severity: nil, start_date: nil, owner: nil, flag: nil, tlp: nil, tags: nil)
|
|
19
52
|
kase = Models::Case.new(
|
|
20
53
|
title: title,
|
|
@@ -30,13 +63,83 @@ module Hachi
|
|
|
30
63
|
post("/api/case", kase.payload) { |json| json }
|
|
31
64
|
end
|
|
32
65
|
|
|
66
|
+
#
|
|
67
|
+
# Find cases
|
|
68
|
+
#
|
|
69
|
+
# @param [Hash] attributes
|
|
70
|
+
# @param [String] range
|
|
71
|
+
#
|
|
72
|
+
# @return [Hash]
|
|
73
|
+
#
|
|
33
74
|
def search(attributes, range: "all")
|
|
34
75
|
_search("/api/case/_search", attributes: attributes, range: range) { |json| json }
|
|
35
76
|
end
|
|
36
77
|
|
|
78
|
+
#
|
|
79
|
+
# Get list of cases linked to this case
|
|
80
|
+
#
|
|
81
|
+
# @param [String] id Case ID
|
|
82
|
+
#
|
|
83
|
+
# @return [Array]
|
|
84
|
+
#
|
|
37
85
|
def links(id)
|
|
38
86
|
get("/api/case/#{id}/links") { |json| json }
|
|
39
87
|
end
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Merge two cases
|
|
91
|
+
#
|
|
92
|
+
# @param [String] id1 Case ID
|
|
93
|
+
# @param [String] id2 Case ID
|
|
94
|
+
#
|
|
95
|
+
# @return [Hash]
|
|
96
|
+
#
|
|
97
|
+
def merge(id1, id2)
|
|
98
|
+
post("/api/case/#{id1}/_merge/#{id2}") { |json| json }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
#
|
|
102
|
+
# Update a case
|
|
103
|
+
#
|
|
104
|
+
# @param [String, nil] id
|
|
105
|
+
# @param [String, nil] title
|
|
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
|
|
120
|
+
#
|
|
121
|
+
# @return [Hash]
|
|
122
|
+
#
|
|
123
|
+
def update(id, title: nil, description: nil, severity: nil, start_date: nil, owner: nil, flag: nil, tlp: nil, tags: nil, status: nil, resolution_status: nil, impact_status: nil, summary: nil, end_date: nil, metrics: nil, custom_fields: nil )
|
|
124
|
+
attributes = {
|
|
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}", attributes) { |json| json }
|
|
142
|
+
end
|
|
40
143
|
end
|
|
41
144
|
end
|
|
42
145
|
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hachi
|
|
4
|
+
module Clients
|
|
5
|
+
class User < Base
|
|
6
|
+
#
|
|
7
|
+
# Get current user
|
|
8
|
+
#
|
|
9
|
+
# @return [Hash]
|
|
10
|
+
#
|
|
11
|
+
def current
|
|
12
|
+
get("/api/user/current") { |json| json }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# Get a user
|
|
17
|
+
#
|
|
18
|
+
# @param [String] id User ID
|
|
19
|
+
#
|
|
20
|
+
# @return [Hash]
|
|
21
|
+
#
|
|
22
|
+
def get_by_id(id)
|
|
23
|
+
get("/api/user/#{id}") { |json| json }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# Delete a user
|
|
28
|
+
#
|
|
29
|
+
# @param [String] id User ID
|
|
30
|
+
#
|
|
31
|
+
# @return [String]
|
|
32
|
+
#
|
|
33
|
+
def delete_by_id(id)
|
|
34
|
+
delete("/api/user/#{id}") { |json| json }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
# Create a user
|
|
39
|
+
#
|
|
40
|
+
# @param [String] login
|
|
41
|
+
# @param [String] name
|
|
42
|
+
# @param [Array<String>] roles
|
|
43
|
+
# @param [String] password
|
|
44
|
+
#
|
|
45
|
+
# @return [Hash]
|
|
46
|
+
#
|
|
47
|
+
def create(login:, name:, roles:, password:)
|
|
48
|
+
user = Models::User.new(
|
|
49
|
+
login: login,
|
|
50
|
+
name: name,
|
|
51
|
+
roles: roles,
|
|
52
|
+
password: password
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
post("/api/user", user.payload) { |json| json }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hachi
|
|
4
|
+
module Models
|
|
5
|
+
class User < Base
|
|
6
|
+
attr_reader :login
|
|
7
|
+
attr_reader :name
|
|
8
|
+
attr_reader :roles
|
|
9
|
+
attr_reader :password
|
|
10
|
+
|
|
11
|
+
ROLES = %w(read write admin).freeze
|
|
12
|
+
|
|
13
|
+
def initialize(login:, name:, roles:, password:)
|
|
14
|
+
@login = login
|
|
15
|
+
@name = name
|
|
16
|
+
@roles = roles
|
|
17
|
+
@password = password
|
|
18
|
+
|
|
19
|
+
validate_roles
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def payload
|
|
23
|
+
{
|
|
24
|
+
login: login,
|
|
25
|
+
name: name,
|
|
26
|
+
roles: roles,
|
|
27
|
+
password: password
|
|
28
|
+
}.compact
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def validate_roles
|
|
34
|
+
raise ArgumentError, "roles should be an array" unless roles.is_a?(Array)
|
|
35
|
+
raise ArgumentError, "role should be one of #{ROLES.join('.')}" unless roles.all? { |role| ROLES.include? role }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/hachi/version.rb
CHANGED
data/lib/hachi.rb
CHANGED
|
@@ -8,11 +8,13 @@ require "hachi/models/base"
|
|
|
8
8
|
require "hachi/models/alert"
|
|
9
9
|
require "hachi/models/artifact"
|
|
10
10
|
require "hachi/models/case"
|
|
11
|
+
require "hachi/models/user"
|
|
11
12
|
|
|
12
13
|
require "hachi/clients/base"
|
|
13
14
|
require "hachi/clients/alert"
|
|
14
15
|
require "hachi/clients/artifact"
|
|
15
16
|
require "hachi/clients/case"
|
|
17
|
+
require "hachi/clients/user"
|
|
16
18
|
|
|
17
19
|
module Hachi
|
|
18
20
|
class Error < StandardError; 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: 0.
|
|
4
|
+
version: 0.3.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: 2019-
|
|
11
|
+
date: 2019-11-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -44,28 +44,28 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '13.0'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
54
|
+
version: '13.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '3.
|
|
61
|
+
version: '3.9'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '3.
|
|
68
|
+
version: '3.9'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: vcr
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,14 +86,14 @@ dependencies:
|
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '3.
|
|
89
|
+
version: '3.7'
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '3.
|
|
96
|
+
version: '3.7'
|
|
97
97
|
description: A dead simple TheHive API wrapper.
|
|
98
98
|
email:
|
|
99
99
|
- manabu.niseki@gmail.com
|
|
@@ -117,10 +117,12 @@ files:
|
|
|
117
117
|
- lib/hachi/clients/artifact.rb
|
|
118
118
|
- lib/hachi/clients/base.rb
|
|
119
119
|
- lib/hachi/clients/case.rb
|
|
120
|
+
- lib/hachi/clients/user.rb
|
|
120
121
|
- lib/hachi/models/alert.rb
|
|
121
122
|
- lib/hachi/models/artifact.rb
|
|
122
123
|
- lib/hachi/models/base.rb
|
|
123
124
|
- lib/hachi/models/case.rb
|
|
125
|
+
- lib/hachi/models/user.rb
|
|
124
126
|
- lib/hachi/version.rb
|
|
125
127
|
- samples/01_create_an_alert.rb
|
|
126
128
|
- samples/02_search_artifacts.rb
|
|
@@ -144,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
144
146
|
- !ruby/object:Gem::Version
|
|
145
147
|
version: '0'
|
|
146
148
|
requirements: []
|
|
147
|
-
rubygems_version: 3.0.
|
|
149
|
+
rubygems_version: 3.0.3
|
|
148
150
|
signing_key:
|
|
149
151
|
specification_version: 4
|
|
150
152
|
summary: A dead simple TheHive API wrapper.
|