nexpose 7.2.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +134 -15
- data/Gemfile.lock +89 -36
- data/README.markdown +6 -1
- data/Rakefile +2 -0
- data/lib/eso.rb +23 -0
- data/lib/eso/conductor.rb +227 -0
- data/lib/eso/configuration/configuration.rb +124 -0
- data/lib/eso/configuration/configuration_manager.rb +145 -0
- data/lib/eso/filter.rb +137 -0
- data/lib/eso/integration_option.rb +88 -0
- data/lib/eso/integration_options_manager.rb +178 -0
- data/lib/eso/nexpose.rb +212 -0
- data/lib/eso/service.rb +83 -0
- data/lib/eso/step.rb +166 -0
- data/lib/eso/step_configuration.rb +73 -0
- data/lib/eso/workflow.rb +149 -0
- data/lib/nexpose/ajax.rb +1 -0
- data/lib/nexpose/role.rb +1 -0
- data/lib/nexpose/util.rb +2 -1
- data/lib/nexpose/version.rb +1 -1
- metadata +19 -8
@@ -0,0 +1,145 @@
|
|
1
|
+
module Eso
|
2
|
+
##
|
3
|
+
# This class represents a configuration manager service, which manages a number of configurations (ie a hostname,
|
4
|
+
# port, username, and password) used to connect to services, and the services they connect to (ie, ePO, dxl, palo-alto).
|
5
|
+
#
|
6
|
+
class ConfigurationManager
|
7
|
+
attr_accessor :url, :nexpose_console
|
8
|
+
|
9
|
+
##
|
10
|
+
# Constructor for ConfigurationManager.
|
11
|
+
#
|
12
|
+
# @param [Nexpose::Connection] nsc A logged-in Nexpose::Connection object with a valid session used to authenticate.
|
13
|
+
# @return [Eso::ConfigurationManager] The newly created configurationManager object
|
14
|
+
#
|
15
|
+
def initialize(nsc)
|
16
|
+
@nexpose_console = nsc
|
17
|
+
@url = "https://#{nsc.host}:#{nsc.port}/eso/configuration-manager/api/"
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Return all of the services that are currently supported by this configuration manager.
|
22
|
+
#
|
23
|
+
# @return [Array] An array containing all of services in the configuration manager in String object form.
|
24
|
+
# Returns an empty array if no services have been configured.
|
25
|
+
#
|
26
|
+
def services
|
27
|
+
json_data = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}service/", ::Nexpose::AJAX::CONTENT_TYPE::JSON)
|
28
|
+
JSON.parse(json_data)
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Return all of the configurations of a particular service type.
|
33
|
+
#
|
34
|
+
# @param [String] service_name The name of a service to find configurations of.
|
35
|
+
# @return [Array] An array containing all the configurations of the given service type.
|
36
|
+
#
|
37
|
+
def service_configurations(service_name)
|
38
|
+
json_data = ::Nexpose::AJAX.get(@nexpose_console,
|
39
|
+
"#{@url}service/configuration/#{service_name}/",
|
40
|
+
::Nexpose::AJAX::CONTENT_TYPE::JSON)
|
41
|
+
JSON.parse(json_data, :symbolize_names => true)
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Return the configuration of a particular service type with a particular name.
|
46
|
+
#
|
47
|
+
# @param [String] service_name The name of a service to find configurations of.
|
48
|
+
# @param [String] config_name The name of the Configuration.
|
49
|
+
# @return [Eso::Configuration] A Configuration object which matches the service name and config name requested.
|
50
|
+
def configuration_by_name(service_name, config_name)
|
51
|
+
service_configs_by_type = service_configurations(service_name)
|
52
|
+
config_hash = service_configs_by_type.find { |config| config[:configName] == config_name }
|
53
|
+
Eso::Configuration.load(config_hash)
|
54
|
+
end
|
55
|
+
|
56
|
+
def configuration_type(service_name:)
|
57
|
+
json_data = ::Nexpose::AJAX.get(@nexpose_console,
|
58
|
+
"#{@url}service/configurationType/#{service_name.downcase}",
|
59
|
+
::Nexpose::AJAX::CONTENT_TYPE::JSON)
|
60
|
+
JSON.parse(json_data)
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Get a configuration by id. Runs a GET call against the eso/configuration-manager/api/service/configuration/CONFIGURATION_ID endpoint
|
65
|
+
# @param [String] configuration_id The id of the configuration to get
|
66
|
+
# return [JSON] A json object representing a configuration
|
67
|
+
# TODO : Update to use an Eso::Configuration
|
68
|
+
def get_configuration(configuration_id)
|
69
|
+
json_data = ::Nexpose::AJAX.get(@nexpose_console, "#{@url}/service/configuration/id/#{configuration_id}", ::Nexpose::AJAX::CONTENT_TYPE::JSON)
|
70
|
+
JSON.parse(json_data, :symbolize_names => true)
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Create a new configuration.
|
75
|
+
#
|
76
|
+
# @param [String] payload The JSON representation of a configuration.
|
77
|
+
# @return [Integer] The configID (>= 1) of the newly created configuration. Raises error on failure.
|
78
|
+
# TODO: Update to use an Eso::Configuration
|
79
|
+
def post_service_configuration(payload)
|
80
|
+
# TODO retry if the post fails on timeout
|
81
|
+
response_body = ::Nexpose::AJAX.post(@nexpose_console, "#{@url}service/configuration", payload, ::Nexpose::AJAX::CONTENT_TYPE::JSON)
|
82
|
+
config_id = Integer(JSON.parse(response_body)['data'])
|
83
|
+
raise Exception.new("API returned invalid configID (#{config_id}) while attempting to create configuration.") unless config_id >= 1
|
84
|
+
config_id
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Test a configuration.
|
89
|
+
#
|
90
|
+
# @param [String] payload The JSON representation of a configuration.
|
91
|
+
# @return [String] The response from the call or an APIError
|
92
|
+
# TODO: Update to use an Eso::Configuration
|
93
|
+
def test_service_configuration(payload)
|
94
|
+
::Nexpose::AJAX.post(@nexpose_console,
|
95
|
+
"#{@url}service/configuration/test",
|
96
|
+
payload,
|
97
|
+
::Nexpose::AJAX::CONTENT_TYPE::JSON)
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Delete a configuration. Runs a DELETE call against the eso/configuration-manager/api/service/configuration/CONFIGURATION_ID endpoint
|
102
|
+
#
|
103
|
+
# @param [String] configuration_id The id of the configuration to delete
|
104
|
+
# return [Boolean] Return true if the api reports a successful delete. Raises an error on failure.
|
105
|
+
def delete(configuration_id)
|
106
|
+
response_body = ::Nexpose::AJAX.delete(@nexpose_console, "#{@url}service/configuration/#{configuration_id}")
|
107
|
+
raise Exception.new("Failed to delete configuration with ID: #{configuration_id}") unless 'success' == response_body
|
108
|
+
true
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# Preview assets for a configuration. Calls a POST to the eso/configuration-manager/api/service/configuration/preview endpoint
|
113
|
+
#
|
114
|
+
# @param configuration The configuration to preview
|
115
|
+
# return [Array] previewed assets
|
116
|
+
# TODO: Update to use an Eso::Configuration
|
117
|
+
def preview_assets(configuration)
|
118
|
+
response_body = ::Nexpose::AJAX.post(@nexpose_console,
|
119
|
+
"#{@url}service/configuration/preview",
|
120
|
+
configuration,
|
121
|
+
::Nexpose::AJAX::CONTENT_TYPE::JSON)
|
122
|
+
@preview_assets = JSON.parse(response_body)["previewAssets"]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
module ConfigManagerMessages
|
127
|
+
module TestConfig
|
128
|
+
AUTH_FAILED_AWS = 'Could not authenticate to Amazon Web Services.'
|
129
|
+
# Actual message will list out the bad ARNs
|
130
|
+
AUTH_FAILED_AWS_ARN = /Could not authenticate to Amazon Web Services with the following ARNs/
|
131
|
+
|
132
|
+
CONNECTION_SUCCESSFUL = 'The connection to the external service was successful.'
|
133
|
+
# Applies to invalid user, password, wrong protocol, can't reach server, bad base or search query
|
134
|
+
CONNECTION_FAILED = 'The connection to the external service failed.'
|
135
|
+
|
136
|
+
INVALID_FIELDS = 'The configuration had invalid fields.'
|
137
|
+
|
138
|
+
RETRY_AD = 'Failed to reach out to the Active Directory service, will try again.'
|
139
|
+
RETRY_AWS = 'Failed to reach out to Amazon Web Services, will try again.'
|
140
|
+
RETRY_AZURE = 'Failed to reach out to the Azure service, will try again.'
|
141
|
+
RETRY_DXL = 'The DXL connection is currently down and the connection is in retry status.'
|
142
|
+
RETRY_EPO = 'Failed to reach out to the ePO service, will try again.'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/eso/filter.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
module Eso
|
2
|
+
class Filter
|
3
|
+
# These are defined in Eso::Filters which reside in the respective service they are related to.
|
4
|
+
attr_accessor :type
|
5
|
+
|
6
|
+
# These are the individual filter items
|
7
|
+
attr_accessor :filter_items
|
8
|
+
|
9
|
+
# Constructor for Filter.
|
10
|
+
#
|
11
|
+
# @param [String] type The type of filter this is. They are based on the service this filter exists in. These are defined in Eso::Filters which reside in the respective service they are related to.
|
12
|
+
# @param [Array] items Array of filters of this type
|
13
|
+
# @return [Eso::Filter] The newly created filter object
|
14
|
+
#
|
15
|
+
def initialize(type:, items: [])
|
16
|
+
@type = type
|
17
|
+
@filter_items = items
|
18
|
+
end
|
19
|
+
|
20
|
+
# Append a filter_item later
|
21
|
+
def <<(filter_item)
|
22
|
+
@filter_items << filter_item
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_json
|
26
|
+
self.to_hash.to_json
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_hash
|
30
|
+
hash = {}
|
31
|
+
hash[@type.to_sym] = {
|
32
|
+
valueClass: 'Array',
|
33
|
+
items: @filter_items.map{|item| item.to_hash}
|
34
|
+
}
|
35
|
+
hash
|
36
|
+
end
|
37
|
+
alias_method :to_h, :to_hash
|
38
|
+
|
39
|
+
class FilterItem
|
40
|
+
attr_accessor :type
|
41
|
+
# Examples are "OR", "IN", "CONTAINS". These should probably be constantized somewhere.
|
42
|
+
attr_accessor :operator
|
43
|
+
|
44
|
+
# Array containing the values to filter on
|
45
|
+
attr_accessor :operands
|
46
|
+
|
47
|
+
def initialize(type:, operator:, operands:)
|
48
|
+
@type = "#{type}_ITEM"
|
49
|
+
@operator = operator
|
50
|
+
process_operands(operands)
|
51
|
+
end
|
52
|
+
|
53
|
+
def process_operands(operands)
|
54
|
+
@operands =
|
55
|
+
if ["IS_EMPTY", "IS_NOT_EMPTY"].include? @operator
|
56
|
+
nil
|
57
|
+
elsif @type == "#{Eso::Filters::IP_ADDRESS}_ITEM" ||
|
58
|
+
@type == "#{Eso::Filters::IP_RANGE}_ITEM" ||
|
59
|
+
@type == "#{Eso::Filters::OPEN_PORT}_ITEM" ||
|
60
|
+
@type == "#{Eso::Filters::RISK_SCORE}_ITEM" ||
|
61
|
+
@type == "#{Eso::Filters::CVSS_SCORE}_ITEM"
|
62
|
+
operands.first.split('-')
|
63
|
+
else
|
64
|
+
operands
|
65
|
+
end
|
66
|
+
|
67
|
+
if @operands == nil
|
68
|
+
return
|
69
|
+
end
|
70
|
+
@operands.map! do |value|
|
71
|
+
# This regex is used to determine if the string is actually a float.
|
72
|
+
# http://stackoverflow.com/questions/1034418/determine-if-a-string-is-a-valid-float-value
|
73
|
+
if value =~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
|
74
|
+
if (@type == "#{Eso::Filters::OPEN_PORT}_ITEM")
|
75
|
+
value.to_i
|
76
|
+
else
|
77
|
+
value.to_f
|
78
|
+
end
|
79
|
+
# If it's not a float, let's see if it's an integer.
|
80
|
+
elsif value.to_i.to_s == value
|
81
|
+
value.to_i
|
82
|
+
# Guess not, so lets keep the original value.
|
83
|
+
else
|
84
|
+
value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_hash
|
90
|
+
hash = {
|
91
|
+
valueClass: "Object",
|
92
|
+
objectType: @type,
|
93
|
+
properties: {
|
94
|
+
operator: {
|
95
|
+
valueClass: "String",
|
96
|
+
value: @operator
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
# Currently there are no standards that say how many operands a filter can have
|
101
|
+
operand_hash = {}
|
102
|
+
operand_counter = 1
|
103
|
+
unless @operands.nil?
|
104
|
+
@operands.each do |operand|
|
105
|
+
label = "operand#{operand_counter}".to_sym
|
106
|
+
|
107
|
+
# A correct value class is required because Jackson expects it.
|
108
|
+
# A Jackson processor for Ruby would probably make this much nicer
|
109
|
+
# Also, defaulting to Number is probably a bad idea, but based on current possible values in ESO this works.
|
110
|
+
case operand.class.to_s
|
111
|
+
|
112
|
+
when "String"
|
113
|
+
value_class = "String"
|
114
|
+
when "Array"
|
115
|
+
value_class = "Array"
|
116
|
+
when "Fixnum"
|
117
|
+
value_class = "Integer"
|
118
|
+
else
|
119
|
+
value_class = "Number"
|
120
|
+
end
|
121
|
+
|
122
|
+
operand_hash[label] = {
|
123
|
+
valueClass: value_class,
|
124
|
+
value: operand
|
125
|
+
}
|
126
|
+
operand_counter += 1
|
127
|
+
end
|
128
|
+
|
129
|
+
hash[:properties].merge! operand_hash
|
130
|
+
end
|
131
|
+
|
132
|
+
hash
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Eso
|
2
|
+
|
3
|
+
module IntegrationOptionNames
|
4
|
+
IMPORT_AD_ASSETS = 'import_ad_assets'
|
5
|
+
IMPORT_EPO_ASSETS = 'import_epo_assets'
|
6
|
+
SYNC_AZURE_ASSETS = 'sync_azure_assets'
|
7
|
+
SYNC_AZURE_ASSETS_WITH_TAGS = 'sync_azure_assets_with_tags'
|
8
|
+
end
|
9
|
+
|
10
|
+
# IntegrationOptionTypes is a way to categorize what various Integration Options do.
|
11
|
+
module IntegrationOptionTypes
|
12
|
+
# The IMPORT_TO_SITE Array tracks Integration Options which load Assets into a Site.
|
13
|
+
IMPORT_TO_SITE = [
|
14
|
+
IntegrationOptionNames::IMPORT_AD_ASSETS,
|
15
|
+
IntegrationOptionNames::IMPORT_EPO_ASSETS,
|
16
|
+
IntegrationOptionNames::SYNC_AZURE_ASSETS,
|
17
|
+
IntegrationOptionNames::SYNC_AZURE_ASSETS_WITH_TAGS
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
class IntegrationOption
|
22
|
+
attr_accessor :name
|
23
|
+
attr_accessor :steps
|
24
|
+
attr_accessor :id
|
25
|
+
|
26
|
+
def initialize(id: nil, name:, steps: [])
|
27
|
+
@id = id
|
28
|
+
@name = name
|
29
|
+
@steps = steps
|
30
|
+
end
|
31
|
+
|
32
|
+
def site_id=(site_id)
|
33
|
+
# As of now, the site is always in the last Step of the IntegrationOption. Might change.
|
34
|
+
@steps.last.add_property(StepConfiguration::ConfigParamProperties::SITE_ID, site_id)
|
35
|
+
end
|
36
|
+
|
37
|
+
def site_id
|
38
|
+
# As of now, the site is always in the last Step of the IntegrationOption. Might change.
|
39
|
+
@steps.last.site_id
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return this object and the associated steps in a digestible JSON format.
|
43
|
+
#
|
44
|
+
# @return [String] JSON interpretation of this workflow.
|
45
|
+
#
|
46
|
+
def to_json
|
47
|
+
# Convert Object to Hash
|
48
|
+
hash = self.to_hash
|
49
|
+
|
50
|
+
# Grab the Step objects and convert to Hashes
|
51
|
+
steps = hash['steps']
|
52
|
+
hashified_steps = []
|
53
|
+
steps.each {|step| hashified_steps << step.to_hash}
|
54
|
+
hash['steps'] = hashified_steps
|
55
|
+
|
56
|
+
# Convert Hash to JSON
|
57
|
+
hash.to_json
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return this object as a Hash. The corresponding Steps will still be objects.
|
61
|
+
#
|
62
|
+
# @return [Hash] Hash interpretation of this IntegrationOption.
|
63
|
+
def to_hash
|
64
|
+
hash = {}
|
65
|
+
instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var)}
|
66
|
+
hash
|
67
|
+
end
|
68
|
+
|
69
|
+
# Load a Hash of an IntegrationOption into an actual IntegrationOption. Probably didn't need to
|
70
|
+
# break out separately, but might be useful
|
71
|
+
#
|
72
|
+
# @param [Hash] raw_integration_option is a Hash representation of an IntegrationOption
|
73
|
+
# @return [IntegrationOption] The IntegrationOption version of the Hash
|
74
|
+
def self.load(raw_integration_option)
|
75
|
+
integration_option = IntegrationOption.new(id: raw_integration_option[:id], name: raw_integration_option[:name])
|
76
|
+
steps = raw_integration_option[:steps]
|
77
|
+
steps.each do |step|
|
78
|
+
step_config = step[:stepConfiguration]
|
79
|
+
integration_option.steps << Step.new(uuid: step[:uuid],
|
80
|
+
service_name: step[:serviceName],
|
81
|
+
type_name: step_config[:typeName],
|
82
|
+
previous_type_name: step_config[:previousTypeName],
|
83
|
+
configuration_params: step_config[:configurationParams])
|
84
|
+
end
|
85
|
+
integration_option
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -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
|