class DSTestConnectivityConnector(object): def __init__(self, connector): """ :param connector: DigitalShadowsConnector """ self._connector = connector self._handle_exception_object = ExceptionHandling() config = connector.get_config() self._ds_api_key = config[DS_API_KEY_CFG] self._ds_api_secret_key = config[DS_API_SECRET_KEY_CFG] def test_connectivity(self): self._connector.save_progress(DS_TEST_CONNECTIVITY_MSG.format(self._ds_api_key)) try: ds_service = DSBaseService(self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception(e) return self._connector.set_status(phantom.APP_ERROR, "{0} {1}".format(DS_TEST_CONNECTIVITY_MSG_FAIL, error_message)) try: if ds_service.valid_credentials(): return self._connector.set_status(phantom.APP_SUCCESS, DS_TEST_CONNECTIVITY_MSG_PASS) else: return self._connector.set_status(phantom.APP_ERROR, DS_TEST_CONNECTIVITY_MSG_FAIL) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception(e) return self._connector.set_status(phantom.APP_ERROR, "{0}. {1}".format(DS_TEST_CONNECTIVITY_MSG_FAIL, error_message))
def __init__(self, connector): """ :param connector: DigitalShadowsConnector """ self._connector = connector self._handle_exception_object = ExceptionHandling() config = connector.get_config() self._ds_api_key = config[DS_API_KEY_CFG] self._ds_api_secret_key = config[DS_API_SECRET_KEY_CFG]
def __init__(self, connector): """ :param connector: DigitalShadowsConnector """ self._connector = connector self._handle_exception_object = ExceptionHandling() config = connector.get_config() self._ds_api_key = config[DS_API_KEY_CFG] self._ds_api_secret_key = config[DS_API_SECRET_KEY_CFG] self._poll_interval = config['ingest'].get('interval_mins') self._container_label = config['ingest']['container_label'] self._history_days_interval = config['history_days_interval'] self._global_incident = config.get('global_incident', False) self._private_incident = config.get('private_incident', False) self._inc_typ_data_leakage = config.get('inc_typ_data_leakage', False) self._inc_typ_brand_protection = config.get('inc_typ_brand_protection', False) self._inc_typ_infrastructure = config.get('inc_typ_infrastructure', False) self._inc_typ_physical_security = config.get( 'inc_typ_physical_security', False) self._inc_typ_social_media_compliance = config.get( 'inc_typ_social_media_compliance', False) self._inc_typ_cyber_threat = config.get('inc_typ_cyber_threat', False)
class DSSearchEntitiesConnector(object): def __init__(self, connector): """ :param connector: DigitalShadowsConnector """ self._connector = connector config = connector.get_config() self._handle_exception_object = ExceptionHandling() self._ds_api_key = config[DS_API_KEY_CFG] self._ds_api_secret_key = config[DS_API_SECRET_KEY_CFG] def search_entities(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) self._connector.save_progress("process started...!!! ") # type = param.get('types').split(',') type = ["CLIENT_INCIDENT", "DATA_BREACH", "AGGREGATE_DATA_BREACH", "INTELLIGENCE", "TECHNICAL_SOURCE", "WEB_SOURCE"] date_range = param.get('date_range') query = param.get('query') """ incident_types = param.get('incident_types') incident_subtypes = param.get('incident_subtypes') incident_severities = param.get('incident_severities') web_page_networks = param.get('web_page_networks') forum_post_networks = param.get('forum_post_networks') marketplace_listing_networks = param.get('marketplace_listing_networks') market_places = param.get('marketplaces') chat_protocols = param.get('chat_protocols') chat_servers = param.get('chat_servers') chat_channels = param.get('chat_channels') threat_level_types = param.get('threat_level_types') web_page_site_categories = param.get('web_page_site_categories') forum_post_site_categories = param.get('forum_post_site_categories') blog_names = param.get('blog_names') date_period = param.get('date_period') start_date = param.get('from') end_date = param.get('until') """ try: search_service = SearchEntitiesService(self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception(e) return action_result.set_status(phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) try: search_view = search_service.search_entity_view(dateRange=date_range, query_string=query, types=type) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception(e) return action_result.set_status(phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) """ search_view = search_service.search_entity_view(types=type, dateRange=date_range, incidentTypes=incident_types, incidentSubtypes=incident_subtypes, incidentSeverities=incident_severities, webPageNetworks=web_page_networks, forumPostNetworks=forum_post_networks, marketplaceListingNetworks=marketplace_listing_networks, marketplaces=market_places, chatProtocols=chat_protocols, chatServers=chat_servers, chatChannels=chat_channels, threatLevelTypes=threat_level_types, webPageSiteCategories=web_page_site_categories, forumPostSiteCategories=forum_post_site_categories, blogNames=blog_names, datePeriod=date_period, from_date=start_date, until=end_date, query_string=query) """ self._connector.save_progress("View: {}".format(search_view)) try: search_entity_pages = search_service.find_all_pages(view=search_view) # self._connector.save_progress("entity: " + str(search_entity_pages)) entity_total = len(search_entity_pages) except StopIteration: error_message = 'No Search Entity objects retrieved from the Digital Shadows API in page groups' return action_result.set_status(phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception(e) return action_result.set_status(phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) if entity_total > 0: summary = { 'entity_count': entity_total, 'entity_found': True } action_result.update_summary(summary) for entity_page in search_entity_pages: for entity in entity_page: # self._connector.save_progress("entity payload: " + str(entity.payload)) action_result.add_data(entity.payload) action_result.set_status(phantom.APP_SUCCESS, 'String search entities are fetched') else: summary = { 'entity_count': 0, 'entity_found': False } action_result.update_summary(summary) action_result.set_status(phantom.APP_SUCCESS, 'Entities not found for search string') return action_result.get_status()
class DSIntelligenceIncidentsConnector(object): def __init__(self, connector): """ :param connector: DigitalShadowsConnector """ self._connector = connector config = connector.get_config() self._handle_exception_object = ExceptionHandling() self._ds_api_key = config[DS_API_KEY_CFG] self._ds_api_secret_key = config[DS_API_SECRET_KEY_CFG] def get_intelligence_incident_by_id(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) try: intelligence_incident_service = IntelligenceIncidentService( self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) intel_incident_id = param['intel_incident_id'] # validate 'intel_incident_id' action parameter ret_val, intel_incident_id = self._handle_exception_object.validate_integer( action_result, intel_incident_id, INTEL_INCIDENT_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() try: intelligence_incident = intelligence_incident_service.find_intel_incident_by_id( intel_incident_id) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) # intelligence_incident_total = len(intelligence_incident_pages) # if intelligence_incident_total > 0: if 'id' in intelligence_incident: summary = { 'intelligence_incident_count': 1, 'intelligence_incident_found': True } action_result.update_summary(summary) action_result.add_data(intelligence_incident) """ for intelligence_incident_page in intelligence_incident_pages: for intelligence_incident in intelligence_incident_page: data = { 'incident_id': intelligence_incident.id, 'type': intelligence_incident.payload['type'], 'severity': intelligence_incident.payload['severity'], 'title': intelligence_incident.payload['title'], 'summary': unidecode(intelligence_incident.payload['summary']), 'published': intelligence_incident.payload['published'], 'modified': intelligence_incident.payload['modified'], 'occurred': intelligence_incident.payload['occurred'], 'verified': intelligence_incident.payload['verified'], 'description': unidecode(intelligence_incident.payload['description']), 'entitysummary': { 'source': intelligence_incident.payload['entitySummary']['source'], 'summarytext': intelligence_incident.payload['entitySummary']['summarytext'] if 'summarytext' in intelligence_incident.payload['entitySummary'] else '', 'domain': intelligence_incident.payload['entitySummary']['domain'], 'sourceDate': intelligence_incident.payload['entitySummary']['sourceDate'], 'type': intelligence_incident.payload['entitySummary']['type'] } } action_result.add_data(data) """ action_result.set_status(phantom.APP_SUCCESS, DS_GET_INTELLIGENCE_INCIDENT_SUCCESS) return action_result.get_status() def get_intel_incident_ioc_by_id(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) param_types = None if 'types' not in param else param.get( 'types').split(',') try: intelligence_incident_service = IntelligenceIncidentService( self._ds_api_key, self._ds_api_secret_key) intelligence_incident_view = IntelligenceIncidentService.intelligence_incident_ioc_view( types=param_types) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) intel_incident_id = param['intel_incident_id'] # validate 'intel_incident_id' action parameter ret_val, intel_incident_id = self._handle_exception_object.validate_integer( action_result, intel_incident_id, INTEL_INCIDENT_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() try: intelligence_incident_ioc_pages = intelligence_incident_service.find_intel_incident_ioc_by_id( intel_incident_id=intel_incident_id, view=intelligence_incident_view) intelligence_incident_ioc_total = len( intelligence_incident_ioc_pages) self._connector.save_progress( "II IoC Total: {}".format(intelligence_incident_ioc_total)) except StopIteration: error_message = 'No Incident review objects retrieved from the Digital Shadows API' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) if intelligence_incident_ioc_total > 0: summary = { 'intelligence_incident_ioc_count': intelligence_incident_ioc_total, 'intelligence_incident_ioc_found': True } action_result.update_summary(summary) for intelligence_incident_ioc_page in intelligence_incident_ioc_pages: for intelligence_incident_ioc in intelligence_incident_ioc_page: self._connector.save_progress("loop id: {}".format( intelligence_incident_ioc.payload)) action_result.add_data(intelligence_incident_ioc.payload) action_result.set_status(phantom.APP_SUCCESS, DS_GET_INTELLIGENCE_INCIDENT_SUCCESS) return action_result.get_status() def get_intelligence_incident(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) # interval_startdate = date.today() - timedelta(int(param['date_range'])) date_ranges = param.get('date_range') incident_types = [] if param.get('incident_types') is not None: param_incident_types = param.get('incident_types').split(',') for inc_type in param_incident_types: if inc_type == "DATA_LEAKAGE": incident_types.append({ 'type': 'DATA_LEAKAGE', 'subTypes': DS_DL_SUBTYPE }) if inc_type == "BRAND_PROTECTION": incident_types.append({ 'type': 'BRAND_PROTECTION', 'subTypes': DS_BP_SUBTYPE }) if inc_type == "INFRASTRUCTURE": incident_types.append({ 'type': 'INFRASTRUCTURE', 'subTypes': DS_INFR_SUBTYPE }) if inc_type == "PHYSICAL_SECURITY": incident_types.append({ 'type': 'PHYSICAL_SECURITY', 'subTypes': DS_PS_SUBTYPE }) if inc_type == "SOCIAL_MEDIA_COMPLIANCE": incident_types.append({ 'type': 'SOCIAL_MEDIA_COMPLIANCE', 'subTypes': DS_SMC_SUBTYPE }) if inc_type == "CYBER_THREAT": incident_types.append({'type': 'CYBER_THREAT'}) else: param_incident_types = None try: intelligence_incident_service = IntelligenceIncidentService( self._ds_api_key, self._ds_api_secret_key) intelligence_incident_view = IntelligenceIncidentService.intelligence_incidents_view( date_range=date_ranges, date_range_field='published', types=incident_types) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) try: intelligence_incident_pages = intelligence_incident_service.find_all_pages( view=intelligence_incident_view) intelligence_incident_total = len(intelligence_incident_pages) except StopIteration: error_message = 'No IntelligenceIncident objects retrieved from the Digital Shadows API in page groups' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) if intelligence_incident_total > 0: summary = { 'intelligence_incident_count': intelligence_incident_total, 'intelligence_incident_found': True } action_result.update_summary(summary) for intelligence_incident_page in intelligence_incident_pages: for intelligence_incident in intelligence_incident_page: action_result.add_data(intelligence_incident.payload) action_result.set_status(phantom.APP_SUCCESS, DS_GET_INTELLIGENCE_INCIDENT_SUCCESS) return action_result.get_status()
class DSDataBreachConnector(object): def __init__(self, connector): """ :param connector: DigitalShadowsConnector """ self._connector = connector config = connector.get_config() self._handle_exception_object = ExceptionHandling() self._ds_api_key = config[DS_API_KEY_CFG] self._ds_api_secret_key = config[DS_API_SECRET_KEY_CFG] def get_data_breach_by_id(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) try: breach_service = DataBreachService(self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) breach_id = param['breach_id'] # validate 'breach_id' action parameter ret_val, breach_id = self._handle_exception_object.validate_integer( action_result, breach_id, BREACH_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() try: breach = breach_service.find_data_breach_by_id(breach_id) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) if 'id' in breach: summary = {'data_breach_count': 1, 'data_breach_found': True} action_result.update_summary(summary) action_result.add_data(breach) action_result.set_status(phantom.APP_SUCCESS, DS_GET_BREACH_SUCCESS) else: summary = {'data_breach_count': 0, 'data_breach_found': False} action_result.update_summary(summary) action_result.set_status(phantom.APP_SUCCESS, DS_GET_BREACH_NOT_FOUND) return action_result.get_status() def get_data_breach(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) date_range = param['date_range'] param_reposted_credentials = None if 'reposted_credentials' not in param else param[ 'reposted_credentials'].split(',') param_severities = None if 'severities' not in param else param.get( 'severities').split(',') param_statuses = None if 'statuses' not in param else param.get( 'statuses').split(',') param_user_name = None if 'user_name' not in param else param.get( 'user_name').split(',') try: breach_service = DataBreachService(self._ds_api_key, self._ds_api_secret_key) breach_view = DataBreachService.data_breach_view( published=date_range, reposted_credentials=param_reposted_credentials, severities=param_severities, statuses=param_statuses, username=param_user_name) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) try: breach_pages = breach_service.find_all_pages(view=breach_view) breach_total = len(breach_pages) except StopIteration: error_message = 'No DataBreach objects retrieved from the Digital Shadows API in page groups' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) if breach_total > 0: summary = { 'data_breach_count': breach_total, 'data_breach_found': True } action_result.update_summary(summary) for breach_page in breach_pages: for breach in breach_page: action_result.add_data(breach.payload) action_result.set_status(phantom.APP_SUCCESS, DS_GET_BREACH_SUCCESS) else: summary = {'data_breach_count': 0, 'data_breach_found': False} action_result.update_summary(summary) action_result.set_status(phantom.APP_SUCCESS, DS_GET_BREACH_NOT_FOUND) return action_result.get_status() def get_data_breach_record(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) date_range = param['date_range'] if 'domain_names' in param: param_domain_names = param['domain_names'].split(',') else: param_domain_names = None if 'review_statuses' in param: param_review_statuses = param['review_statuses'].split(',') else: param_review_statuses = None param_distinction = param.get('distinction') param_user_name = param.get('user_name') param_password = param.get('password') try: breach_record_service = DataBreachRecordService( self._ds_api_key, self._ds_api_secret_key) breach_record_view = DataBreachRecordService.data_breach_records_view( published=date_range, domain_names=param_domain_names, username=param_user_name, password=param_password, review_statuses=param_review_statuses, distinction=param_distinction) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) self._connector.save_progress(str(breach_record_view)) try: breach_record_pages = breach_record_service.read_all_records( view=breach_record_view) breach_record_total = len(breach_record_pages) except StopIteration: error_message = 'No DataBreach objects retrieved from the Digital Shadows API in page groups' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) if breach_record_total > 0: summary = { 'data_breach_record_count': breach_record_total, 'data_breach_record_found': True } action_result.update_summary(summary) for breach_record_page in breach_record_pages: for breach_record in breach_record_page: action_result.add_data(breach_record.payload) action_result.set_status( phantom.APP_SUCCESS, "Digital Shadows data breach records fetched") else: summary = { 'data_breach_record_count': 0, 'data_breach_record_found': False } action_result.update_summary(summary) action_result.set_status( phantom.APP_SUCCESS, "Data breach record not found in Digital Shadows") return action_result.get_status() def get_data_breach_record_by_id(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) try: breach_record_service = DataBreachRecordService( self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) breach_id = param['breach_id'] # validate 'breach_id' action parameter ret_val, breach_id = self._handle_exception_object.validate_integer( action_result, breach_id, BREACH_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() try: breach_record_pages = breach_record_service.find_all_pages( breach_id) breach_record_total = len(breach_record_pages) except StopIteration: error_message = 'No data breach record retrieved from the Digital Shadows API in page groups' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) if breach_record_total > 0: summary = { 'data_breach_record_count': breach_record_total, 'data_breach_record_found': True } action_result.update_summary(summary) for breach_record_page in breach_record_pages: for breach_record in breach_record_page: action_result.add_data(breach_record.payload) action_result.set_status( phantom.APP_SUCCESS, "Digital Shadows data breach records fetched") else: summary = { 'data_breach_record_count': 0, 'data_breach_record_found': False } action_result.update_summary(summary) action_result.set_status( phantom.APP_SUCCESS, "Data breach record not found in Digital Shadows") return action_result.get_status() def get_data_breach_record_by_username(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) try: breach_record_service = DataBreachRecordService( self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) user_name = param['user_name'] domain_names_param = None if 'domain_names' not in param else param[ 'domain_names'].split(',') review_statuses_param = None if 'review_statuses' not in param else param[ 'review_statuses'].split(',') published_date_range = param.get('published_date_range', 'ALL') try: breach_record_view = DataBreachRecordService.data_breach_records_view( username=user_name, published=published_date_range, domain_names=domain_names_param, review_statuses=review_statuses_param) self._connector.save_progress( "Breach record View: {}".format(breach_record_view)) breach_record_pages = breach_record_service.read_all_records( view=breach_record_view) except StopIteration: error_message = 'No DataBreach objects retrieved from the Digital Shadows API in page groups' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) breach_record_total = len(breach_record_pages) if breach_record_total > 0: summary = { 'data_breach_record_count': breach_record_total, 'data_breach_record_found': True } action_result.update_summary(summary) for breach_record_page in breach_record_pages: for breach_record in breach_record_page: action_result.add_data(breach_record.payload) action_result.set_status( phantom.APP_SUCCESS, "Digital Shadows data breach records fetched") else: summary = { 'data_breach_record_count': 0, 'data_breach_record_found': False } action_result.update_summary(summary) action_result.set_status( phantom.APP_SUCCESS, "Data breach record not found in Digital Shadows") return action_result.get_status() def get_data_breach_record_reviews(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) try: breach_record_service = DataBreachRecordService( self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) breach_record_id = param['breach_record_id'] # validate 'breach_record_id' action parameter ret_val, breach_record_id = self._handle_exception_object.validate_integer( action_result, breach_record_id, BREACH_RECORD_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() try: breach_record_reviews = breach_record_service.find_data_breach_record_reviews( breach_record_id) breach_record_reviews_total = len(breach_record_reviews) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) if breach_record_reviews_total > 0: summary = { 'breach_record_reviews_count': breach_record_reviews_total, 'breach_record_reviews_found': True } action_result.update_summary(summary) for breach_record_review in breach_record_reviews: action_result.add_data(breach_record_review) action_result.set_status( phantom.APP_SUCCESS, "Digital Shadows breach record reviews fetched for the Breach Record ID: {}" .format(breach_record_id)) return action_result.get_status() def post_breach_record_review(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) try: breach_record_service = DataBreachRecordService( self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) post_data = { 'note': param.get('review_note'), 'status': param.get('review_status') } breach_record_id = param.get('breach_record_id') # validate 'breach_record_id' action parameter ret_val, breach_record_id = self._handle_exception_object.validate_integer( action_result, breach_record_id, BREACH_RECORD_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() try: response = breach_record_service.post_data_breach_record_review( post_data, breach_record_id=breach_record_id) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) summary = { 'breach_record_reviews_status_code': response['status'], 'breach_record_reviews_message': response['message'] } action_result.update_summary(summary) if response['message'] == "SUCCESS": action_result.set_status( phantom.APP_SUCCESS, "Digital Shadows breach record review posted successfully") else: action_result.set_status( phantom.APP_SUCCESS, "Error in breach record review post request")
class DSOnPollConnector(object): def __init__(self, connector): """ :param connector: DigitalShadowsConnector """ self._connector = connector self._handle_exception_object = ExceptionHandling() config = connector.get_config() self._ds_api_key = config[DS_API_KEY_CFG] self._ds_api_secret_key = config[DS_API_SECRET_KEY_CFG] self._poll_interval = config['ingest'].get('interval_mins') self._container_label = config['ingest']['container_label'] self._history_days_interval = config['history_days_interval'] self._global_incident = config.get('global_incident', False) self._private_incident = config.get('private_incident', False) self._inc_typ_data_leakage = config.get('inc_typ_data_leakage', False) self._inc_typ_brand_protection = config.get('inc_typ_brand_protection', False) self._inc_typ_infrastructure = config.get('inc_typ_infrastructure', False) self._inc_typ_physical_security = config.get( 'inc_typ_physical_security', False) self._inc_typ_social_media_compliance = config.get( 'inc_typ_social_media_compliance', False) self._inc_typ_cyber_threat = config.get('inc_typ_cyber_threat', False) def on_poll(self, param): # noqa self._connector.debug_print(param) action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) start_time, end_time = self._phantom_daterange(param) if start_time is None or end_time is None: action_result.set_status( phantom.APP_ERROR, status_message='start time or end time not specified') else: self._connector.save_progress("Start creating incident") # Validate 'history_days_interval' configuration parameter ret_val, self._history_days_interval = self._handle_exception_object.validate_integer( action_result, self._history_days_interval, HISTORY_DAYS_INTERVAL_KEY) if phantom.is_fail(ret_val): return action_result.get_status() date_range = "P{}D".format(self._history_days_interval) incident_types = [] if self._inc_typ_data_leakage: incident_types.append({ 'type': 'DATA_LEAKAGE', 'subTypes': DS_DL_SUBTYPE }) if self._inc_typ_brand_protection: incident_types.append({ 'type': 'BRAND_PROTECTION', 'subTypes': DS_BP_SUBTYPE }) if self._inc_typ_infrastructure: incident_types.append({ 'type': 'INFRASTRUCTURE', 'subTypes': DS_INFR_SUBTYPE }) if self._inc_typ_physical_security: incident_types.append({ 'type': 'PHYSICAL_SECURITY', 'subTypes': DS_PS_SUBTYPE }) if self._inc_typ_social_media_compliance: incident_types.append({ 'type': 'SOCIAL_MEDIA_COMPLIANCE', 'subTypes': DS_SMC_SUBTYPE }) if self._inc_typ_cyber_threat: incident_types.append({'type': 'CYBER_THREAT'}) if self._private_incident: try: incident_service = IncidentService(self._ds_api_key, self._ds_api_secret_key) incident_view = IncidentService.incidents_view( date_range=date_range, date_range_field='published', statuses=['READ', 'UNREAD'], types=incident_types) self._connector.save_progress( "incident req view: {}".format( json.dumps(incident_view, ensure_ascii=False))) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) try: incident_pages = incident_service.find_all_pages( view=incident_view) j = 0 incident_total = len(incident_pages) except StopIteration: error_message = 'No Incident objects retrieved from the Digital Shadows API in page groups' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) for incident_page in incident_pages: for incident in incident_page: status, message = self._save_incident(incident) if status == phantom.APP_SUCCESS: j += 1 self._connector.save_progress( DS_POLL_INCIDENT_COMPLETE.format( incident.id, j, incident_total)) else: self._connector.error_print( "Did not ingest incident {}".format( incident.id)) action_result.set_status(phantom.APP_ERROR, message) self._connector.add_action_result(action_result) return action_result.get_status() self._connector.save_progress( "Ingesting DS Incidents Completed.") if j != incident_total: action_result.set_status( phantom.APP_ERROR, status_message= 'Did not receive all the incident from Digital Shadows' ) else: action_result.set_status(phantom.APP_SUCCESS) if self._global_incident: try: intelligence_incident_service = IntelligenceIncidentService( self._ds_api_key, self._ds_api_secret_key) intelligence_incident_view = IntelligenceIncidentService.intelligence_incidents_view( date_range=date_range, date_range_field='published', types=incident_types) self._connector.save_progress( 'intelligence_incident_view: {}'.format( json.dumps(intelligence_incident_view, ensure_ascii=False))) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) try: intelligence_incident_pages = intelligence_incident_service.find_all_pages( view=intelligence_incident_view) k = 0 intelligence_incident_total = len( intelligence_incident_pages) except StopIteration: error_message = 'No IntelligenceIncident objects retrieved from the Digital Shadows API in page groups' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {}".format(error_message)) for intelligence_incident_page in intelligence_incident_pages: for intelligence_incident in intelligence_incident_page: self._connector.save_progress('count: {}'.format(k)) status, message = self._save_intel_incident( intelligence_incident) if status == phantom.APP_SUCCESS: k += 1 self._connector.save_progress( DS_POLL_INCIDENT_COMPLETE.format( intelligence_incident.id, k, intelligence_incident_total)) else: self._connector.error_print( "Did not ingest intel-incident {}".format( intelligence_incident.id)) action_result.set_status(phantom.APP_ERROR, message) self._connector.add_action_result(action_result) return action_result.get_status() if k != intelligence_incident_total: action_result.set_status( phantom.APP_ERROR, status_message= 'Did not receive all the intelligence incident from Digital Shadows' ) else: action_result.set_status(phantom.APP_SUCCESS) self._connector.save_progress( "Ingesting DS Intelligence Incidents Completed.") """ self._connector.save_progress("Ingesting Data Breaches from {} until {}".format(start_time, end_time)) published_filter = '{}/{}'.format(start_time.isoformat(), end_time.isoformat()) breach_service = DataBreachService(self._ds_api_key, self._ds_api_secret_key) view = DataBreachService.data_breach_view(published=published_filter) breach_pages = breach_service.find_all_pages(view=view) i = 0 total = len(breach_pages) for breach_page in breach_pages: for breach in breach_page: status, message = self._save_data_breach(breach) if status == phantom.APP_SUCCESS: i += 1 self._connector.save_progress(DS_POLL_BREACH_COMPLETE.format(breach.id, i, total)) else: self._connector.error_print("Did not ingest Data Breach {}".format(breach.id)) action_result.set_status(phantom.APP_ERROR, message) self._connector.add_action_result(action_result) return action_result.get_status() if i != total: action_result.set_status(phantom.APP_ERROR, status_message='Did not receive all data breaches from Digital Shadows') else: action_result.set_status(phantom.APP_SUCCESS) """ return action_result.get_status() def _phantom_daterange(self, param): """ Extract Phantom start time and end time as datetime objects. Divide by 1000 to resolve milliseconds. :param param: dict :return: start_time, end_time """ try: start_time_param = float(param.get('start_time')) end_time_param = float(param.get('end_time')) except TypeError: self._connector.error_print("start time or end time not specified") return None, None return datetime.fromtimestamp( start_time_param / 1000.0), datetime.fromtimestamp(end_time_param / 1000.0) def _save_data_breach(self, breach): container = self._prepare_container(breach) status, message, container_id = self._connector.save_container( container) if status == phantom.APP_SUCCESS: breach_record_service = DataBreachRecordService( self._ds_api_key, self._ds_api_secret_key) for breach_record_page in breach_record_service.find_all_pages( breach.id): artifacts = list( map( lambda breach_record: self._prepare_artifact( container_id, container['severity'], breach, breach_record), breach_record_page)) self._connector.save_artifacts(artifacts) return status, message else: return status, message def _save_intel_incident(self, intelligence_incident): container = self._prepare_intel_incident_container( intelligence_incident) status, message, container_id = self._connector.save_container( container) if status == phantom.APP_SUCCESS and message != 'Duplicate container found': intel_incident_artifacts = self._prepare_intel_incident_artifact( container_id, container['severity'], intelligence_incident) self._connector.save_artifact(intel_incident_artifacts) self._connector.save_progress( "Created the intelligence incident successfully") return status, message else: return status, message def _prepare_intel_incident_container(self, intelligence_incident): """ Create a container from Digital Shadows incident. """ # now = datetime.now() container = dict() # self._connector.save_progress(" print container: " + str(container)) container['label'] = self._container_label container['name'] = '{} - {}'.format( intelligence_incident.payload['type'].title().replace('_', ' '), unidecode(intelligence_incident.payload['title'])) intel_incident_desc = unidecode(intelligence_incident.payload['title']) # intel_incident_desc = intel_incident_desc.replace( u'\u201c', u'"').replace( u'\u201d', u'"') container['description'] = '{}'.format(intel_incident_desc) container['custom_fields'] = dict() container['custom_fields']['IncidentType'] = str( intelligence_incident.payload['type']) if 'subType' in intelligence_incident.payload: container['custom_fields']['IncidentSubType'] = str( intelligence_incident.payload['subType']) container['custom_fields'][ 'IncidentURL'] = 'https://portal-digitalshadows.com/client/intelligence/incident/{}'.format( intelligence_incident.payload['id']) container['severity'] = self._ds_to_phantom_severity_transform( intelligence_incident.payload['severity']) container['source_data_identifier'] = intelligence_incident.id container['start_time'] = intelligence_incident.payload['published'] container['ingest_app_id'] = self._connector.get_app_id() return container def _prepare_intel_incident_artifact(self, container_id, container_severity, intelligence_incident): """ Create an artifact from Digital Shadows Intelligence Incidents. :param container_id: int :param incident: DS Incident :return: dict """ now = datetime.now() artifact = dict() artifact['container_id'] = container_id artifact['label'] = ' ' artifact['name'] = 'Intelligence Incident details' artifact['description'] = 'Details provided by Digital Shadows' artifact['severity'] = container_severity artifact['type'] = ' ' artifact['start_time'] = now.strftime('%Y-%m-%dT%H:%M:%S.%fZ') artifact['source_data_identifier'] = intelligence_incident.id artifact['run_automation'] = False artifact['cef'] = dict() artifact['cef']['externalId'] = intelligence_incident.id artifact['cef'][ 'deviceAddress'] = 'https://portal-digitalshadows.com/client/intelligence/incident/{}'.format( intelligence_incident.id) artifact['cef'][' Title'] = intelligence_incident.payload['title'] # artifact['cef'][' Type'] = intelligence_incident.payload['type'].title().replace('_', ' ') artifact['cef']['deviceEventCategory'] = intelligence_incident.payload[ 'type'] if 'subType' in intelligence_incident.payload: # artifact['cef'][' SubType'] = intelligence_incident.payload['subType'].title().replace('_', ' ') artifact['cef']['deviceFacility'] = intelligence_incident.payload[ 'subType'] artifact['cef'][' Description'] = intelligence_incident.payload[ 'description'] # artifact['cef'][' Impact'] = intelligence_incident.payload['impactDescription'] # artifact['cef'][' Mitigation'] = intelligence_incident.payload['mitigation'] artifact['cef'][' Summary'] = dict() # artifact['cef'][' Summary'] = intelligence_incident.payload['entitySummary'] if 'domain' in intelligence_incident.payload['entitySummary']: # artifact['cef'][' Summary']['domain'] = intelligence_incident.payload['entitySummary']['domain'] artifact['cef']['deviceDnsDomain'] = intelligence_incident.payload[ 'entitySummary']['domain'] if 'contentRemoved' in intelligence_incident.payload['entitySummary']: artifact['cef'][' Summary'][ 'contentRemoved'] = intelligence_incident.payload[ 'entitySummary']['contentRemoved'] if 'source' in intelligence_incident.payload['entitySummary']: artifact['cef'][' Summary'][ 'source'] = intelligence_incident.payload['entitySummary'][ 'source'] if 'sourceDate' in intelligence_incident.payload['entitySummary']: artifact['cef'][' Summary'][ 'sourceDate'] = intelligence_incident.payload['entitySummary'][ 'sourceDate'] if 'summaryText' in intelligence_incident.payload['entitySummary']: artifact['cef'][' Summary'][ 'summaryText'] = intelligence_incident.payload[ 'entitySummary']['summaryText'] if 'type' in intelligence_incident.payload['entitySummary']: # artifact['cef'][' Summary']['type'] = intelligence_incident.payload['entitySummary']['type'] artifact['cef']['fileType'] = intelligence_incident.payload[ 'entitySummary']['type'] if 'dataBreach' in intelligence_incident.payload['entitySummary']: # artifact['cef'][' Summary']['DataBreach ID'] = intelligence_incident.payload['entitySummary']['dataBreach']['id'] artifact['cef'][ 'deviceExternalId'] = intelligence_incident.payload[ 'entitySummary']['dataBreach']['id'] artifact['cef'][' Internal'] = intelligence_incident.payload[ 'internal'] artifact['cef'][' Restricted'] = intelligence_incident.payload[ 'restrictedContent'] artifact['cef']['Dates'] = dict() if 'alerted' in intelligence_incident.payload: artifact['cef']['Dates'][ 'alerted'] = intelligence_incident.payload['alerted'] artifact['cef']['Dates']['verified'] = intelligence_incident.payload[ 'verified'] artifact['cef']['Dates']['occurred'] = intelligence_incident.payload[ 'occurred'] artifact['cef']['Dates']['modified'] = intelligence_incident.payload[ 'modified'] # artifact['cef']['Dates']['published'] = intelligence_incident.payload['published'] artifact['cef']['deviceCustomeDate1'] = intelligence_incident.payload[ 'published'] artifact['cef_types'] = dict() artifact['cef_types']['deviceAddress'] = ['url'] return artifact def _save_incident(self, incident): container = self._prepare_incident_container(incident) status, message, container_id = self._connector.save_container( container) if status == phantom.APP_SUCCESS and message != 'Duplicate container found': incident_artifacts = self._prepare_incident_artifact( container_id, container['severity'], incident) self._connector.save_artifact(incident_artifacts) self._connector.save_progress("Created the incident successfully") return status, message else: return status, message def _prepare_incident_container(self, incident): """ Create a container from Digital Shadows incident. """ # now = datetime.now() container = dict() container['label'] = self._container_label container['name'] = '{} - {}'.format( incident.payload['type'].title().replace('_', ' '), unidecode(incident.payload['title'])) incident_desc = unidecode(incident.payload['title']) container['description'] = '{}'.format(incident_desc) container['custom_fields'] = dict() container['custom_fields']['IncidentType'] = str( incident.payload['type']) if 'subType' in incident.payload: container['custom_fields']['IncidentSubType'] = str( incident.payload['subType']) container['custom_fields'][ 'IncidentURL'] = 'https://www.portal-digitalshadows.com/client/incidents/{}'.format( incident.payload['id']) container['severity'] = self._ds_to_phantom_severity_transform( incident.payload['severity']) container['source_data_identifier'] = incident.id container['start_time'] = incident.payload['published'] container['ingest_app_id'] = self._connector.get_app_id() return container def _prepare_incident_artifact(self, container_id, container_severity, incident): """ Create an artifact from Digital Shadows Incidents. :param container_id: int :param incident: DS Incident :return: dict """ now = datetime.now() artifact = dict() artifact['container_id'] = container_id artifact['label'] = ' ' artifact['name'] = 'Incident details' artifact['description'] = 'Details provided by Digital Shadows' artifact['severity'] = container_severity artifact['type'] = ' ' artifact['start_time'] = now.strftime('%Y-%m-%dT%H:%M:%S.%fZ') artifact['source_data_identifier'] = incident.id artifact['run_automation'] = False artifact['cef'] = dict() artifact['cef']['externalId'] = incident.id artifact['cef'][ 'deviceAddress'] = 'https://www.portal-digitalshadows.com/client/incidents/{}'.format( incident.payload['id']) artifact['cef'][' Title'] = incident.payload['title'] # artifact['cef'][' Type'] = incident.payload['type'].title().replace('_', ' ') artifact['cef']['deviceEventCategory'] = incident.payload['type'] if 'subType' in incident.payload: # artifact['cef'][' Sub Type'] = incident.payload['subType'].title().replace('_', ' ') artifact['cef']['deviceFacility'] = incident.payload['subType'] artifact['cef'][' Description'] = incident.payload['description'] artifact['cef'][' Impact'] = incident.payload['impactDescription'] artifact['cef'][' Mitigation'] = incident.payload['mitigation'] artifact['cef'][' Summary'] = dict() # artifact['cef'][' Summary'] = incident.payload['entitySummary'] if 'domain' in incident.payload['entitySummary']: artifact['cef']['deviceDnsDomain'] = incident.payload[ 'entitySummary']['domain'] if 'type' in incident.payload['entitySummary']: artifact['cef']['fileType'] = incident.payload['entitySummary'][ 'type'] if 'contentRemoved' in incident.payload['entitySummary']: artifact['cef'][' Summary']['contentRemoved'] = incident.payload[ 'entitySummary']['contentRemoved'] if 'source' in incident.payload['entitySummary']: artifact['cef'][' Summary']['source'] = incident.payload[ 'entitySummary']['source'] if 'sourceDate' in incident.payload['entitySummary']: artifact['cef'][' Summary']['sourceDate'] = incident.payload[ 'entitySummary']['sourceDate'] if 'summaryText' in incident.payload['entitySummary']: artifact['cef'][' Summary']['summaryText'] = incident.payload[ 'entitySummary']['summaryText'] if 'type' in incident.payload['entitySummary']: artifact['cef']['fileType'] = incident.payload['entitySummary'][ 'type'] if 'dataBreach' in incident.payload['entitySummary']: artifact['cef']['deviceExternalId'] = incident.payload[ 'entitySummary']['dataBreach']['id'] if 'internal' in incident.payload: artifact['cef'][' Internal'] = incident.payload['internal'] if 'restrictedContent' in incident.payload: artifact['cef'][' Restricted'] = incident.payload[ 'restrictedContent'] artifact['cef']['Dates'] = dict() if 'alerted' in incident.payload: artifact['cef']['Dates']['alerted'] = incident.payload['alerted'] if 'verified' in incident.payload: artifact['cef']['Dates']['verified'] = incident.payload['verified'] if 'occurred' in incident.payload: artifact['cef']['Dates']['occurred'] = incident.payload['occurred'] if 'modified' in incident.payload: artifact['cef']['Dates']['modified'] = incident.payload['modified'] # artifact['cef']['Dates']['published'] = incident.payload['published'] artifact['cef']['deviceCustomeDate1'] = incident.payload['published'] artifact['cef_types'] = dict() artifact['cef_types']['deviceAddress'] = ['url'] return artifact def _prepare_container(self, breach): """ Create a container from Digital Shadows Data Breach. :param breach: DataBreach :return: dict """ container = dict() container['label'] = self._container_label container['name'] = 'Digital Shadows Data Breach {}'.format(breach.id) container['description'] = '{}'.format(breach.incident_title) container['severity'] = self._ds_to_phantom_severity_transform( breach.incident_severity) container['source_data_identifier'] = breach.id container['start_time'] = breach.published container['ingest_app_id'] = self._connector.get_app_id() return container def _prepare_artifact(self, container_id, container_severity, breach, breach_record): """ Create an artifact from Digital Shadows Data Breach Record. :param container_id: int :param breach: DataBreach :param breach_record: DataBreachRecord :return: dict """ source_host_name = urlparse( breach.source_url ).hostname if breach.source_url is not None else None link_to_incident = "{}/client/incidents/{}".format( ds_api_host, breach.incident_id) artifact = dict() artifact['container_id'] = container_id artifact['label'] = self._container_label artifact['name'] = 'Digital Shadows Data Breach Record {}'.format( breach_record.id) artifact['type'] = 'data breach record' artifact['severity'] = container_severity artifact['start_time'] = breach_record.published artifact['source_data_identifier'] = breach_record.id artifact['cef'] = { 'suser': '******'.format(breach_record.username), 'sourceHostName': '{}'.format(source_host_name), 'cs1Label': 'Password', 'cs1': '{}'.format(breach_record.password), 'cs2Label': 'Source Url', 'cs2': '{}'.format(breach.source_url), 'cs3Label': 'Link to Incident', 'cs3': link_to_incident, 'cn1Label': 'Digital Shadows Incident Id', 'cn1': '{}'.format(breach.incident_id) } return artifact def _ds_to_phantom_severity_transform(self, severity): """ Map Digital Shadows severity to Phantom severity. :param severity: DS Severity: VERY_HIGH, HIGH, MEDIUM, LOW, VERY_LOW, NONE :return: Phantom Severity: high, medium, low """ return { 'VERY_HIGH': 'high', 'HIGH': 'high', 'MEDIUM': 'medium', 'LOW': 'low', 'VERY_LOW': 'low', 'NONE': 'low' }.get(severity)
class DSIncidentsConnector(object): def __init__(self, connector): """ :param connector: DigitalShadowsConnector """ self._connector = connector config = connector.get_config() self._handle_exception_object = ExceptionHandling() self._ds_api_key = config[DS_API_KEY_CFG] self._ds_api_secret_key = config[DS_API_SECRET_KEY_CFG] def get_incident_by_id(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) try: incident_service = IncidentService(self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) incident_id = param['incident_id'] # validate 'incident_id' action parameter ret_val, incident_id = self._handle_exception_object.validate_integer( action_result, incident_id, INCIDENT_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() try: incident = incident_service.find_incident_by_id(incident_id) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) if 'id' in incident: summary = {'incident_found': True} action_result.update_summary(summary) action_result.add_data(incident) action_result.set_status(phantom.APP_SUCCESS, DS_GET_INCIDENT_SUCCESS) return action_result.get_status() def get_incident_review_by_id(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) incident_id = param['incident_id'] # validate 'incident_id' action parameter ret_val, incident_id = self._handle_exception_object.validate_integer( action_result, incident_id, INCIDENT_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() try: incident_service = IncidentService(self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) try: incident_reviews = incident_service.find_all_reviews(incident_id) incident_reviews_total = len(incident_reviews) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) if incident_reviews_total > 0: summary = { 'incident_reviews_count': incident_reviews_total, 'incident_reviews_found': True } action_result.update_summary(summary) for incident_review in incident_reviews: action_result.add_data(incident_review) action_result.set_status( phantom.APP_SUCCESS, "Digital Shadows incident reviews fetched for the Incident ID: {}" .format(incident_id)) return action_result.get_status() def get_incident_list(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) # interval_startdate = date.today() - timedelta(int(param['date_range'])) incident_types = [] if param.get('incident_types') is not None: param_incident_types = str(param['incident_types']).split(',') for inc_type in param_incident_types: if inc_type == "DATA_LEAKAGE": incident_types.append({ 'type': 'DATA_LEAKAGE', 'subTypes': DS_DL_SUBTYPE }) if inc_type == "BRAND_PROTECTION": incident_types.append({ 'type': 'BRAND_PROTECTION', 'subTypes': DS_BP_SUBTYPE }) if inc_type == "INFRASTRUCTURE": incident_types.append({ 'type': 'INFRASTRUCTURE', 'subTypes': DS_INFR_SUBTYPE }) if inc_type == "PHYSICAL_SECURITY": incident_types.append({ 'type': 'PHYSICAL_SECURITY', 'subTypes': DS_PS_SUBTYPE }) if inc_type == "SOCIAL_MEDIA_COMPLIANCE": incident_types.append({ 'type': 'SOCIAL_MEDIA_COMPLIANCE', 'subTypes': DS_SMC_SUBTYPE }) if inc_type == "CYBER_THREAT": incident_types.append({'type': 'CYBER_THREAT'}) else: param_incident_types = None try: incident_service = IncidentService(self._ds_api_key, self._ds_api_secret_key) incident_view = IncidentService.incidents_view( date_range=param.get('date_range'), date_range_field='published', types=incident_types) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) self._connector.save_progress( "incident view: {}".format(incident_view)) try: incident_pages = incident_service.find_all_pages( view=incident_view) self._connector.save_progress( "incident_pages next: {}".format(incident_pages)) incident_total = len(incident_pages) except StopIteration: error_message = 'No Incident objects retrieved from the Digital Shadows API in page groups' return action_result.set_status( phantom.APP_ERROR, "Error Details: {0}".format(error_message)) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) if incident_total > 0: summary = { 'incident_count': incident_total, 'incident_found': True } action_result.update_summary(summary) self._connector.save_progress( "incident_pages: {}".format(incident_pages)) for incident_page in incident_pages: for incident in incident_page: self._connector.save_progress('incident: {}'.format( incident.payload)) action_result.add_data(incident.payload) action_result.set_status(phantom.APP_SUCCESS, DS_GET_INCIDENT_SUCCESS) return action_result.get_status() def post_incident_review(self, param): action_result = ActionResult(dict(param)) self._connector.add_action_result(action_result) try: incident_service = IncidentService(self._ds_api_key, self._ds_api_secret_key) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "{0} {1}".format(SERVICE_ERR_MSG, error_message)) incident_id = param.get('incident_id') # validate 'incident_id' action parameter ret_val, incident_id = self._handle_exception_object.validate_integer( action_result, incident_id, INCIDENT_ID_KEY) if phantom.is_fail(ret_val): return action_result.get_status() post_data = { 'note': param.get('review_note'), 'status': param.get('review_status') } self._connector.save_progress("post_data: {}".format(post_data)) try: response = incident_service.post_incident_review( post_data, incident_id=incident_id) except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error Connecting to server. {0}".format(error_message)) self._connector.save_progress("response: {}".format(response)) try: summary = { 'incident_reviews_status_code': response['status'], 'incident_reviews_message': response['message'] } action_result.update_summary(summary) action_result.add_data(response['content'][0]) if response['message'] == "SUCCESS": action_result.set_status( phantom.APP_SUCCESS, "Digital Shadows Incident review posted successfully") else: action_result.set_status( phantom.APP_SUCCESS, "Error in incident review post request") except Exception as e: error_message = self._handle_exception_object.get_error_message_from_exception( e) return action_result.set_status( phantom.APP_ERROR, "Error occurred while fetching data from response. {}".format( error_message)) return action_result.get_status()