def add_device_counts(policy_list): devices = di.get_devices(include_deactivated=False) device_counts = di.count_data_by_field(devices, 'policy_id') for policy in policy_list: if policy['ID'] not in device_counts.keys(): policy['Device Count'] = 0 else: policy['Device Count'] = device_counts[policy['ID']] return policy_list
#get tenant data from server print('INFO: Getting Tenant data from server') tenants = di.get_tenants() #confirm that we got valid data back; if not, abort script if len(tenants) == 0: print('ERROR: No Tenants returned. Check that server is multi-tenancy enabled and that your API key has the appropriate permissions.') sys.exit(0) #get msp data from server print('INFO: Getting MSP data from server') msps = di.get_msps() # get device data from server print('INFO: Getting Device data from server') devices = di.get_devices(include_deactivated=False) # add msp_name to tenant data print('INFO: Adding MSP names to Tenant data') for tenant in tenants: for msp in msps: if tenant['msp_id'] == msp['id']: tenant['msp_name'] = msp['name'] # If option to include policy mode counts is enabled, get policy details, # then parse policies to calculate mode, then add that data to devices if include_policy_mode_counts: print('INFO: Getting policy data from server') policies = di.get_policies(include_policy_data=True) print('INFO: Parsing policy data to determine policy mode')
def run_deployment_phase_progression_readiness(fqdn, key, config): print('Beginning data collection') di.fqdn = fqdn di.key = key di.quiet_mode = True config = config mt = di.is_server_multitenancy_enabled() #collect policy data print('\nGetting policy data from server') policies = di.get_policies(include_policy_data=True) #collect event data search_parameters = get_event_search_parameters(config['deployment_phase']) suspicious_search_parameters = get_suspicious_event_search_parameters( config['deployment_phase']) print('\nGetting event data from server') events = di.get_events(search=search_parameters) print(len(events), 'events were returned.') if not config['ignore_suspicious_events']: if suspicious_search_parameters != {}: print('\nGetting suspicious event data from server') suspicious_events = di.get_suspicious_events( search=suspicious_search_parameters) print(len(suspicious_events), 'suspicious events were returned.') events = events + suspicious_events event_counts = di.count_data_by_field(events, 'device_id') #collect device data print('\nGetting device data from server') devices = di.get_devices(include_deactivated=False) print(len(devices), 'devices were found.') #determine if we have data from a single MSP or multiple policy_msp_ids = [] for policy in policies: if policy['msp_id'] not in policy_msp_ids: policy_msp_ids.append(policy['msp_id']) if len(policy_msp_ids) > 1: multiple_msps = True else: multiple_msps = False print('\nAnalyzing policy data') policy_evaluation_results = [] for policy in policies: policy['deployment_phase'] = classify_policy(policy, config) if policy['os'] == 'WINDOWS': if policy['deployment_phase'] > 0: result = f"Policy '{policy['name']}' (ID {policy['id']}) is a Phase {policy['deployment_phase']} policy." else: result = f"Policy '{policy['name']}' (ID {policy['id']}) is not aligned with any defined Deployment Phase." if mt and multiple_msps: result = f"MSP '{policy['msp_name']}' (ID {policy['msp_id']}) {result}" print(result) policy_evaluation_results.append(result) filtered_devices = [] for device in devices: for policy in policies: if policy['id'] == device['policy_id']: device['deployment_phase'] = policy['deployment_phase'] if device['deployment_phase'] == config['deployment_phase']: filtered_devices.append(device) excluded_device_count = len(devices) - len(filtered_devices) devices = filtered_devices print('') print(len(devices), 'devices are in a phase', config['deployment_phase'], 'policy.') if len(devices) == 0: print('ERROR: Aborting analysis due to zero devices to analyze.') sys.exit(0) devices_ready = [] devices_not_ready = [] for device in devices: if device['id'] not in event_counts.keys(): device['event_count'] = 0 else: device['event_count'] = event_counts[device['id']] device['last_contact_days_ago'] = ( datetime.datetime.now(datetime.timezone.utc) - parser.parse(device['last_contact'])).days device['days_since_install'] = ( datetime.datetime.now(datetime.timezone.utc) - parser.parse(device['last_registration'])).days device['progression_criteria_violations'] = [] if device['event_count'] > int(config['max_open_event_quantity']): device['progression_criteria_violations'].append( 'More than ' + str(config['max_open_event_quantity']) + ' open events') if device['last_contact_days_ago'] > int( config['max_days_since_last_contact']): device['progression_criteria_violations'].append( 'Offline for more than ' + str(config['max_days_since_last_contact']) + ' days') if device['days_since_install'] < int( config['min_days_since_install']): device['progression_criteria_violations'].append( 'Installed less than ' + str(config['min_days_since_install']) + ' days ago') if len(device['progression_criteria_violations']) > 0: device['ready_to_move_to_next_phase'] = False devices_not_ready.append(device) else: device['ready_to_move_to_next_phase'] = True devices_ready.append(device) print(len(devices_ready), 'devices are ready to move to the next phase.') print( len(devices_not_ready), 'devices are not ready based on violating one or more of the provided criteria.' ) print( excluded_device_count, 'devices in the system were not assessed due to not being in a phase', config['deployment_phase'], 'policy.') #convert data to be exported to dataframes devices_ready_df = pandas.DataFrame(devices_ready) devices_not_ready_df = pandas.DataFrame(devices_not_ready) config_df = pandas.DataFrame(config.items()) search_parameters_df = pandas.DataFrame(search_parameters.items()) suspicious_search_parameters_df = pandas.DataFrame( suspicious_search_parameters.items()) policy_evaluation_results_df = pandas.DataFrame(policy_evaluation_results) #prep for export folder_name = di.create_export_folder() from_deployment_phase = "{:g}".format(float(config['deployment_phase'])) if di.is_server_multitenancy_enabled() and not multiple_msps: server_shortname = re.sub(r'[^a-z0-9]', '', policies[0]['msp_name'].lower()) else: server_shortname = di.fqdn.split(".", 1)[0] file_name = f'deployment_phase_{from_deployment_phase}_progression_readiness_assessment_{datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d_%H.%M")}_UTC_{server_shortname}.xlsx' #export dataframes to Excel format with pandas.ExcelWriter(f'{folder_name}/{file_name}') as writer: devices_ready_df.to_excel(writer, sheet_name='ready_for_next_phase', index=False) devices_not_ready_df.to_excel(writer, sheet_name='not_ready_for_next_phase', index=False) config_df.to_excel(writer, sheet_name='config', index=False) search_parameters_df.to_excel(writer, sheet_name='event_search', index=False) suspicious_search_parameters_df.to_excel( writer, sheet_name='suspicious_event_search', index=False) policy_evaluation_results_df.to_excel(writer, sheet_name='policy_evaluation', index=False) print('') print(f'Results were exported to disk as\n{folder_name}\\{file_name}\n')
def do_warranty_compliance_check(fqdn, key, exclude_empty_policies): di.fqdn = fqdn di.key = key #Get data from server print('INFO: Getting policy data from server') policies = di.get_policies(include_policy_data=True) print('INFO: Getting device data from server') devices = di.get_devices(include_deactivated=False) # Calculate device_count for each policy (how many active devices in policy) # Add device_countfield with initial value zero print('INFO: Calculating device count for each policy') for policy in policies: policy['device_count'] = 0 # Iterate through devices and policies, incrementing device_count appropriately for device in devices: for policy in policies: if policy['id'] == device['policy_id']: policy['device_count'] += 1 if exclude_empty_policies: print( 'INFO: Narrowing policy list to include only those which contain 1 or more activated devices' ) non_empty_policies = [] for policy in policies: if policy['device_count'] > 0: non_empty_policies.append(policy) empty_policy_count = len(policies) - len(non_empty_policies) policies = non_empty_policies else: print( 'INFO: exclude_empty_policies is disabled, therefore proceeding with analysis on all policies' ) #Extract Windows policies print('INFO: Extracting Windows policies to new list windows_policies') windows_policies = [] for policy in policies: if policy['os'] == 'WINDOWS': windows_policies.append(policy) #Iterate through Windows policies, determine compliance or lack thereof, and assign to appropriate list print('INFO: Analyzing policies for compliance') compliant_windows_policies = [] noncompliant_windows_policies = [] for policy in windows_policies: policy[ 'compliant'] = True #initially assume compliant; will change to false if violation(s) identified policy['compliance_violations'] = { } #define dictionary to store details of violation(s) if any if policy['prevention_level'] not in ['HIGH', 'MEDIUM', 'LOW']: policy['compliant'] = False policy['compliance_violations']['prevention_level'] = policy[ 'prevention_level'] if policy['remote_code_injection'] != 'PREVENT': policy['compliant'] = False policy['compliance_violations']['remote_code_injection'] = policy[ 'remote_code_injection'] if policy['arbitrary_shellcode_execution'] != 'PREVENT': policy['compliant'] = False policy['compliance_violations'][ 'arbitrary_shellcode_execution'] = policy[ 'arbitrary_shellcode_execution'] if policy['ransomware_behavior'] != 'PREVENT': policy['compliant'] = False policy['compliance_violations']['ransomware_behavior'] = policy[ 'ransomware_behavior'] #TODO: Add logic to check the following atttributes of the Windows policy: # 1. D-Cloud Services (compliance requires that this be enabled) # 2. Malicious PowerShell Prevention (compliance requires that this be in Prevention) #Both of above require that product make these fields visible via the REST API. Submitted #as FR-166 and FR-167 on 2021-07-06 if policy['compliant'] == True: compliant_windows_policies.append(policy) else: noncompliant_windows_policies.append(policy) #Calculate how many devices are in compliant versus non-compliance policies print('INFO: Counting sum of devices in policies in each category') device_count_compliant_windows_policies = 0 for policy in compliant_windows_policies: device_count_compliant_windows_policies += policy['device_count'] device_count_noncompliant_windows_policies = 0 for policy in noncompliant_windows_policies: device_count_noncompliant_windows_policies += policy['device_count'] #Write results to disk print('INFO: Calculating file and folder names for export') folder_name = di.create_export_folder() file_name = f'warranty_compliance_audit_{datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d_%H.%M")}_UTC.txt' print('INFO: Opening file for writing data to to disk') output = open(f'{folder_name}\{file_name}', 'a') print('INFO: Writing data to disk') output.writelines([ '--------\nDeep Instinct Ransomware Warranty Compliance Check\n', di.fqdn, '\n', datetime.datetime.now( datetime.timezone.utc).strftime("%Y-%m-%d_%H.%M"), ' UTC\n--------\n\n' ]) if exclude_empty_policies: if empty_policy_count > 0: output.writelines([ 'NOTE: Data below excludes ', str(empty_policy_count), ' policies containing 0 activated devices.\n\n' ]) output.writelines([ str(device_count_compliant_windows_policies), ' devices are in a compliant Windows policy.\n' ]) output.writelines([ str(device_count_noncompliant_windows_policies), ' devices are in a non-compliant Windows policy.\n' ]) output.writelines([ '\n', str(len(compliant_windows_policies)), ' Windows policies are compliant:\n\n' ]) output.writelines([ 'msp_id\tmsp_name\tpolicy_id\tpolicy_name\tdevice_count\tcompliance_violations\n' ]) for policy in compliant_windows_policies: output.writelines([ str(policy['msp_id']), '\t', policy['msp_name'], '\t', str(policy['id']), '\t', policy['name'], '\t', str(policy['device_count']), '\t', str(policy['compliance_violations']), '\n' ]) output.writelines([ '\n', str(len(noncompliant_windows_policies)), ' Windows policies are non-compliant:\n\n' ]) output.writelines([ 'msp_id\tmsp_name\tpolicy_id\tpolicy_name\tdevice_count\tcompliance_violations\n' ]) for policy in noncompliant_windows_policies: output.writelines([ str(policy['msp_id']), '\t', policy['msp_name'], '\t', str(policy['id']), '\t', policy['name'], '\t', str(policy['device_count']), '\t', str(policy['compliance_violations']), '\n' ]) print('INFO: Closing file for writing data to to disk') output.close() print('INFO: Done. Results written to', f'{folder_name}\{file_name}')