def delete_vulnerability(finding_id: str, vuln_id: str, justification: str, user_email: str) -> bool: vulnerability = vuln_dal.get(finding_id, uuid=vuln_id) success = False if vulnerability and vulnerability[0].get('historic_state'): all_states = cast(List[Dict[str, str]], vulnerability[0].get('historic_state')) current_state = all_states[-1].get('state') if current_state == 'open': tzn = pytz.timezone(settings.TIME_ZONE) # type: ignore current_day = datetime.now( tz=tzn).today().strftime('%Y-%m-%d %H:%M:%S') new_state = { 'date': current_day, 'state': 'DELETED', 'justification': justification, 'analyst': user_email } success = vuln_dal.update_state( finding_id, str(vulnerability[0].get('UUID', '')), 'historic_state', [new_state], cast(List[Dict[str, str]], vulnerability)) return success
def test_get_open_vulnerability_date(self): closed_vulnerability = { 'specific': 'phone', 'finding_id': '422286126', 'UUID': '80d6a69f-a376-46be-98cd-2fdedcffdcc0', 'treatment_manager': '*****@*****.**', 'historic_state': [{ 'date': '2019-01-08 16:01:26', 'state': 'closed' }], 'treatment_justification': 'Test 123', 'vuln_type': 'inputs', 'treatment': 'IN PROGRESS', 'where': 'https://example.com', 'analyst': '*****@*****.**' } open_vulnerability = vuln_dal.get( finding_id='422286126', vuln_type='inputs', where='https://example.com', uuid='80d6a69f-a376-46be-98cd-2fdedcffdcc0')[0] test_data = get_open_vulnerability_date(open_vulnerability) expected_output = datetime(2018, 9, 28).date() assert test_data == expected_output test_data = get_open_vulnerability_date(closed_vulnerability) assert test_data is None
def add_vuln_to_dynamo(item: Dict[str, str], specific: str, vuln: str, finding_id: str, info) -> bool: """Add vulnerability to dynamo.""" historic_state = [] last_finding_state = cast( List[Dict[str, str]], finding_dal.get_finding(finding_id)['historic_treatment'])[-1] where = item.get('where', '') vulnerability = cast( List[Dict[str, str]], vuln_dal.get(finding_id, vuln_type=vuln, where=where, specific=specific)) response = False tzn = pytz.timezone(settings.TIME_ZONE) # type: ignore current_day = datetime.now(tz=tzn).today().strftime('%Y-%m-%d %H:%M:%S') user_data = cast(UserType, util.get_jwt_content(info.context)) email = str(user_data['user_email']) if vulnerability: response = update_vuln_state(info, vulnerability, item, finding_id, current_day) else: data: Dict[str, FindingType] = {} data['vuln_type'] = vuln data['where'] = where data['specific'] = specific data['finding_id'] = finding_id data['UUID'] = str(uuid.uuid4()) data['treatment'] = 'NEW' if last_finding_state['treatment'] != 'NEW': data['treatment_manager'] = last_finding_state.get('user', '') if item.get('state'): if util.is_api_token(user_data): historic_state.append({ 'date': current_day, 'state': item.get('state', ''), 'origin': item.get('origin', ''), 'approval_status': 'PENDING', 'analyst': 'api-{email}'.format(email=email) }) else: historic_state.append({ 'date': current_day, 'state': item.get('state', ''), 'analyst': email }) data['historic_state'] = historic_state response = vuln_dal.create(data) else: util.cloudwatch_log( info.context, 'Security: Attempted to add vulnerability without state') return response
def update_approval_status(finding_id: str, vuln_id: str, approval_status: str) -> bool: """ Update vulnerability approval state """ vulnerability = cast(List[Dict[str, str]], vuln_dal.get(finding_id, uuid=vuln_id)) response = False if vulnerability: historic_state = cast(List[Dict[str, str]], vulnerability[0].get('historic_state')) last_state = historic_state[-1] del vulnerability[0]['historic_state'] if last_state.get('approval_status') == 'PENDING': if approval_status: response = \ approve_vulnerability(finding_id, historic_state, last_state, vulnerability) else: response = reject_vulnerability(finding_id, historic_state, vulnerability, vuln_id) else: # vuln approval_status is different than pending pass else: # vuln not found pass return response
def get(finding_id: str, vuln_id: str): vuln = cast(List[Dict[str, FindingType]], vuln_dal.get(finding_id, uuid=vuln_id)) first_vuln = cast(Dict[str, List[Dict[str, str]]], vuln[0]) if not vuln: raise VulnNotFound() if first_vuln.get('historic_state', [{}])[-1].get('state', '') == 'DELETED': raise VulnNotFound() return vuln[0]
def test_is_vulnerability_closed(self): closed_vulnerability = { 'specific': 'phone', 'finding_id': '422286126', 'UUID': '80d6a69f-a376-46be-98cd-2fdedcffdcc0', 'treatment_manager': '*****@*****.**', 'historic_state': [{ 'date': '2018-09-28 10:32:58', 'state': 'open' }, { 'date': '2019-01-08 16:01:26', 'state': 'closed' }], 'treatment_justification': 'Test 123', 'vuln_type': 'inputs', 'treatment': 'IN PROGRESS', 'where': 'https://example.com', 'analyst': '*****@*****.**' } open_vulnerability = vuln_dal.get( finding_id='422286126', vuln_type='inputs', where='https://example.com', uuid='80d6a69f-a376-46be-98cd-2fdedcffdcc0')[0] assert is_vulnerability_closed(closed_vulnerability) assert not is_vulnerability_closed(open_vulnerability)
def update_treatment_vuln(vulnerabilities: List[str], finding_id: str, updated_values: Dict[str, FindingType], info) -> bool: if updated_values.get('acceptance_date'): del updated_values['acceptance_date'] del updated_values['finding_id'] user_email = util.get_jwt_content(info.context)['user_email'] updated_vuln_description = [] for vulnerability in vulnerabilities: vuln_info = cast(List[Dict[str, FindingType]], vuln_dal.get(finding_id, uuid=vulnerability)) new_info = copy.copy(updated_values) if new_info.get('tag'): new_info['tag'] = cast(List[str], vuln_info[0].get('tag', [])) for tag in str(updated_values['tag']).split(','): validations.validate_field(cast(List[str], tag)) if tag.strip(): cast(List[str], new_info['tag']).append(tag.strip()) new_info['tag'] = cast( # conflict between mypy and pylint -> 'github.com/PyCQA/pylint/issues/2377' # pylint: disable=unsubscriptable-object List[str], list(set(cast(Iterable[Collection[str]], new_info['tag'])))) new_info['tag'] = [ html.unescape(tag) for tag in cast(List[str], new_info['tag']) ] new_info = { key: None if not value else value for key, value in new_info.items() } new_info = { util.camelcase_to_snakecase(k): new_info.get(k) for k in new_info } result_update_vuln = \ vuln_dal.update(finding_id, vulnerability, new_info) if 'lines' in str(vuln_info[0]['vuln_type']): where = 'Path' specific = 'Line' elif 'ports' in str(vuln_info[0]['vuln_type']): where = 'Host' specific = 'Port' else: where = 'URL' specific = 'Field' mail_description =\ "<b>{where}:</b>{where_info} \ <b>{specific}:</b> {specific_info}"\ .format(where=where, where_info=vuln_info[0]['where'], specific_info=vuln_info[0]['specific'], specific=specific) updated_vuln_description.append( {'updated_vuln_description': mail_description}) if not result_update_vuln: util.cloudwatch_log( info.context, 'Security: Attempted to update vulnerability\ :{id} from finding:{finding}'.format(id=vulnerability, finding=finding_id)) return False util.cloudwatch_log( info.context, 'Security: Updated vulnerability:\ {id} from finding:{finding} succesfully'.format(id=vulnerability, finding=finding_id)) if updated_values.get('treatment') != 'NEW': send_updated_vuln_email(finding_id, user_email, cast(Dict[str, str], updated_values), str(updated_vuln_description)) return True