nexpose 7.0.1 → 7.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.
@@ -0,0 +1,178 @@
1
+ require 'nexpose'
2
+
3
+ module Eso
4
+ ##
5
+ # This class is a manager for the integration options api. Integration options match epo/dxl/etc steps
6
+ # (ie discover-epo-assets) to nexpose steps (ie import-external-assets).
7
+
8
+ class IntegrationOptionsManager
9
+
10
+ ##
11
+ # Constructor for IntegrationOptionsManager.
12
+ #
13
+ # @param [Nexpose::Connection] nsc A logged-in Nexpose::Connection object with a valid session used to authenticate.
14
+ # @return [Eso::IntegrationOptionsManager] The newly created IntegrationOptionManager object
15
+ #
16
+ def initialize(nsc)
17
+ @nexpose_console = nsc
18
+ @url = "https://#{nsc.host}:#{nsc.port}/eso/integration-manager-service/api/integration-options/"
19
+ end
20
+
21
+ ##
22
+ # Create a new or Update existing integration option.
23
+ #
24
+ # @param [String] payload The JSON representation of an integration option.
25
+ # @return [String] The integrationOptionID (a UUID) of the newly created configuration. Raises error on failure.
26
+ #
27
+ def create(payload)
28
+ # TODO retry if the post fails on timeout
29
+ response_body = ::Nexpose::AJAX.post(@nexpose_console, "#{@url}", payload, ::Nexpose::AJAX::CONTENT_TYPE::JSON)
30
+ JSON.parse(response_body)['data']['id']
31
+ end
32
+ alias_method :update, :create
33
+
34
+ # Deleting and stopping are the same thing
35
+ def delete(integration_option_id)
36
+ ::Nexpose::AJAX.delete(@nexpose_console, "#{@url}#{integration_option_id}/state")
37
+ end
38
+ alias_method :stop, :delete
39
+
40
+ ##
41
+ # Get an existing integration option.
42
+ #
43
+ # @param [String] integration_option_id The integration_option_id of the integration option.
44
+ # @return IntegrationOption for that id, or nil
45
+ #
46
+ def get(integration_option_id)
47
+ # Gets all integration options
48
+ response_body = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}", ::Nexpose::AJAX::CONTENT_TYPE::JSON)
49
+ response = JSON.parse(response_body, symbolize_names: true)
50
+
51
+ # Find the desired one
52
+ raw_integration_option = response.find{|raw| raw[:id] == integration_option_id}
53
+ raise "No IntegrationOption with ID #{integration_option_id}" if raw_integration_option.nil?
54
+
55
+ # Load it to an object
56
+ IntegrationOption.load(raw_integration_option)
57
+ end
58
+
59
+ ##
60
+ # Get the status of an integration option.
61
+ #
62
+ # @param [String] integration_option_id The integration_option_id of the integration option.
63
+ # @return the state (READY, STOPPED, etc)
64
+ #
65
+ def status(integration_option_id)
66
+ response_body = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}#{integration_option_id}/status", ::Nexpose::AJAX::CONTENT_TYPE::JSON)
67
+ response = JSON.parse(response_body)
68
+ response['state']
69
+ end
70
+
71
+ def start(integration_option_id)
72
+ response_body = ::Nexpose::AJAX.post(@nexpose_console, "#{@url}#{integration_option_id}/state", ::Nexpose::AJAX::CONTENT_TYPE::JSON)
73
+ JSON.parse(response_body)
74
+ end
75
+
76
+ # TODO: These build_* methods must die.
77
+ def self.build_import_epo_assets_option(name:, discovery_conn_id:, site_id: nil)
78
+ step1 = Step.new(service_name: ServiceNames::EPO, type_name: StepNames::DISCOVER_EPO)
79
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
80
+ step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::IMPORT_EXTERNAL, previous_type_name: step1.type_name)
81
+
82
+ #This isn't always known immediately, which is why we have IntegrationOption.site_id=
83
+ step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id
84
+ IntegrationOption.new(name: name, steps: [step1, step2])
85
+ end
86
+
87
+ def self.build_import_ad_assets_option(name:, discovery_conn_id:, site_id: nil)
88
+ step1 = Step.new(service_name: ServiceNames::ACTIVE_DIRECTORY, type_name: StepNames::DISCOVER_ACTIVE_DIRECTORY)
89
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
90
+ step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::IMPORT_EXTERNAL, previous_type_name: step1.type_name)
91
+
92
+ #This isn't always known immediately, which is why we have IntegrationOption.site_id=
93
+ step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id
94
+ IntegrationOption.new(name: name, steps: [step1, step2])
95
+ end
96
+
97
+ def self.build_sync_aws_assets_option(name:, discovery_conn_id:, site_id: nil)
98
+ step1 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::DISCOVER_AWS_ASSETS)
99
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
100
+ step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name)
101
+
102
+ #This isn't always known immediately, which is why we have IntegrationOption.site_id=
103
+ step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id
104
+ IntegrationOption.new(name: name, steps: [step1, step2])
105
+ end
106
+
107
+ def self.build_verify_aws_targets_option(name:, discovery_conn_id:)
108
+ step1 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::VERIFY_AWS_ASSETS)
109
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
110
+ step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::VERIFY_EXTERNAL_TARGETS,
111
+ previous_type_name: step1.type_name)
112
+ step3 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::VERIFY_AWS_ASSETS,
113
+ previous_type_name: step2.type_name)
114
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
115
+
116
+ IntegrationOption.new(name: name, steps: [step1, step2, step3])
117
+ end
118
+
119
+ def self.build_sync_azure_assets_option(name:, discovery_conn_id:, site_id: nil)
120
+ step1 = Step.new(service_name: ServiceNames::AZURE, type_name: StepNames::DISCOVER_AZURE_ASSETS)
121
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
122
+ step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name)
123
+
124
+ #This isn't always known immediately, which is why we have IntegrationOption.site_id=
125
+ step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id
126
+ IntegrationOption.new(name: name, steps: [step1, step2])
127
+ end
128
+
129
+ def self.build_sync_aws_assets_with_tags_option(name:, discovery_conn_id:, site_id: nil, tags: '')
130
+ step1 = Step.new(service_name: ServiceNames::AWS, type_name: StepNames::DISCOVER_AWS_ASSETS)
131
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
132
+ .add_property(StepConfiguration::ConfigParamProperties::IMPORT_TAGS, true)
133
+ .add_property(StepConfiguration::ConfigParamProperties::EXCLUDE_ASSETS_WITH_TAGS, "")
134
+ .add_property(StepConfiguration::ConfigParamProperties::ONLY_IMPORT_THESE_TAGS, tags)
135
+ step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name)
136
+
137
+ #This isn't always known immediately, which is why we have IntegrationOption.site_id=
138
+ step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id
139
+ IntegrationOption.new(name: name, steps: [step1, step2])
140
+ end
141
+
142
+ def self.build_sync_azure_assets_with_tags_option(name:, discovery_conn_id:, site_id: nil, only_tags: '', exclude_tags: '')
143
+ step1 = Step.new(service_name: ServiceNames::AZURE, type_name: StepNames::DISCOVER_AZURE_ASSETS)
144
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
145
+ .add_property(StepConfiguration::ConfigParamProperties::IMPORT_TAGS, true)
146
+ .add_property(StepConfiguration::ConfigParamProperties::EXCLUDE_ASSETS_WITH_TAGS, exclude_tags)
147
+ .add_property(StepConfiguration::ConfigParamProperties::ONLY_IMPORT_THESE_TAGS, only_tags)
148
+ step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::SYNC_EXTERNAL, previous_type_name: step1.type_name)
149
+
150
+ #This isn't always known immediately, which is why we have IntegrationOption.site_id=
151
+ step2.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id) if site_id
152
+ IntegrationOption.new(name: name, steps: [step1, step2])
153
+ end
154
+
155
+ def self.build_export_risk_scores_option(name:, discovery_conn_id:)
156
+ step1 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::RISK_SCORE_UPDATED)
157
+ step2 = Step.new(service_name: ServiceNames::EPO, type_name: StepNames::PUSH_RISK_SCORE, previous_type_name: step1.type_name)
158
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
159
+ IntegrationOption.new(name: name, steps: [step1, step2])
160
+ end
161
+
162
+ def self.build_find_vuln_details_option(name:, discovery_conn_id:)
163
+ step1 = Step.new(service_name: ServiceNames::DXL, type_name: StepNames::VULN_DETAILS_REQUEST)
164
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
165
+ step2 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::VULN_DETAILS, previous_type_name: step1.type_name)
166
+ step3 = Step.new(service_name: ServiceNames::DXL, type_name: StepNames::VULN_DETAILS_REQUEST, previous_type_name: step2.type_name)
167
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
168
+ IntegrationOption.new(name: name, steps: [step1, step2, step3])
169
+ end
170
+
171
+ def self.build_publish_vulnerabilities_option(name:, discovery_conn_id:)
172
+ step1 = Step.new(service_name: ServiceNames::NEXPOSE, type_name: StepNames::NEW_ASSET_VULN)
173
+ step2 = Step.new(service_name: ServiceNames::DXL, type_name: StepNames::PUBLISH_VULN_INT_TYPE, previous_type_name: step1.type_name)
174
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, discovery_conn_id)
175
+ IntegrationOption.new(name: name, steps: [step1, step2])
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,212 @@
1
+ require 'nexpose'
2
+
3
+ module Eso
4
+ module ServiceNames
5
+ ACTIVE_DIRECTORY = 'active-directory'
6
+ AWS = 'amazon-web-services'
7
+ AZURE = 'azure'
8
+ DXL = 'dxl'
9
+ EPO = 'epo'
10
+ NEXPOSE = 'nexpose'
11
+ end
12
+
13
+ module StepNames
14
+ ADD_TO_SITE = 'add-to-site'
15
+ ADD_VULN_AND_SCAN = 'add-vulnerabilities-to-site-and-scan'
16
+ DISCOVER_ACTIVE_DIRECTORY = 'discover-ad-assets'
17
+ DISCOVER_AWS_ASSETS = 'discover-aws-assets'
18
+ DISCOVER_AZURE_ASSETS = 'discover-azure-assets'
19
+ DISCOVER_EPO = 'discover-epo-assets'
20
+ DISCOVER_KNOWN = 'discover-known-assets'
21
+ DISCOVER_NEW = 'discover-new-assets'
22
+ DISCOVERY_CONFIG_METADATA = 'discoveryConfigMetadata'
23
+ EMPTY = ''
24
+ FILE_REPUTATION_TRIGGER = 'tie-file-reputation-trigger'
25
+ IMPORT_EXTERNAL = 'import-external-assets'
26
+ NEW_ASSET_VULN = 'new-asset-vulnerability'
27
+ NEW_VULN = 'new-vulnerabilities'
28
+ PUBLISH_VULN_INT_TYPE = 'publish-vulnerability-integration-type'
29
+ PUSH_RISK_SCORE = 'push-risk-score'
30
+ RISK_SCORE_UPDATED = 'risk-score-updated'
31
+ SCAN = 'scan'
32
+ SCAN_IN_SITE = 'scan-in-site'
33
+ SYNC_EXTERNAL = 'sync-external-assets'
34
+ TAG = 'tag'
35
+ VERIFY_AWS_ASSETS = 'verify-aws-targets'
36
+ VERIFY_EXTERNAL_TARGETS = 'verify-external-targets'
37
+ VULN_DETAILS = 'vulnerability-details'
38
+ VULN_DETAILS_REQUEST = 'vulnerability-details-request'
39
+ end
40
+
41
+ module Values
42
+ ARRAY = 'Array'
43
+ BOOLEAN = 'Boolean'
44
+ INTEGER = 'Integer'
45
+ OBJECT = 'Object'
46
+ STRING = 'String'
47
+ end
48
+
49
+ module StepConfigTypes
50
+ DISCOVERY_CONFIG = [StepNames::DISCOVER_ACTIVE_DIRECTORY,
51
+ StepNames::DISCOVER_AWS_ASSETS,
52
+ StepNames::DISCOVER_AZURE_ASSETS,
53
+ StepNames::DISCOVER_EPO,
54
+ StepNames::DISCOVER_KNOWN,
55
+ StepNames::DISCOVER_NEW,
56
+ StepNames::FILE_REPUTATION_TRIGGER,
57
+ StepNames::PUBLISH_VULN_INT_TYPE,
58
+ StepNames::PUSH_RISK_SCORE,
59
+ StepNames::VULN_DETAILS_REQUEST]
60
+ EMPTY = [StepNames::NEW_ASSET_VULN,
61
+ StepNames::NEW_VULN,
62
+ StepNames::RISK_SCORE_UPDATED,
63
+ StepNames::VULN_DETAILS]
64
+ SITE = [StepNames::ADD_TO_SITE,
65
+ StepNames::ADD_VULN_AND_SCAN,
66
+ StepNames::IMPORT_EXTERNAL,
67
+ StepNames::SCAN,
68
+ StepNames::SCAN_IN_SITE,
69
+ StepNames::SYNC_EXTERNAL]
70
+ TAG = [StepNames::TAG]
71
+ VERIFY = [StepNames::DISCOVER_AWS_ASSETS]
72
+ end
73
+
74
+ module Filters
75
+ CVSS_SCORE = 'CVSS_SCORE'
76
+ DHCP_HOST_NAME = 'DHCP_HOST_NAME'
77
+ HOURS_SINCE_LAST_SCAN= 'HOURS_SINCE_LAST_SCAN'
78
+ HOURS_SINCE_LAST_SCAN_ITEM = 'HOURS_SINCE_LAST_SCAN_ITEM'
79
+ IP_ADDRESS = 'IP_ADDRESS'
80
+ IP_RANGE = 'IP_RANGE'
81
+ MAC_ADDRESS = 'MAC_ADDRESS'
82
+ OPEN_PORT = 'OPEN_PORT'
83
+ RISK_SCORE = 'RISK_SCORE'
84
+ SERVICE_NAME = 'SERVICE_NAME'
85
+ end
86
+
87
+ module Nexpose
88
+ def self.create_discovery_workflow(conductor:, name:, step1_type:, step1_param: nil, step2_type:, step2_param:)
89
+ step1 = self.send("create_#{step1_type.to_s.gsub(/-/, "_")}_step", id: step1_param)
90
+ step2 = self.send("create_#{step2_type.to_s.gsub(/-/, "_")}_step", id: step2_param)
91
+ step2.previous_type_name = step1.type_name
92
+ conductor.create_workflow(name: name, steps: [step1, step2])
93
+ end
94
+
95
+ def self.create_scan_new_vuln_workflow(conductor:, name:, filters:, site_id:)
96
+ step1 = self.create_new_vuln_step(workflow: nil, filters: filters, previous_type_name: StepNames::EMPTY)
97
+ step2 = self.create_add_vuln_and_scan_step(id: site_id)
98
+ step2.previous_type_name = step1.type_name
99
+ conductor.create_workflow(name: name, steps: [step1, step2])
100
+ end
101
+
102
+ def self.create_file_trigger_workflow(conductor:, name:, step1_param:, step2_param:)
103
+ step1 = self.create_file_reputation_step(workflow: nil, id: step1_param)
104
+ step2 = self.create_tag_step(workflow: nil, id: step2_param)
105
+ step2.previous_type_name = step1.type_name
106
+ conductor.create_workflow(name: name, steps: [step1, step2])
107
+ end
108
+
109
+ def self.create_scan_in_site_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY)
110
+ Step.new(workflow: workflow,
111
+ service_name: ServiceNames::NEXPOSE,
112
+ type_name: StepNames::SCAN_IN_SITE,
113
+ previous_type_name: previous_type_name)
114
+ .add_property(StepConfiguration::ConfigParamProperties::SITE_ID, id)
115
+ end
116
+
117
+ def self.create_file_reputation_step(workflow: nil, id:)
118
+ Step.new(workflow: workflow,
119
+ service_name: ServiceNames::DXL,
120
+ type_name: StepNames::FILE_REPUTATION_TRIGGER,
121
+ previous_type_name: nil)
122
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, id)
123
+ end
124
+
125
+ def self.create_discover_new_assets_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY)
126
+ Step.new(workflow: workflow,
127
+ service_name: ServiceNames::NEXPOSE,
128
+ type_name: StepNames::DISCOVER_NEW,
129
+ previous_type_name: previous_type_name)
130
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, id)
131
+ end
132
+
133
+ def self.create_discover_known_assets_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY)
134
+ step = Step.new(workflow: workflow,
135
+ service_name: ServiceNames::NEXPOSE,
136
+ type_name: StepNames::DISCOVER_KNOWN,
137
+ previous_type_name: previous_type_name)
138
+ .add_property(StepConfiguration::ConfigParamProperties::DISCOVERY_CONFIG_ID, id)
139
+ config_params = step.configuration_params
140
+ config_params[:HOURS_SINCE_LAST_SCAN] = {
141
+ :valueClass => Values::ARRAY,
142
+ :items => [
143
+ {
144
+ :valueClass => Values::OBJECT,
145
+ :objectType => Filters::HOURS_SINCE_LAST_SCAN_ITEM,
146
+ :properties => {
147
+ :operator => {
148
+ :valueClass => Values::STRING,
149
+ :value => ::Nexpose::Search::Operator::GREATER_THAN
150
+ },
151
+ :operand1 => {
152
+ :valueClass => Values::STRING,
153
+ :value => '1'
154
+ }
155
+ }
156
+ }
157
+ ]
158
+ }
159
+ step.configuration_params = config_params
160
+ step
161
+ end
162
+
163
+ def self.create_new_vuln_step(workflow: nil, filters:, previous_type_name: StepNames::EMPTY)
164
+ # The filter definitions on the server are not standard at this point so that is why it is necessary to hard code this
165
+ # Opening a defect to fix the consistency on these on the backend so we can use the add_filter function in the automation
166
+ step = Step.new(workflow: workflow,
167
+ service_name: ServiceNames::NEXPOSE,
168
+ type_name: StepNames::NEW_VULN,
169
+ previous_type_name: previous_type_name)
170
+
171
+ filters.each { |filter| step.add_filter(filter) }
172
+ step
173
+ end
174
+
175
+ def self.create_add_vuln_and_scan_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY)
176
+ Step.new(workflow: workflow,
177
+ service_name: ServiceNames::NEXPOSE,
178
+ type_name: StepNames::ADD_VULN_AND_SCAN,
179
+ previous_type_name: previous_type_name)
180
+ .add_property(StepConfiguration::ConfigParamProperties::SITE_ID, id)
181
+ end
182
+
183
+ def self.create_add_to_site_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY)
184
+ Step.new(workflow: workflow,
185
+ service_name: ServiceNames::NEXPOSE,
186
+ type_name: StepNames::ADD_TO_SITE,
187
+ previous_type_name: previous_type_name)
188
+ .add_property(StepConfiguration::ConfigParamProperties::SITE_ID, id)
189
+ end
190
+
191
+ def self.create_scan_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY)
192
+ Step.new(workflow: workflow,
193
+ service_name: ServiceNames::NEXPOSE,
194
+ type_name: StepNames::SCAN,
195
+ previous_type_name: previous_type_name)
196
+ .add_property(StepConfiguration::ConfigParamProperties::SITE_ID, id)
197
+ end
198
+
199
+ def self.create_tag_step(workflow: nil, id:, previous_type_name: StepNames::EMPTY)
200
+ Step.new(workflow: workflow,
201
+ service_name: ServiceNames::NEXPOSE,
202
+ type_name: StepNames::TAG,
203
+ previous_type_name: previous_type_name)
204
+ .add_property(StepConfiguration::ConfigParamProperties::TAG_ID, id)
205
+ end
206
+
207
+ def self.get_discover_step(workflow: )
208
+ workflow.get_step(StepNames::DISCOVER_NEW) || workflow.get_step(StepNames::DISCOVER_KNOWN)
209
+ end
210
+ end
211
+ end
212
+
@@ -0,0 +1,83 @@
1
+ module Eso
2
+ class Service
3
+ attr_accessor :host
4
+
5
+ attr_accessor :port
6
+
7
+ attr_accessor :url
8
+
9
+ CONTENT_TYPE_JSON = 'application/json; charset-utf-8'
10
+
11
+ def initialize(host:, port: 3780, nsc:)
12
+ @host = host
13
+ @port = port
14
+ @nexpose_console = nsc
15
+ end
16
+
17
+ def get(url:, content_type: CONTENT_TYPE_JSON)
18
+ get = Net::HTTP::Get.new(url)
19
+ get.set_content_type(content_type)
20
+ request(request: get)
21
+ end
22
+
23
+ def put(url:, payload:, content_type: CONTENT_TYPE_JSON)
24
+ put = Net::HTTP::Put.new(url)
25
+ put.set_content_type(content_type)
26
+ put.body = payload.to_s if payload
27
+ request(request: put)
28
+ end
29
+
30
+ def post(url:, payload: nil, content_type: CONTENT_TYPE_JSON)
31
+ post = Net::HTTP::Post.new(url)
32
+ post.set_content_type(content_type)
33
+ post.body = payload.to_s if payload
34
+ request(request: post)
35
+ end
36
+
37
+ def delete(url:, content_type: CONTENT_TYPE_JSON)
38
+ delete = Net::HTTP::Delete.new(url)
39
+ delete.set_content_type(content_type)
40
+ request(request: delete)
41
+ end
42
+
43
+ def http(timeout:)
44
+ http = Net::HTTP.new(@host, @port)
45
+ http.read_timeout = timeout if timeout
46
+ http.use_ssl = false
47
+ http
48
+ end
49
+
50
+ def https(timeout:)
51
+ http = Net::HTTP.new(@host, @port)
52
+ http.read_timeout = timeout if timeout
53
+ http.use_ssl = true
54
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
55
+ http
56
+ end
57
+
58
+ def add_nexpose_session(request:)
59
+ request.add_field('nexposeCCSessionID', @nexpose_console.session_id)
60
+ request.add_field('Cookie', "nexposeCCSessionID=#{@nexpose_console.session_id}")
61
+ request.add_field('X-Requested-With', 'XMLHttpRequest')
62
+ end
63
+
64
+ def request(request:, timeout: nil)
65
+ http = https(timeout: timeout)
66
+ add_nexpose_session(request: request)
67
+ response = http.request(request)
68
+ case response
69
+ when Net::HTTPOK, Net::HTTPCreated
70
+ rv = nil
71
+ if response.content_type == "application/json" && !response.body.empty?
72
+ json_data = JSON.parse(response.body, symbolize_names: true)
73
+ json_data[:data].nil? ? rv = json_data : rv = json_data[:data]
74
+ end
75
+ rv
76
+ when Net::HTTPForbidden
77
+ raise "Access denied. Response was #{response.body}"
78
+ else
79
+ raise "There was an error sending the request. Response was #{response.body}"
80
+ end
81
+ end
82
+ end
83
+ end