From bcdc608f2183c5c6608239a056b4565059be13f4 Mon Sep 17 00:00:00 2001 From: momohossain Date: Mon, 25 Feb 2019 04:41:24 -0500 Subject: [PATCH 1/5] Add code for proxy --- irflow_client/irflow_client.py | 36 ++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/irflow_client/irflow_client.py b/irflow_client/irflow_client.py index da54106..a60a306 100644 --- a/irflow_client/irflow_client.py +++ b/irflow_client/irflow_client.py @@ -954,6 +954,20 @@ def _get_config_args_params(self, config_args): if isinstance(config_args['address'], str): self.address = config_args['address'] + elif 'proxy_user' in config_args and \ + 'proxy_pass' in config_args and \ + ('http_proxy' in config_args or 'https_proxy' in config_args): + auth_string = config_args['proxy_user'] + ':' + config_args['proxy_pass'] + '@' + proxy = None + if 'http_proxy' in config_args: + proxy = config_args['http_proxy'] + if 'http_proxy_port' in config_args: + proxy += ':' + config_args['http_proxy_port'] + elif 'https_proxy' in config_args: + proxy = config_args['https_proxy'] + if 'https_proxy_port' in config_args: + proxy += ':' + config_args['https_proxy_port'] + self.address = 'https://{0}'.format(auth_string) + proxy elif not config_args['address']: raise KeyError('You have the wrong or missing key or value') else: @@ -1009,7 +1023,10 @@ def _get_config_file_params(self, config_file): missing_options = [] # Check for missing required configuration keys - if not config.has_option('IRFlowAPI', 'address'): + if not config.has_option('IRFlowAPI', 'address') and \ + not config.has_option('IRFlowAPI', 'proxy_user') and \ + not config.has_option('IRFlowAPI', 'proxy_pass') and \ + not (config.has_option('IRFlowAPI', 'http_proxy') or config.has_option('IRFlowAPI', 'https_proxy')): self.logger.error( 'Configuration File "{}" does not contain the "address" option in the [IRFlowAPI] ' 'section'.format(config_file) @@ -1037,7 +1054,22 @@ def _get_config_file_params(self, config_file): raise IRFlowClientConfigError('Missing configuration sections: {0}'.format(", ".join(missing_options))) # Now set the configuration values on the self object. - self.address = config.get('IRFlowAPI', 'address') + if config.has_option('IRFlowAPI', 'proxy_user') and \ + config.has_option('IRFlowAPI', 'proxy_pass') and \ + (config.has_option('IRFlowAPI', 'http_proxy') or config.has_option('IRFlowAPI', 'https_proxy')): + auth_string = config.get('IRFlowAPI', 'proxy_user') + ':' + config.get('IRFlowAPI', 'proxy_pass') + '@' + proxy = None + if config.has_option('IRFlowAPI', 'http_proxy'): + proxy = config.get('IRFlowAPI', 'http_proxy') + if config.has_option('IRFlowAPI', 'http_proxy_port'): + proxy += ':' + config.get('IRFlowAPI', 'http_proxy_port') + elif config.has_option('IRFlowAPI', 'https_proxy'): + proxy = config.get('IRFlowAPI', 'https_proxy') + if config.has_option('IRFlowAPI', 'https_proxy_port'): + proxy += ':' + config.get('IRFlowAPI', 'https_proxy_port') + self.address = 'https://{0}'.format(auth_string) + proxy + else: + self.address = config.get('IRFlowAPI', 'address') self.api_user = config.get('IRFlowAPI', 'api_user') self.api_key = config.get('IRFlowAPI', 'api_key') if config.has_option('IRFlowAPI', 'protocol'): From 085ef3ac3784791abb561df6ee44e893a61d96c5 Mon Sep 17 00:00:00 2001 From: momohossain Date: Tue, 26 Feb 2019 20:47:28 -0500 Subject: [PATCH 2/5] Revert "Add code for proxy" This reverts commit bcdc608f2183c5c6608239a056b4565059be13f4. --- irflow_client/irflow_client.py | 36 ++-------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/irflow_client/irflow_client.py b/irflow_client/irflow_client.py index a60a306..da54106 100644 --- a/irflow_client/irflow_client.py +++ b/irflow_client/irflow_client.py @@ -954,20 +954,6 @@ def _get_config_args_params(self, config_args): if isinstance(config_args['address'], str): self.address = config_args['address'] - elif 'proxy_user' in config_args and \ - 'proxy_pass' in config_args and \ - ('http_proxy' in config_args or 'https_proxy' in config_args): - auth_string = config_args['proxy_user'] + ':' + config_args['proxy_pass'] + '@' - proxy = None - if 'http_proxy' in config_args: - proxy = config_args['http_proxy'] - if 'http_proxy_port' in config_args: - proxy += ':' + config_args['http_proxy_port'] - elif 'https_proxy' in config_args: - proxy = config_args['https_proxy'] - if 'https_proxy_port' in config_args: - proxy += ':' + config_args['https_proxy_port'] - self.address = 'https://{0}'.format(auth_string) + proxy elif not config_args['address']: raise KeyError('You have the wrong or missing key or value') else: @@ -1023,10 +1009,7 @@ def _get_config_file_params(self, config_file): missing_options = [] # Check for missing required configuration keys - if not config.has_option('IRFlowAPI', 'address') and \ - not config.has_option('IRFlowAPI', 'proxy_user') and \ - not config.has_option('IRFlowAPI', 'proxy_pass') and \ - not (config.has_option('IRFlowAPI', 'http_proxy') or config.has_option('IRFlowAPI', 'https_proxy')): + if not config.has_option('IRFlowAPI', 'address'): self.logger.error( 'Configuration File "{}" does not contain the "address" option in the [IRFlowAPI] ' 'section'.format(config_file) @@ -1054,22 +1037,7 @@ def _get_config_file_params(self, config_file): raise IRFlowClientConfigError('Missing configuration sections: {0}'.format(", ".join(missing_options))) # Now set the configuration values on the self object. - if config.has_option('IRFlowAPI', 'proxy_user') and \ - config.has_option('IRFlowAPI', 'proxy_pass') and \ - (config.has_option('IRFlowAPI', 'http_proxy') or config.has_option('IRFlowAPI', 'https_proxy')): - auth_string = config.get('IRFlowAPI', 'proxy_user') + ':' + config.get('IRFlowAPI', 'proxy_pass') + '@' - proxy = None - if config.has_option('IRFlowAPI', 'http_proxy'): - proxy = config.get('IRFlowAPI', 'http_proxy') - if config.has_option('IRFlowAPI', 'http_proxy_port'): - proxy += ':' + config.get('IRFlowAPI', 'http_proxy_port') - elif config.has_option('IRFlowAPI', 'https_proxy'): - proxy = config.get('IRFlowAPI', 'https_proxy') - if config.has_option('IRFlowAPI', 'https_proxy_port'): - proxy += ':' + config.get('IRFlowAPI', 'https_proxy_port') - self.address = 'https://{0}'.format(auth_string) + proxy - else: - self.address = config.get('IRFlowAPI', 'address') + self.address = config.get('IRFlowAPI', 'address') self.api_user = config.get('IRFlowAPI', 'api_user') self.api_key = config.get('IRFlowAPI', 'api_key') if config.has_option('IRFlowAPI', 'protocol'): From 2ec42dd4131ba63ed829f73ad3baf782a075ff19 Mon Sep 17 00:00:00 2001 From: momohossain Date: Mon, 11 Mar 2019 05:06:48 -0400 Subject: [PATCH 3/5] Add functionality for the IRFlowClient session object to be able to use a proxy --- irflow_client/irflow_client.py | 131 ++++++++++++++++++++++++++------- 1 file changed, 105 insertions(+), 26 deletions(-) diff --git a/irflow_client/irflow_client.py b/irflow_client/irflow_client.py index da54106..172b246 100644 --- a/irflow_client/irflow_client.py +++ b/irflow_client/irflow_client.py @@ -166,7 +166,7 @@ def get_version(self, ): url = "%s://%s/%s" % (self.protocol, self.address, self.end_points['version']) headers = {'Content-type': 'application/json'} - response = self.session.get(url, verify=False, headers=headers) + response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) if response.status_code == 503: raise IRFlowMaintenanceError('IR-Flow Server is down for maintenance') @@ -190,7 +190,7 @@ def close_alert(self, alert_num, close_reason): if self.debug: self.dump_request_debug_info('Close Alert', url, headers, data=data) - response = self.session.put(url, json=data, headers=headers, verify=False) + response = self.session.put(url, json=data, headers=headers, verify=False, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Close Alert', response.status_code, response.json()) @@ -216,7 +216,7 @@ def attach_incident_to_alert(self, incident_num, alert_num): if self.debug: self.dump_request_debug_info('Attach Incident to Alert', url, headers=headers) - response = self.session.put(url, headers=headers, verify=False) + response = self.session.put(url, headers=headers, verify=False, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Attach Incident to Alert', response.status_code, response.json()) @@ -242,7 +242,7 @@ def upload_attachment_to_alert(self, alert_num, filename): if self.debug: self.dump_request_debug_info('Upload Attachment to Alert', url, headers=headers) - response = self.session.post(url, data={}, files=data, headers=headers, verify=False) + response = self.session.post(url, data={}, files=data, headers=headers, verify=False, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Upload Attachment to Alert', response.status_code, response.json()) @@ -267,7 +267,7 @@ def upload_attachment_to_incident(self, incident_id, filename): if self.debug: self.dump_request_debug_info('Upload Attachment to Incident', url, headers=headers) - response = self.session.post(url, data={}, files=data, headers=headers, verify=False) + response = self.session.post(url, data={}, files=data, headers=headers, verify=False, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Upload Attachment to Incident', response.status_code, response.json()) @@ -292,7 +292,7 @@ def upload_attachment_to_task(self, task_id, filename): if self.debug: self.dump_request_debug_info('Upload Attachment to Alert', url, headers=headers) - response = self.session.post(url, data={}, files=data, headers=headers, verify=False) + response = self.session.post(url, data={}, files=data, headers=headers, verify=False, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Upload Attachment to Alert Response', response.status_code, response.json()) @@ -315,7 +315,7 @@ def download_attachment(self, attachment_id, attachment_output_file): self.dump_request_debug_info('Download Attachment', url) with open(attachment_output_file, 'wb') as handle: - response = self.session.get(url, stream=True, verify=False) + response = self.session.get(url, stream=True, verify=False, proxies=self.proxies) for block in response.iter_content(1024): handle.write(block) @@ -342,7 +342,7 @@ def download_attachment_string(self, attachment_id): # Get a temporary file to download the results into temp = tempfile.TemporaryFile() - response = self.session.get(url, stream=True, verify=False) + response = self.session.get(url, stream=True, verify=False, proxies=self.proxies) # Iterate, downloading data 1,024 bytes at a time for block in response.iter_content(1024): temp.write(block) @@ -373,7 +373,7 @@ def put_fact_group(self, fact_group_id, fact_data): if self.debug: self.dump_request_debug_info('Put Fact Group', url, headers=headers) - response = self.session.put(url, json=fact_payload, verify=False, headers=headers) + response = self.session.put(url, json=fact_payload, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Put Fact Group', response.status_code, response.json()) @@ -397,7 +397,7 @@ def get_fact_group(self, fact_group_id): if self.debug: self.dump_request_debug_info('Get Fact Group', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers) + response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Get Fact Group', response.status_code, response.json()) @@ -421,7 +421,7 @@ def get_alert(self, alert_num): if self.debug: self.dump_request_debug_info('Get Alert', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers) + response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Get Alert', response.status_code, response.json()) @@ -461,7 +461,7 @@ def create_alert(self, alert_fields, description=None, incoming_field_group_name if self.debug: self.dump_request_debug_info('Create Alert', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers) + response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Create Alert', response.status_code, response.json()) @@ -495,7 +495,7 @@ def create_incident(self, incident_fields, incident_type_name, incident_subtype_ if self.debug: self.dump_request_debug_info('Create Incident', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers) + response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Create Incident', response.status_code, response.json()) @@ -520,7 +520,7 @@ def get_incident(self, incident_num): if self.debug: self.dump_request_debug_info('Get Incident', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers) + response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Get Incident', response.status_code, response.json()) @@ -564,7 +564,7 @@ def update_incident(self, incident_num, incident_fields, incident_type_name, own if self.debug: self.dump_request_debug_info('Update Incident', url, headers=headers, params=params) - response = self.session.put(url, json=params, verify=False, headers=headers) + response = self.session.put(url, json=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Update Incident', response.status_code, response.json()) @@ -588,7 +588,7 @@ def attach_alert_to_incident(self, alert_num, incident_num): if self.debug: self.dump_request_debug_info('Attach Alert to Incident', url, headers=headers) - response = self.session.put(url, headers=headers, verify=False) + response = self.session.put(url, headers=headers, verify=False, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Attach Alert to Incident', response.status_code, response.json()) @@ -617,7 +617,7 @@ def list_picklists(self, with_trashed=False, only_trashed=False): if self.debug: self.dump_request_debug_info('Get List of Picklists', url, headers=headers, params=params) - response = self.session.get(url, params=params, verify=False, headers=headers) + response = self.session.get(url, params=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Get List of Picklists', response.status_code, response.json()) @@ -642,7 +642,7 @@ def get_picklist(self, picklist_id): if self.debug: self.dump_request_debug_info('Get Picklist', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers) + response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Get Picklist', response.status_code, response.json()) @@ -678,7 +678,7 @@ def add_item_to_picklist(self, picklist_id, value, label, description=None): if self.debug: self.dump_request_debug_info('Add Item to Picklist', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers) + response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Add Item to Picklist', response.status_code, response.json()) @@ -709,7 +709,7 @@ def list_picklist_items(self, picklist_id, with_trashed=False, only_trashed=Fals if self.debug: self.dump_request_debug_info('Get List of Picklist Items', url, headers=headers, params=params) - response = self.session.get(url, params=params, verify=False, headers=headers) + response = self.session.get(url, params=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Get List of Picklist Items', response.status_code, response.json()) @@ -745,7 +745,7 @@ def create_picklist_item(self, picklist_id, value, label, description=None): if self.debug: self.dump_request_debug_info('Add Picklist Item', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers) + response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Add PIcklist Item', response.status_code, response.json()) @@ -770,7 +770,7 @@ def get_picklist_item(self, picklist_item_id): if self.debug: self.dump_request_debug_info('Get Picklist Item', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers) + response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Get Picklist Item', response.status_code, response.json()) @@ -795,7 +795,7 @@ def restore_picklist_item(self, picklist_item_id): if self.debug: self.dump_request_debug_info('Restore Picklist Item', url, headers=headers) - response = self.session.put(url, verify=False, headers=headers) + response = self.session.put(url, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Restore Picklist Item', response.status_code, response.json()) @@ -820,7 +820,7 @@ def delete_picklist_item(self, picklist_item_id): if self.debug: self.dump_request_debug_info('Delete Picklist Item', url, headers=headers) - response = self.session.delete(url, verify=False, headers=headers) + response = self.session.delete(url, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Delete Picklist Item', response.status_code, response.json()) @@ -863,7 +863,7 @@ def create_object_type(self, type_name, type_label, parent_type_name=None, paren if self.debug: self.dump_request_debug_info('Store Object Type', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers) + response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Store Object Type', response.status_code, response.json()) @@ -901,7 +901,7 @@ def attach_field_to_object_type(self, object_type_name, field_name, object_type_ if self.debug: self.dump_request_debug_info('Attach Field to Object Type', url, headers=headers, params=params) - response = self.session.put(url, json=params, verify=False, headers=headers) + response = self.session.put(url, json=params, verify=False, headers=headers, proxies=self.proxies) if self.debug: self.dump_response_debug_info('Attach Field to Object Type', response.status_code, response.json()) @@ -991,6 +991,36 @@ def _get_config_args_params(self, config_args): if self.debug: self.dump_settings() + # Check if the user is trying to use a proxy by seeing if the config args contains any of the proxy_options. + proxy_options = ['proxy_user', 'proxy_pass', 'http_proxy', 'https_proxy', 'http_proxy_port', 'https_proxy_port'] + proxy_usage_found = False + for option in proxy_options: + if config_args[option]: + proxy_usage_found = True + break + + # If any of the proxy options are used, do some basic error checking. Log issues as warnings. + if proxy_usage_found: + if config_args['proxy_user'] and not config_args['proxy_pass']: + raise KeyError('A "proxy_pass" must be submitted if using a "proxy_user"') + if config_args['proxy_pass'] and not config_args['proxy_user']: + raise KeyError('A "proxy_user" must be submitted if using a "proxy_pass"') + if not config_args['http_proxy'] or not config_args['https_proxy']: + raise KeyError('A proxy option was submitted for configuration but neither an "http_proxy" nor an ' + '"https_proxy" was submitted') + + # Our logic for setting up proxies + self.proxies = {} + if proxy_usage_found: + proxy_user = config_args['proxy_user'] + ':' if config_args['proxy_user'] else '' + proxy_pass = config_args['proxy_pass'] + '@' if config_args['proxy_pass'] else '' + if config_args['http_proxy']: + port = ':' + config_args['http_proxy_port'] if config_args['http_proxy_port'] else '' + self.proxies['http'] = 'http://' + proxy_user + proxy_pass + config_args['http_proxy'] + port + if config_args['https_proxy']: + port = ':' + config_args['https_proxy_port'] if config_args['https_proxy_port'] else '' + self.proxies['https'] = 'https://' + proxy_user + proxy_pass + config_args['https_proxy'] + port + def _get_config_file_params(self, config_file): """Helper function to parse configuration arguments from a valid IR-Flow configuration file @@ -1028,8 +1058,39 @@ def _get_config_file_params(self, config_file): ) missing_options.append('api_key') + # Check if the user is trying to use a proxy by seeing if the config file contains any of the proxy_options. + proxy_options = ['proxy_user', 'proxy_pass', 'http_proxy', 'https_proxy', 'http_proxy_port', 'https_proxy_port'] + proxy_usage_found = False + for option in proxy_options: + if config.has_option('IRFlowAPI', option): + proxy_usage_found = True + break + + # If any of the proxy options are used, do some basic error checking. Log issues as warnings. + if proxy_usage_found: + if not config.has_option('IRFlowAPI', 'proxy_user') and config.has_option('IRFlowAPI', 'proxy_pass'): + self.logger.warning( + 'Configuration File "{}" does not contain the "proxy_user" option in the [IRFlowAPI] ' + 'section, but a proxy_pass option was found in the file'.format(config_file) + ) + missing_options.append('proxy_user') + if not config.has_option('IRFlowAPI', 'proxy_pass') and config.has_option('IRFlowAPI', 'proxy_user'): + self.logger.warning( + 'Configuration File "{}" does not contain the "proxy_pass" option in the [IRFlowAPI] ' + 'section, but a proxy_user option was found in the file'.format(config_file) + ) + missing_options.append('proxy_pass') + if not config.has_option('IRFlowAPI', 'http_proxy') or not config.has_option('IRFlowAPI', 'https_proxy'): + self.logger.warning( + 'Configuration File "{}" does not contain the "http_proxy" option or the "https_proxy" option in ' + 'the [IRFlowAPI] section, but a proxy option was found in the file'.format(config_file) + ) + missing_options.append('http_proxy') + missing_options.append('https_proxy') + # Do not need to check for protocol, it is optional. Will assume https if missing. # Do not need to check for debug, it is optional. Will assume False if missing. + # Do not need to check for proxy_user, proxy_pass, http_proxy_port, nor https_proxy_port. They are optional. # If the required keys do not exist, then simply exit if len(missing_options) > 0: @@ -1056,3 +1117,21 @@ def _get_config_file_params(self, config_file): # Dump Configuration if --debug if self.debug: self.dump_settings() + + # Our logic for setting up proxies + self.proxies = {} + if proxy_usage_found: + proxy_user = config.get('IRFlowAPI', 'proxy_user') + ':' \ + if config.has_option('IRFlowAPI', 'proxy_user') else '' + proxy_pass = config.get('IRFlowAPI', 'proxy_pass') + '@' \ + if config.has_option('IRFlowAPI', 'proxy_pass') else '' + if config.has_option('IRFlowAPI', 'http_proxy'): + port = ':' + config.get('IRFlowAPI', 'http_proxy_port') \ + if config.has_option('IRFlowAPI', 'http_proxy_port') else '' + self.proxies['http'] = 'http://' + proxy_user + proxy_pass + \ + config.get('IRFlowAPI', 'http_proxy') + port + if config.has_option('IRFlowAPI', 'https_proxy'): + port = ':' + config.get('IRFlowAPI', 'https_proxy_port') \ + if config.has_option('IRFlowAPI', 'https_proxy_port') else '' + self.proxies['https'] = 'https://' + proxy_user + proxy_pass + \ + config.get('IRFlowAPI', 'https_proxy') + port From d6f52cbfeb419184728cf9bdbe0ddea8149f5827 Mon Sep 17 00:00:00 2001 From: momohossain Date: Tue, 12 Mar 2019 19:00:05 -0400 Subject: [PATCH 4/5] Add some documentation, add better error handling for config args --- irflow_client/irflow_client.py | 75 +++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/irflow_client/irflow_client.py b/irflow_client/irflow_client.py index 172b246..99c7d33 100644 --- a/irflow_client/irflow_client.py +++ b/irflow_client/irflow_client.py @@ -948,37 +948,43 @@ def _get_config_args_params(self, config_args): protocol (str): https unless otherwise specified, default = HTTPS debug (bool): enable debug output, default = None verbose (int): turn up the verbosity default = 0 (optional) + proxy_user (str): the username for a proxy, default = None + proxy_pass (str): the password for a proxy, default = None + http_proxy (str): the address of the http proxy, default = None + https_proxy (str): the address of the https proxy, default = None + http_proxy_port (str): the port for the http proxy, default = None + https_proxy_port (str): the port for the https proxy, default = None """ # Checking for missing config values - if isinstance(config_args['address'], str): + if 'address' in config_args and isinstance(config_args['address'], str): self.address = config_args['address'] - elif not config_args['address']: - raise KeyError('You have the wrong or missing key or value') + elif 'address' not in config_args: + raise KeyError('An "address" must be submitted to establish a connection to the IR-Flow client') else: - raise KeyError('You have the wrong or missing key or value') + raise KeyError('The "address" submitted had an invalid value') - if isinstance(config_args['api_user'], str): + if 'api_user' in config_args and isinstance(config_args['api_user'], str): self.api_user = config_args['api_user'] - elif not config_args['api_user']: - raise KeyError('You have the wrong or missing key or value') + elif 'api_user' not in config_args: + raise KeyError('An "api_user" must be submitted to establish a connection to the IR-Flow client') else: - raise KeyError('You have the wrong or missing key or value') + raise KeyError('The "api_user" submitted had an invalid value') - if isinstance(config_args['api_key'], str): + if 'api_key' in config_args and isinstance(config_args['api_key'], str): self.api_key = config_args['api_key'] - elif not config_args['api_key']: - raise KeyError('You have the wrong or missing key or value') + elif 'api_key' not in config_args: + raise KeyError('An "api_key" must be submitted to establish a connection to the IR-Flow client') else: - raise KeyError('You have the wrong or missing key or value') + raise KeyError('The "api_key" submitted had an invalid value') - if config_args['protocol']: + if 'protocol' in config_args and isinstance(config_args['protocol'], str): self.protocol = config_args['protocol'] else: self.protocol = 'https' - if config_args['debug']: - self.debug = config_args['debug'] + if 'debug' in config_args and config_args['debug']: + self.debug = True else: self.debug = False try: @@ -991,34 +997,37 @@ def _get_config_args_params(self, config_args): if self.debug: self.dump_settings() - # Check if the user is trying to use a proxy by seeing if the config args contains any of the proxy_options. - proxy_options = ['proxy_user', 'proxy_pass', 'http_proxy', 'https_proxy', 'http_proxy_port', 'https_proxy_port'] + # Check if the user is trying to use a proxy by seeing if the config args contains any of the proxy_args. + # Also, make sure that the submitted proxy option is a string since all of the proxy_args should be a string. + proxy_args = ['proxy_user', 'proxy_pass', 'http_proxy', 'https_proxy', 'http_proxy_port', 'https_proxy_port'] proxy_usage_found = False - for option in proxy_options: - if config_args[option]: - proxy_usage_found = True - break - - # If any of the proxy options are used, do some basic error checking. Log issues as warnings. + for option in proxy_args: + if option in config_args: + if isinstance(config_args[option], str): + proxy_usage_found = True + else: + raise KeyError('The configuration argument "{}" was set to an incorrect type'.format(option)) + + # If any of the proxy options are used, do some basic error checking. if proxy_usage_found: - if config_args['proxy_user'] and not config_args['proxy_pass']: + if 'proxy_user' in config_args and 'proxy_pass' not in config_args: raise KeyError('A "proxy_pass" must be submitted if using a "proxy_user"') - if config_args['proxy_pass'] and not config_args['proxy_user']: + if 'proxy_pass' in config_args and 'proxy_user' not in config_args: raise KeyError('A "proxy_user" must be submitted if using a "proxy_pass"') - if not config_args['http_proxy'] or not config_args['https_proxy']: + if 'http_proxy' not in config_args and 'https_proxy' not in config_args: raise KeyError('A proxy option was submitted for configuration but neither an "http_proxy" nor an ' '"https_proxy" was submitted') - # Our logic for setting up proxies + # Our logic for setting up proxies using a dict of configuration arguments. self.proxies = {} if proxy_usage_found: - proxy_user = config_args['proxy_user'] + ':' if config_args['proxy_user'] else '' - proxy_pass = config_args['proxy_pass'] + '@' if config_args['proxy_pass'] else '' - if config_args['http_proxy']: - port = ':' + config_args['http_proxy_port'] if config_args['http_proxy_port'] else '' + proxy_user = config_args['proxy_user'] + ':' if 'proxy_user' in config_args else '' + proxy_pass = config_args['proxy_pass'] + '@' if 'proxy_pass' in config_args else '' + if 'http_proxy' in config_args: + port = ':' + config_args['http_proxy_port'] if 'http_proxy_port' in config_args else '' self.proxies['http'] = 'http://' + proxy_user + proxy_pass + config_args['http_proxy'] + port - if config_args['https_proxy']: - port = ':' + config_args['https_proxy_port'] if config_args['https_proxy_port'] else '' + if 'https_proxy' in config_args: + port = ':' + config_args['https_proxy_port'] if 'https_proxy_port' in config_args else '' self.proxies['https'] = 'https://' + proxy_user + proxy_pass + config_args['https_proxy'] + port def _get_config_file_params(self, config_file): From c2bce44f1c8d01663baf2d87ac5fe549230469cf Mon Sep 17 00:00:00 2001 From: momohossain Date: Mon, 18 Mar 2019 19:17:53 -0400 Subject: [PATCH 5/5] Move proxy code over into separate private helper functions for easier readability, add to self.session.proxies instead of relying on a self.proxies, minor text fixes --- irflow_client/irflow_client.py | 235 +++++++++++++++++++-------------- 1 file changed, 138 insertions(+), 97 deletions(-) diff --git a/irflow_client/irflow_client.py b/irflow_client/irflow_client.py index 99c7d33..9b5eea9 100644 --- a/irflow_client/irflow_client.py +++ b/irflow_client/irflow_client.py @@ -95,6 +95,7 @@ def __init__(self, config_args=None, config_file=None): # Set timeout on (connect, read) timeouts self.session.timeout=(5, 30) + # Set the User-Agent self.session.headers.update({'User-Agent': IRFlowClient._build_user_agent()}) @@ -102,6 +103,13 @@ def __init__(self, config_args=None, config_file=None): # The rest of the headers are specified by the individual calls. self.session.headers.update({'X-Authorization': "{} {}".format(self.api_user, self.api_key)}) + # If a proxy option was found from parsing the config file/args, we add the proxy to the session + if self.proxy_usage: + if config_file: + self._get_proxy_from_config_file(config_file) + elif config_args: + self._get_proxy_from_config_args(config_args) + if not self.circle_ci: self.version = self.get_version() @@ -166,7 +174,7 @@ def get_version(self, ): url = "%s://%s/%s" % (self.protocol, self.address, self.end_points['version']) headers = {'Content-type': 'application/json'} - response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) + response = self.session.get(url, verify=False, headers=headers) if response.status_code == 503: raise IRFlowMaintenanceError('IR-Flow Server is down for maintenance') @@ -190,7 +198,7 @@ def close_alert(self, alert_num, close_reason): if self.debug: self.dump_request_debug_info('Close Alert', url, headers, data=data) - response = self.session.put(url, json=data, headers=headers, verify=False, proxies=self.proxies) + response = self.session.put(url, json=data, headers=headers, verify=False) if self.debug: self.dump_response_debug_info('Close Alert', response.status_code, response.json()) @@ -216,7 +224,7 @@ def attach_incident_to_alert(self, incident_num, alert_num): if self.debug: self.dump_request_debug_info('Attach Incident to Alert', url, headers=headers) - response = self.session.put(url, headers=headers, verify=False, proxies=self.proxies) + response = self.session.put(url, headers=headers, verify=False) if self.debug: self.dump_response_debug_info('Attach Incident to Alert', response.status_code, response.json()) @@ -242,7 +250,7 @@ def upload_attachment_to_alert(self, alert_num, filename): if self.debug: self.dump_request_debug_info('Upload Attachment to Alert', url, headers=headers) - response = self.session.post(url, data={}, files=data, headers=headers, verify=False, proxies=self.proxies) + response = self.session.post(url, data={}, files=data, headers=headers, verify=False) if self.debug: self.dump_response_debug_info('Upload Attachment to Alert', response.status_code, response.json()) @@ -267,7 +275,7 @@ def upload_attachment_to_incident(self, incident_id, filename): if self.debug: self.dump_request_debug_info('Upload Attachment to Incident', url, headers=headers) - response = self.session.post(url, data={}, files=data, headers=headers, verify=False, proxies=self.proxies) + response = self.session.post(url, data={}, files=data, headers=headers, verify=False) if self.debug: self.dump_response_debug_info('Upload Attachment to Incident', response.status_code, response.json()) @@ -292,7 +300,7 @@ def upload_attachment_to_task(self, task_id, filename): if self.debug: self.dump_request_debug_info('Upload Attachment to Alert', url, headers=headers) - response = self.session.post(url, data={}, files=data, headers=headers, verify=False, proxies=self.proxies) + response = self.session.post(url, data={}, files=data, headers=headers, verify=False) if self.debug: self.dump_response_debug_info('Upload Attachment to Alert Response', response.status_code, response.json()) @@ -315,7 +323,7 @@ def download_attachment(self, attachment_id, attachment_output_file): self.dump_request_debug_info('Download Attachment', url) with open(attachment_output_file, 'wb') as handle: - response = self.session.get(url, stream=True, verify=False, proxies=self.proxies) + response = self.session.get(url, stream=True, verify=False) for block in response.iter_content(1024): handle.write(block) @@ -342,7 +350,7 @@ def download_attachment_string(self, attachment_id): # Get a temporary file to download the results into temp = tempfile.TemporaryFile() - response = self.session.get(url, stream=True, verify=False, proxies=self.proxies) + response = self.session.get(url, stream=True, verify=False) # Iterate, downloading data 1,024 bytes at a time for block in response.iter_content(1024): temp.write(block) @@ -373,7 +381,7 @@ def put_fact_group(self, fact_group_id, fact_data): if self.debug: self.dump_request_debug_info('Put Fact Group', url, headers=headers) - response = self.session.put(url, json=fact_payload, verify=False, headers=headers, proxies=self.proxies) + response = self.session.put(url, json=fact_payload, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Put Fact Group', response.status_code, response.json()) @@ -397,7 +405,7 @@ def get_fact_group(self, fact_group_id): if self.debug: self.dump_request_debug_info('Get Fact Group', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) + response = self.session.get(url, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Get Fact Group', response.status_code, response.json()) @@ -421,7 +429,7 @@ def get_alert(self, alert_num): if self.debug: self.dump_request_debug_info('Get Alert', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) + response = self.session.get(url, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Get Alert', response.status_code, response.json()) @@ -461,7 +469,7 @@ def create_alert(self, alert_fields, description=None, incoming_field_group_name if self.debug: self.dump_request_debug_info('Create Alert', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.post(url, json=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Create Alert', response.status_code, response.json()) @@ -495,7 +503,7 @@ def create_incident(self, incident_fields, incident_type_name, incident_subtype_ if self.debug: self.dump_request_debug_info('Create Incident', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.post(url, json=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Create Incident', response.status_code, response.json()) @@ -520,7 +528,7 @@ def get_incident(self, incident_num): if self.debug: self.dump_request_debug_info('Get Incident', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) + response = self.session.get(url, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Get Incident', response.status_code, response.json()) @@ -564,7 +572,7 @@ def update_incident(self, incident_num, incident_fields, incident_type_name, own if self.debug: self.dump_request_debug_info('Update Incident', url, headers=headers, params=params) - response = self.session.put(url, json=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.put(url, json=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Update Incident', response.status_code, response.json()) @@ -588,7 +596,7 @@ def attach_alert_to_incident(self, alert_num, incident_num): if self.debug: self.dump_request_debug_info('Attach Alert to Incident', url, headers=headers) - response = self.session.put(url, headers=headers, verify=False, proxies=self.proxies) + response = self.session.put(url, headers=headers, verify=False) if self.debug: self.dump_response_debug_info('Attach Alert to Incident', response.status_code, response.json()) @@ -617,7 +625,7 @@ def list_picklists(self, with_trashed=False, only_trashed=False): if self.debug: self.dump_request_debug_info('Get List of Picklists', url, headers=headers, params=params) - response = self.session.get(url, params=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.get(url, params=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Get List of Picklists', response.status_code, response.json()) @@ -642,7 +650,7 @@ def get_picklist(self, picklist_id): if self.debug: self.dump_request_debug_info('Get Picklist', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) + response = self.session.get(url, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Get Picklist', response.status_code, response.json()) @@ -678,7 +686,7 @@ def add_item_to_picklist(self, picklist_id, value, label, description=None): if self.debug: self.dump_request_debug_info('Add Item to Picklist', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.post(url, json=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Add Item to Picklist', response.status_code, response.json()) @@ -709,7 +717,7 @@ def list_picklist_items(self, picklist_id, with_trashed=False, only_trashed=Fals if self.debug: self.dump_request_debug_info('Get List of Picklist Items', url, headers=headers, params=params) - response = self.session.get(url, params=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.get(url, params=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Get List of Picklist Items', response.status_code, response.json()) @@ -745,7 +753,7 @@ def create_picklist_item(self, picklist_id, value, label, description=None): if self.debug: self.dump_request_debug_info('Add Picklist Item', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.post(url, json=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Add PIcklist Item', response.status_code, response.json()) @@ -770,7 +778,7 @@ def get_picklist_item(self, picklist_item_id): if self.debug: self.dump_request_debug_info('Get Picklist Item', url, headers=headers) - response = self.session.get(url, verify=False, headers=headers, proxies=self.proxies) + response = self.session.get(url, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Get Picklist Item', response.status_code, response.json()) @@ -795,7 +803,7 @@ def restore_picklist_item(self, picklist_item_id): if self.debug: self.dump_request_debug_info('Restore Picklist Item', url, headers=headers) - response = self.session.put(url, verify=False, headers=headers, proxies=self.proxies) + response = self.session.put(url, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Restore Picklist Item', response.status_code, response.json()) @@ -820,7 +828,7 @@ def delete_picklist_item(self, picklist_item_id): if self.debug: self.dump_request_debug_info('Delete Picklist Item', url, headers=headers) - response = self.session.delete(url, verify=False, headers=headers, proxies=self.proxies) + response = self.session.delete(url, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Delete Picklist Item', response.status_code, response.json()) @@ -863,7 +871,7 @@ def create_object_type(self, type_name, type_label, parent_type_name=None, paren if self.debug: self.dump_request_debug_info('Store Object Type', url, headers=headers, params=params) - response = self.session.post(url, json=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.post(url, json=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Store Object Type', response.status_code, response.json()) @@ -901,7 +909,7 @@ def attach_field_to_object_type(self, object_type_name, field_name, object_type_ if self.debug: self.dump_request_debug_info('Attach Field to Object Type', url, headers=headers, params=params) - response = self.session.put(url, json=params, verify=False, headers=headers, proxies=self.proxies) + response = self.session.put(url, json=params, verify=False, headers=headers) if self.debug: self.dump_response_debug_info('Attach Field to Object Type', response.status_code, response.json()) @@ -948,12 +956,12 @@ def _get_config_args_params(self, config_args): protocol (str): https unless otherwise specified, default = HTTPS debug (bool): enable debug output, default = None verbose (int): turn up the verbosity default = 0 (optional) - proxy_user (str): the username for a proxy, default = None - proxy_pass (str): the password for a proxy, default = None - http_proxy (str): the address of the http proxy, default = None - https_proxy (str): the address of the https proxy, default = None - http_proxy_port (str): the port for the http proxy, default = None - https_proxy_port (str): the port for the https proxy, default = None + proxy_user (str): the username for a proxy, default = None (optional) + proxy_pass (str): the password for a proxy, default = None (optional) + http_proxy (str): the address of the http proxy, default = None (optional) + https_proxy (str): the address of the https proxy, default = None (optional) + http_proxy_port (str): the port for the http proxy, default = None (optional) + https_proxy_port (str): the port for the https proxy, default = None (optional) """ # Checking for missing config values @@ -1000,38 +1008,55 @@ def _get_config_args_params(self, config_args): # Check if the user is trying to use a proxy by seeing if the config args contains any of the proxy_args. # Also, make sure that the submitted proxy option is a string since all of the proxy_args should be a string. proxy_args = ['proxy_user', 'proxy_pass', 'http_proxy', 'https_proxy', 'http_proxy_port', 'https_proxy_port'] - proxy_usage_found = False + self.proxy_usage = False for option in proxy_args: if option in config_args: if isinstance(config_args[option], str): - proxy_usage_found = True + self.proxy_usage = True else: raise KeyError('The configuration argument "{}" was set to an incorrect type'.format(option)) + def _get_proxy_from_config_args(self, config_args): + """Helper function to check/parse the proxy configuration arguments provided in a dict + + Args: + config_args (dict): A dict of the following keys: + + Keys: + address (str): IR-Flow Server FQDN or IP Address + api_user (str): IR-Flow API User + api_key (str): above user's api key + protocol (str): https unless otherwise specified, default = HTTPS + debug (bool): enable debug output, default = None + verbose (int): turn up the verbosity default = 0 (optional) + proxy_user (str): the username for a proxy, default = None + proxy_pass (str): the password for a proxy, default = None + http_proxy (str): the address of the http proxy, default = None + https_proxy (str): the address of the https proxy, default = None + http_proxy_port (str): the port for the http proxy, default = None + https_proxy_port (str): the port for the https proxy, default = None + """ # If any of the proxy options are used, do some basic error checking. - if proxy_usage_found: - if 'proxy_user' in config_args and 'proxy_pass' not in config_args: - raise KeyError('A "proxy_pass" must be submitted if using a "proxy_user"') - if 'proxy_pass' in config_args and 'proxy_user' not in config_args: - raise KeyError('A "proxy_user" must be submitted if using a "proxy_pass"') - if 'http_proxy' not in config_args and 'https_proxy' not in config_args: - raise KeyError('A proxy option was submitted for configuration but neither an "http_proxy" nor an ' - '"https_proxy" was submitted') - - # Our logic for setting up proxies using a dict of configuration arguments. - self.proxies = {} - if proxy_usage_found: - proxy_user = config_args['proxy_user'] + ':' if 'proxy_user' in config_args else '' - proxy_pass = config_args['proxy_pass'] + '@' if 'proxy_pass' in config_args else '' - if 'http_proxy' in config_args: - port = ':' + config_args['http_proxy_port'] if 'http_proxy_port' in config_args else '' - self.proxies['http'] = 'http://' + proxy_user + proxy_pass + config_args['http_proxy'] + port - if 'https_proxy' in config_args: - port = ':' + config_args['https_proxy_port'] if 'https_proxy_port' in config_args else '' - self.proxies['https'] = 'https://' + proxy_user + proxy_pass + config_args['https_proxy'] + port + if 'proxy_user' in config_args and 'proxy_pass' not in config_args: + raise KeyError('A "proxy_pass" must be submitted if using a "proxy_user"') + if 'proxy_pass' in config_args and 'proxy_user' not in config_args: + raise KeyError('A "proxy_user" must be submitted if using a "proxy_pass"') + if 'http_proxy' not in config_args and 'https_proxy' not in config_args: + raise KeyError('A proxy option was submitted for configuration but neither an "http_proxy" nor an ' + '"https_proxy" was submitted') + + # The logic we are using to set up proxies. We store the result into self.session.proxies + proxy_user = config_args['proxy_user'] + ':' if 'proxy_user' in config_args else '' + proxy_pass = config_args['proxy_pass'] + '@' if 'proxy_pass' in config_args else '' + if 'http_proxy' in config_args: + port = ':' + config_args['http_proxy_port'] if 'http_proxy_port' in config_args else '' + self.session.proxies['http'] = 'http://' + proxy_user + proxy_pass + config_args['http_proxy'] + port + if 'https_proxy' in config_args: + port = ':' + config_args['https_proxy_port'] if 'https_proxy_port' in config_args else '' + self.session.proxies['https'] = 'https://' + proxy_user + proxy_pass + config_args['https_proxy'] + port def _get_config_file_params(self, config_file): - """Helper function to parse configuration arguments from a valid IR-Flow configuration file + """Helper function to parse configuration options from a valid IR-Flow configuration file Args: config_file (str): Path to a valid IR-Flow configuration file @@ -1069,37 +1094,14 @@ def _get_config_file_params(self, config_file): # Check if the user is trying to use a proxy by seeing if the config file contains any of the proxy_options. proxy_options = ['proxy_user', 'proxy_pass', 'http_proxy', 'https_proxy', 'http_proxy_port', 'https_proxy_port'] - proxy_usage_found = False + self.proxy_usage = False for option in proxy_options: if config.has_option('IRFlowAPI', option): - proxy_usage_found = True + self.proxy_usage = True break - # If any of the proxy options are used, do some basic error checking. Log issues as warnings. - if proxy_usage_found: - if not config.has_option('IRFlowAPI', 'proxy_user') and config.has_option('IRFlowAPI', 'proxy_pass'): - self.logger.warning( - 'Configuration File "{}" does not contain the "proxy_user" option in the [IRFlowAPI] ' - 'section, but a proxy_pass option was found in the file'.format(config_file) - ) - missing_options.append('proxy_user') - if not config.has_option('IRFlowAPI', 'proxy_pass') and config.has_option('IRFlowAPI', 'proxy_user'): - self.logger.warning( - 'Configuration File "{}" does not contain the "proxy_pass" option in the [IRFlowAPI] ' - 'section, but a proxy_user option was found in the file'.format(config_file) - ) - missing_options.append('proxy_pass') - if not config.has_option('IRFlowAPI', 'http_proxy') or not config.has_option('IRFlowAPI', 'https_proxy'): - self.logger.warning( - 'Configuration File "{}" does not contain the "http_proxy" option or the "https_proxy" option in ' - 'the [IRFlowAPI] section, but a proxy option was found in the file'.format(config_file) - ) - missing_options.append('http_proxy') - missing_options.append('https_proxy') - # Do not need to check for protocol, it is optional. Will assume https if missing. # Do not need to check for debug, it is optional. Will assume False if missing. - # Do not need to check for proxy_user, proxy_pass, http_proxy_port, nor https_proxy_port. They are optional. # If the required keys do not exist, then simply exit if len(missing_options) > 0: @@ -1127,20 +1129,59 @@ def _get_config_file_params(self, config_file): if self.debug: self.dump_settings() - # Our logic for setting up proxies - self.proxies = {} - if proxy_usage_found: - proxy_user = config.get('IRFlowAPI', 'proxy_user') + ':' \ - if config.has_option('IRFlowAPI', 'proxy_user') else '' - proxy_pass = config.get('IRFlowAPI', 'proxy_pass') + '@' \ - if config.has_option('IRFlowAPI', 'proxy_pass') else '' - if config.has_option('IRFlowAPI', 'http_proxy'): - port = ':' + config.get('IRFlowAPI', 'http_proxy_port') \ - if config.has_option('IRFlowAPI', 'http_proxy_port') else '' - self.proxies['http'] = 'http://' + proxy_user + proxy_pass + \ - config.get('IRFlowAPI', 'http_proxy') + port - if config.has_option('IRFlowAPI', 'https_proxy'): - port = ':' + config.get('IRFlowAPI', 'https_proxy_port') \ - if config.has_option('IRFlowAPI', 'https_proxy_port') else '' - self.proxies['https'] = 'https://' + proxy_user + proxy_pass + \ - config.get('IRFlowAPI', 'https_proxy') + port + def _get_proxy_from_config_file(self, config_file): + """Helper function to parse the proxy configuration options from a valid IR-Flow configuration file + + Args: + config_file (str): Path to a valid IR-Flow configuration file + """ + config = configparser.ConfigParser() + + config.read(config_file) + + missing_options = [] + + # If any of the proxy options are used, do some basic error checking. Log issues as warnings. + # We do not need to make sure the config file has the IRFlowAPI section because it was already checked. + if not config.has_option('IRFlowAPI', 'proxy_user') and config.has_option('IRFlowAPI', 'proxy_pass'): + self.logger.warning( + 'Configuration File "{}" does not contain the "proxy_user" option in the [IRFlowAPI] ' + 'section, but a proxy_pass option was found in the file'.format(config_file) + ) + missing_options.append('proxy_user') + if not config.has_option('IRFlowAPI', 'proxy_pass') and config.has_option('IRFlowAPI', 'proxy_user'): + self.logger.warning( + 'Configuration File "{}" does not contain the "proxy_pass" option in the [IRFlowAPI] ' + 'section, but a proxy_user option was found in the file'.format(config_file) + ) + missing_options.append('proxy_pass') + if not config.has_option('IRFlowAPI', 'http_proxy') and not config.has_option('IRFlowAPI', 'https_proxy'): + self.logger.warning( + 'Configuration File "{}" does not contain the "http_proxy" option or the "https_proxy" option in ' + 'the [IRFlowAPI] section, but a proxy option was found in the file'.format(config_file) + ) + missing_options.append('http_proxy') + missing_options.append('https_proxy') + + # Do not need to check for proxy_user, proxy_pass, http_proxy_port, nor https_proxy_port. They are optional. + + # If the required keys do not exist, then simply exit + if len(missing_options) > 0: + self.logger.error('Missing configuration sections: {0}'.format(", ".join(missing_options))) + raise IRFlowClientConfigError('Missing configuration sections: {0}'.format(", ".join(missing_options))) + + # The logic we are using to set up proxies. We store the result into self.session.proxies + proxy_user = config.get('IRFlowAPI', 'proxy_user') + ':' \ + if config.has_option('IRFlowAPI', 'proxy_user') else '' + proxy_pass = config.get('IRFlowAPI', 'proxy_pass') + '@' \ + if config.has_option('IRFlowAPI', 'proxy_pass') else '' + if config.has_option('IRFlowAPI', 'http_proxy'): + port = ':' + config.get('IRFlowAPI', 'http_proxy_port') \ + if config.has_option('IRFlowAPI', 'http_proxy_port') else '' + self.session.proxies['http'] = 'http://' + proxy_user + proxy_pass + \ + config.get('IRFlowAPI', 'http_proxy') + port + if config.has_option('IRFlowAPI', 'https_proxy'): + port = ':' + config.get('IRFlowAPI', 'https_proxy_port') \ + if config.has_option('IRFlowAPI', 'https_proxy_port') else '' + self.session.proxies['https'] = 'https://' + proxy_user + proxy_pass + \ + config.get('IRFlowAPI', 'https_proxy') + port