nexpose 7.2.1 → 7.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|