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.
@@ -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