Module: ALGOSEC_SDK::BusinessFlowHelper
- Included in:
- Client
- Defined in:
- lib/algosec-sdk/helpers/business_flow_helper.rb
Overview
Contains helper methods for BusinessFlow
Instance Method Summary collapse
-
#apply_application_draft(app_revision_id) ⇒ Object
Apply application draft.
-
#create_application(name, custom_fields = [], contacts = [], labels = [], flows = []) ⇒ Object
Create an application.
-
#create_application_flow(app_revision_id, flow_name, sources, destinations, network_services, network_users, network_apps, comment, type = 'APPLICATION', custom_fields = []) ⇒ Object
Create a flow rubocop:disable Metrics/ParameterLists.
-
#create_missing_network_objects(network_object_names) ⇒ Object
Create all the missing network objects which are simple IPv4 ip or subnet.
-
#create_missing_services(service_names) ⇒ Object
Create all the missing network services which are of simple protocol/port pattern.
-
#create_network_object(type, content, name) ⇒ Object
Create a new network object.
-
#create_network_service(service_name, content) ⇒ Object
Create a new network service.
-
#decommission_application(app_revision_id) ⇒ Object
Decommission an application.
-
#define_application_flows(app_name, new_app_flows) ⇒ Object
Update application flows of an application to match a requested flows configuration.
-
#delete_flow_by_id(app_revision_id, flow_id) ⇒ Object
Delete a specific flow.
-
#get_app_id_by_name(app_name) ⇒ Boolean
Get application id by it’s name.
-
#get_app_revision_id_by_name(app_name) ⇒ Boolean
Get latest application revision id by application name.
-
#get_application_by_name(app_name) ⇒ Hash
Get application by name.
-
#get_application_flow_by_name(app_revision_id, flow_name) ⇒ Object
Fetch an application flow by it’s name.
-
#get_application_flows(app_revision_id) ⇒ Array<Hash>
Get list of application flows for an application revision id.
-
#get_application_flows_hash(app_revision_id) ⇒ Hash
Get application flows from the server as a hash from flow name it it’s content.
-
#get_applications ⇒ Array<Hash>
Get all applications.
-
#get_flow_connectivity(app_revision_id, flow_id) ⇒ String
Get connectivity status for a flow.
-
#implement_app_flows_plan(app_name, new_app_flows, flows_from_server, flows_to_delete, flows_to_create, flows_to_modify) ⇒ Object
Create/modify/delete application2 flows to match a given flow plan returned by ‘plan_application_flows’ param [Array<String>] flows_to_modify List of network flow names to delete and re-create with the new definition.
-
#login ⇒ Array<Hash>
Request login to get session cookie credentials.
-
#plan_application_flows(server_app_flows, new_app_flows) ⇒ Object
Return a plan for modifying application flows based on current and newly proposed application flows definition.
-
#search_network_object(ip_or_subnet, search_type) ⇒ Object
Search a network object.
Instance Method Details
#apply_application_draft(app_revision_id) ⇒ Object
Apply application draft
215 216 217 218 219 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 215 def apply_application_draft(app_revision_id) response = rest_post("/BusinessFlow/rest/v1/applications/#{app_revision_id}/apply") response_handler(response) true end |
#create_application(name, custom_fields = [], contacts = [], labels = [], flows = []) ⇒ Object
Create an application
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 43 def create_application( name, custom_fields = [], contacts = [], labels = [], flows = [] ) new_application = { name: name, custom_fields: custom_fields, contacts: contacts, labels: labels, flows: flows } response = rest_post('/BusinessFlow/rest/v1/applications/new', body: new_application) response_handler(response) end |
#create_application_flow(app_revision_id, flow_name, sources, destinations, network_services, network_users, network_apps, comment, type = 'APPLICATION', custom_fields = []) ⇒ Object
Create a flow rubocop:disable Metrics/ParameterLists
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 122 def create_application_flow( app_revision_id, flow_name, sources, destinations, network_services, network_users, network_apps, comment, type = 'APPLICATION', custom_fields = [] ) # rubocop:enable Metrics/ParameterLists # Create the missing network objects from the sources and destinations create_missing_network_objects(sources + destinations) create_missing_services(network_services) get_named_objects = ->(name_list) { name_list.map { |name| { name: name } } } new_flow = { name: flow_name, sources: get_named_objects.call(sources), destinations: get_named_objects.call(destinations), users: network_users, network_applications: get_named_objects.call(network_apps), services: get_named_objects.call(network_services), comment: comment, type: type, custom_fields: custom_fields } response = rest_post("/BusinessFlow/rest/v1/applications/#{app_revision_id}/flows/new", body: [new_flow]) flows = response_handler(response) # AlgoSec return a list of created flows, we created only one flows[0] end |
#create_missing_network_objects(network_object_names) ⇒ Object
Create all the missing network objects which are simple IPv4 ip or subnet
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 365 def create_missing_network_objects(network_object_names) # TODO: Add unitests that objects are being create only once (if the same object is twice in the incoming list) network_object_names = Set.new(network_object_names) ipv4_or_subnet_objects = network_object_names.map do |object_name| next unless get_network_object_type(object_name) search_results = search_network_object(object_name, NetworkObjectSearchType::EXACT) if search_results.empty? # nothing was found, mark the object for creation object_name else # if no object named the same way, mark it for creation search_results.any? { |result| result['name'] == object_name } ? nil : object_name end end.compact # Create all the objects. If the error from the server tells us that the object already exists, ignore the error ipv4_or_subnet_objects.map do |ipv4_or_subnet| create_network_object(get_network_object_type(ipv4_or_subnet), ipv4_or_subnet, ipv4_or_subnet) end.compact end |
#create_missing_services(service_names) ⇒ Object
Create all the missing network services which are of simple protocol/port pattern
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 390 def create_missing_services(service_names) parsed_services = service_names.map do |service_name| protocol, port = service_name.scan(%r{(TCP|UDP)/(\d+)}i).last [service_name, [protocol, port]] if !protocol.nil? && !port.nil? end.compact # Create all the objects. If the error from the server tells us that the object already exists, ignore the error parsed_services.map do |parsed_service| service_name, service_content = parsed_service begin create_network_service(service_name, [service_content]) rescue StandardError => e # If the error is different from "service already exists", the exception will be re-raised raise e if e.to_s.index('Service name already exists').nil? end end.compact end |
#create_network_object(type, content, name) ⇒ Object
Create a new network object
240 241 242 243 244 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 240 def create_network_object(type, content, name) new_object = { type: type, name: name, content: content } response = rest_post('/BusinessFlow/rest/v1/network_objects/new', body: new_object) response_handler(response) end |
#create_network_service(service_name, content) ⇒ Object
Create a new network service
226 227 228 229 230 231 232 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 226 def create_network_service(service_name, content) content = content.map { |service| { protocol: service[0], port: service[1] } } new_service = { name: service_name, content: content } response = rest_post('/BusinessFlow/rest/v1/network_services/new', body: new_service) response_handler(response) true end |
#decommission_application(app_revision_id) ⇒ Object
Decommission an application
65 66 67 68 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 65 def decommission_application(app_revision_id) response = rest_post("/BusinessFlow/rest/v1/applications/#{app_revision_id}/decommission") response_handler(response) end |
#define_application_flows(app_name, new_app_flows) ⇒ Object
Update application flows of an application to match a requested flows configuration.
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 342 def define_application_flows(app_name, new_app_flows) flows_from_server = get_application_flows_hash(get_app_revision_id_by_name(app_name)) flows_to_delete, flows_to_create, flows_to_modify = plan_application_flows(flows_from_server, new_app_flows) implement_app_flows_plan( app_name, new_app_flows, flows_from_server, flows_to_delete, flows_to_create, flows_to_modify ) # Stage 2: Run connectivity check for all the unchanged flows. Check with Chef is this non-deterministic approach # is OK with them for the cookbook. # # Return the current list of created flows if successful get_application_flows(get_app_revision_id_by_name(app_name)) end |
#delete_flow_by_id(app_revision_id, flow_id) ⇒ Object
Delete a specific flow
93 94 95 96 97 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 93 def delete_flow_by_id(app_revision_id, flow_id) response = rest_delete("/BusinessFlow/rest/v1/applications/#{app_revision_id}/flows/#{flow_id}") response_handler(response) true end |
#get_app_id_by_name(app_name) ⇒ Boolean
Get application id by it’s name
207 208 209 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 207 def get_app_id_by_name(app_name) get_application_by_name(app_name)['applicationId'] end |
#get_app_revision_id_by_name(app_name) ⇒ Boolean
Get latest application revision id by application name
199 200 201 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 199 def get_app_revision_id_by_name(app_name) get_application_by_name(app_name)['revisionID'] end |
#get_application_by_name(app_name) ⇒ Hash
Get application by name
190 191 192 193 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 190 def get_application_by_name(app_name) response = rest_get("/BusinessFlow/rest/v1/applications/name/#{app_name}") response_handler(response) end |
#get_application_flow_by_name(app_revision_id, flow_name) ⇒ Object
Fetch an application flow by it’s name
164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 164 def get_application_flow_by_name(app_revision_id, flow_name) flows = get_application_flows(app_revision_id) requested_flow = flows.find do |flow| break flow if flow['name'] == flow_name end if requested_flow.nil? raise( "Unable to find flow by name. Application revision id: #{app_revision_id}, flow_name: #{flow_name}." ) end requested_flow end |
#get_application_flows(app_revision_id) ⇒ Array<Hash>
Get list of application flows for an application revision id
74 75 76 77 78 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 74 def get_application_flows(app_revision_id) response = rest_get("/BusinessFlow/rest/v1/applications/#{app_revision_id}/flows") flows = response_handler(response) flows.map { |flow| flow['flowType'] == 'APPLICATION_FLOW' ? flow : nil }.compact end |
#get_application_flows_hash(app_revision_id) ⇒ Hash
Get application flows from the server as a hash from flow name it it’s content
84 85 86 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 84 def get_application_flows_hash(app_revision_id) Hash[get_application_flows(app_revision_id).map { |flow| [flow['name'], flow] }] end |
#get_applications ⇒ Array<Hash>
Get all applications
181 182 183 184 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 181 def get_applications response = rest_get('/BusinessFlow/rest/v1/applications/') response_handler(response) end |
#get_flow_connectivity(app_revision_id, flow_id) ⇒ String
Get connectivity status for a flow
104 105 106 107 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 104 def get_flow_connectivity(app_revision_id, flow_id) response = rest_post("/BusinessFlow/rest/v1/applications/#{app_revision_id}/flows/#{flow_id}/check_connectivity") response_handler(response) end |
#implement_app_flows_plan(app_name, new_app_flows, flows_from_server, flows_to_delete, flows_to_create, flows_to_modify) ⇒ Object
Create/modify/delete application2 flows to match a given flow plan returned by ‘plan_application_flows’ param [Array<String>] flows_to_modify List of network flow names to delete and re-create with the new definition
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 288 def implement_app_flows_plan( app_name, new_app_flows, flows_from_server, flows_to_delete, flows_to_create, flows_to_modify ) # Get the app revision id app_revision_id = get_app_revision_id_by_name(app_name) # This param is used to determine if it is necessary to update the app_revision_id is_draft_revision = false # Delete all the flows for deletion and modification (flows_to_delete | flows_to_modify).each do |flow_name_to_delete| delete_flow_by_id(app_revision_id, flows_from_server[flow_name_to_delete]['flowID']) next if is_draft_revision app_revision_id = get_app_revision_id_by_name(app_name) # Refetch the fresh flows from the server, as a new application revision has been created # and it's flow IDs have been change. Only that way we can make sure that the following flow deletions # by name will work as expected flows_from_server = get_application_flows_hash(app_revision_id) is_draft_revision = true end # Create all the new + modified flows (flows_to_create | flows_to_modify).each do |flow_name_to_create| new_flow_data = new_app_flows[flow_name_to_create] create_application_flow( app_revision_id, flow_name_to_create, # Document those key fields somewhere so users know how what is the format of app_flows object # that is provided to this function new_flow_data['sources'], new_flow_data['destinations'], new_flow_data['services'], new_flow_data.fetch('users', []), new_flow_data.fetch('applications', []), new_flow_data.fetch('comment', '') ) unless is_draft_revision app_revision_id = get_app_revision_id_by_name(app_name) is_draft_revision = true end end apply_application_draft(app_revision_id) if is_draft_revision end |
#login ⇒ Array<Hash>
Request login to get session cookie credentials
31 32 33 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 31 def login response_handler(rest_post('/BusinessFlow/rest/v1/login')) end |
#plan_application_flows(server_app_flows, new_app_flows) ⇒ Object
Return a plan for modifying application flows based on current and newly proposed application flows definition
264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 264 def plan_application_flows(server_app_flows, new_app_flows) current_flow_names = Set.new(server_app_flows.keys) new_flow_names = Set.new(new_app_flows.keys) # Calculate the flows_to_delete, flows_to_create and flows_to_modify and unchanging_flows flows_to_delete = current_flow_names - new_flow_names flows_to_create = new_flow_names - current_flow_names flows_to_modify = Set.new((new_flow_names & current_flow_names).map do |flow_name| flow_on_server = server_app_flows[flow_name] new_flow_definition = new_app_flows[flow_name] ALGOSEC_SDK::AreFlowsEqual.flows_equal?(new_flow_definition, flow_on_server) ? nil : flow_name end.compact) [flows_to_delete, flows_to_create, flows_to_modify] end |
#search_network_object(ip_or_subnet, search_type) ⇒ Object
Search a network object
251 252 253 254 255 256 257 |
# File 'lib/algosec-sdk/helpers/business_flow_helper.rb', line 251 def search_network_object(ip_or_subnet, search_type) response = rest_get( '/BusinessFlow/rest/v1/network_objects/find', query: { address: ip_or_subnet, type: search_type } ) response_handler(response) end |