hachi 0.3.1 → 2.0.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.
@@ -7,18 +7,83 @@ require "uri"
7
7
  module Hachi
8
8
  module Clients
9
9
  class Base
10
+ # @return [String]
10
11
  attr_reader :api_endpoint
12
+
13
+ # @return [String]
11
14
  attr_reader :api_key
12
15
 
13
- def initialize(api_endpoint:, api_key:)
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:)
14
22
  @api_endpoint = URI(api_endpoint)
15
23
  @api_key = api_key
24
+ @api_version = api_version
25
+ end
26
+
27
+ def get(path, params: {}, &block)
28
+ url = url_for(path)
29
+ url.query = URI.encode_www_form(params) unless params.empty?
30
+
31
+ get = Net::HTTP::Get.new(url)
32
+ get.add_field "Authorization", "Bearer #{api_key}"
33
+ request(get, &block)
34
+ end
35
+
36
+ def post(path, params: {}, json: {}, &block)
37
+ url = url_for(path)
38
+ url.query = URI.encode_www_form(params) unless params.empty?
39
+
40
+ json = to_camelback_keys(json.compact) if json.is_a?(Hash)
41
+
42
+ post = Net::HTTP::Post.new(url)
43
+ post.body = json.is_a?(Hash) ? json.to_json : json.to_s
44
+
45
+ post.add_field "Content-Type", "application/json"
46
+ post.add_field "Authorization", "Bearer #{api_key}"
47
+
48
+ request(post, &block)
49
+ end
50
+
51
+ def delete(path, params: {}, json: {}, &block)
52
+ url = url_for(path)
53
+ url.query = URI.encode_www_form(params) unless params.empty?
54
+
55
+ json = to_camelback_keys(json.compact) if json.is_a?(Hash)
56
+
57
+ delete = Net::HTTP::Delete.new(url)
58
+ delete.body = json.is_a?(Hash) ? json.to_json : json.to_s
59
+
60
+ delete.add_field "Authorization", "Bearer #{api_key}"
61
+ request(delete, &block)
62
+ end
63
+
64
+ def patch(path, params: {}, json: {}, &block)
65
+ url = url_for(path)
66
+ url.query = URI.encode_www_form(params) unless params.empty?
67
+
68
+ json = to_camelback_keys(json.compact) if json.is_a?(Hash)
69
+
70
+ patch = Net::HTTP::Patch.new(url)
71
+ patch.body = json.is_a?(Hash) ? json.to_json : json.to_s
72
+
73
+ patch.add_field "Content-Type", "application/json"
74
+ patch.add_field "Authorization", "Bearer #{api_key}"
75
+
76
+ request(patch, &block)
16
77
  end
17
78
 
18
79
  private
19
80
 
20
81
  def base_url
21
- "#{api_endpoint.scheme}://#{api_endpoint.hostname}:#{api_endpoint.port}"
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
22
87
  end
23
88
 
24
89
  def url_for(path)
@@ -28,13 +93,13 @@ module Hachi
28
93
  def https_options
29
94
  return nil if api_endpoint.scheme != "https"
30
95
 
31
- if proxy = ENV["HTTPS_PROXY"] || ENV["https_proxy"]
96
+ if proxy = ENV.fetch("HTTPS_PROXY") { ENV.fetch("https_proxy", nil) }
32
97
  uri = URI(proxy)
33
98
  {
34
99
  proxy_address: uri.hostname,
35
100
  proxy_port: uri.port,
36
101
  proxy_from_env: false,
37
- use_ssl: true,
102
+ use_ssl: true
38
103
  }
39
104
  else
40
105
  { use_ssl: true }
@@ -42,12 +107,12 @@ module Hachi
42
107
  end
43
108
 
44
109
  def http_options
45
- if proxy = ENV["HTTP_PROXY"] || ENV["http_proxy"]
110
+ if proxy = ENV.fetch("HTTP_PROXY") { ENV.fetch("http_proxy", nil) }
46
111
  uri = URI(proxy)
47
112
  {
48
113
  proxy_address: uri.hostname,
49
114
  proxy_port: uri.port,
50
- proxy_from_env: false,
115
+ proxy_from_env: false
51
116
  }
52
117
  else
53
118
  {}
@@ -74,107 +139,8 @@ module Hachi
74
139
  end
75
140
  end
76
141
 
77
- def get(path, params = {}, &block)
78
- url = url_for(path)
79
- url.query = URI.encode_www_form(params) unless params.empty?
80
-
81
- get = Net::HTTP::Get.new(url)
82
- get.add_field "Authorization", "Bearer #{api_key}"
83
- request(get, &block)
84
- end
85
-
86
- def post(path, params = {}, &block)
87
- url = url_for(path)
88
-
89
- post = Net::HTTP::Post.new(url)
90
- post.body = params.is_a?(Hash) ? params.to_json : params.to_s
91
-
92
- post.add_field "Content-Type", "application/json"
93
- post.add_field "Authorization", "Bearer #{api_key}"
94
-
95
- request(post, &block)
96
- end
97
-
98
- def delete(path, params = {}, &block)
99
- url = url_for(path)
100
- url.query = URI.encode_www_form(params) unless params.empty?
101
-
102
- delete = Net::HTTP::Delete.new(url)
103
- delete.add_field "Authorization", "Bearer #{api_key}"
104
- request(delete, &block)
105
- end
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
-
119
- def validate_range(range)
120
- return true if range == "all"
121
- raise ArgumentError, "range should be 'all' or `from-to`" unless range.match?(/(\d+)-(\d+)/)
122
-
123
- from, to = range.split("-").map(&:to_i)
124
- return true if from < to
125
-
126
- raise ArgumentError, "from should be smaller than to"
127
- end
128
-
129
- def _search(path, attributes:, range: "all", sort: nil)
130
- validate_range range
131
-
132
- attributes = normalize_attributes(attributes)
133
- conditions = attributes.map do |key, value|
134
- if key == :data && value.is_a?(Array)
135
- { _or: decompose_data(value) }
136
- else
137
- { _string: "#{key}:\"#{value}\"" }
138
- end
139
- end
140
-
141
- default_conditions = {
142
- _and: [
143
- { _not: { status: "Deleted" } },
144
- { _not: { _in: { _field: "_type", _values: ["dashboard", "data", "user", "analyzer", "caseTemplate", "reportTemplate", "action"] } } },
145
- ],
146
- }
147
-
148
- query = {
149
- _and: [conditions, default_conditions].flatten,
150
- }
151
-
152
- query_string = build_query_string(range: range, sort: sort)
153
-
154
- post("#{path}?#{query_string}", query: query) { |json| json }
155
- end
156
-
157
- def decompose_data(data)
158
- data.map do |elem|
159
- { _field: "data", _value: elem }
160
- end
161
- end
162
-
163
- def normalize_attributes(attributes)
164
- h = {}
165
- attributes.each do |key, value|
166
- h[camelize(key).to_sym] = value
167
- end
168
- h
169
- end
170
-
171
- def camelize(string)
172
- head, *others = string.to_s.split("_")
173
- [head, others.map(&:capitalize)].flatten.join
174
- end
175
-
176
142
  def build_query_string(params)
177
- URI.encode_www_form(params.reject { |_k, v| v.nil? })
143
+ URI.encode_www_form(params.compact)
178
144
  end
179
145
  end
180
146
  end
@@ -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("/api/case/#{id}") { |json| json }
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("/api/case/#{id}") { |json| json }
25
+ delete("/case/#{id}") { |json| json }
35
26
  end
36
27
 
37
28
  #
38
29
  # Create a case
39
30
  #
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
- #
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", kase.payload) { |json| json }
64
- end
65
-
66
- #
67
- # Find cases
68
- #
69
- # @param [Hash] attributes
70
- # @param [String] range
71
- #
72
- # @return [Hash]
73
- #
74
- def search(attributes, range: "all")
75
- _search("/api/case/_search", attributes: attributes, 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 merge(id1, id2)
98
- post("/api/case/#{id1}/_merge/#{id2}") { |json| json }
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, 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
42
+ # @param [String] id
43
+ # @param [Hash] payload
120
44
  #
121
45
  # @return [Hash]
122
46
  #
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 }
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
@@ -9,7 +9,7 @@ module Hachi
9
9
  # @return [Hash]
10
10
  #
11
11
  def current
12
- get("/api/user/current") { |json| json }
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("/api/user/#{id}") { |json| json }
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("/api/user/#{id}") { |json| json }
34
+ delete("/user/#{id}") { |json| json }
35
35
  end
36
36
 
37
37
  #
38
38
  # Create a user
39
39
  #
40
- # @param [String] login
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(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 }
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hachi
4
- VERSION = "0.3.1"
4
+ VERSION = "2.0.0"
5
5
  end
data/lib/hachi.rb CHANGED
@@ -2,20 +2,29 @@
2
2
 
3
3
  require "hachi/version"
4
4
 
5
- require "hachi/api"
5
+ require "hachi/awrence/methods"
6
6
 
7
- require "hachi/models/base"
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
data/renovate.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": [
3
+ "config:base"
4
+ ]
5
+ }