def set_treatment_manager(treatment: str, treatment_manager: str,
                          finding: Dict[str, FindingType],
                          is_customer_admin: bool, user_mail: str) -> str:
    if treatment == 'IN PROGRESS':
        if not is_customer_admin:
            treatment_manager = user_mail
        if treatment_manager:
            project_users = project_dal.get_users(
                str(finding.get('project_name')))
            customer_roles = ['customer', 'customeradmin']
            customer_users = \
                [user for user in project_users
                    if user_domain.get_data(user, 'role') in customer_roles]
            if treatment_manager not in customer_users:
                raise GraphQLError('Invalid treatment manager')
        else:
            raise GraphQLError('Invalid treatment manager')
    elif treatment == 'ACCEPTED':
        treatment_manager = user_mail
    elif treatment == 'ACCEPTED_UNDEFINED':
        last_state = cast(List[Dict[str, str]],
                          finding.get('historic_treatment'))[-1]
        if last_state['acceptance_status'] == 'SUBMITTED':
            treatment_manager = user_mail
        else:
            treatment_manager = last_state['user']
    return treatment_manager
def send_updated_vuln_email(finding_id: str, user_email: str,
                            data_vuln: Dict[str, str],
                            updated_vuln_description: str):
    """Send email when vulnerabilities were updated"""
    if len(updated_vuln_description) == 1:
        number_vuln = 'vulnerability'
    else:
        number_vuln = 'vulnerabilities'
    project_name = \
        str(finding_dal.get_attributes(finding_id, ['project_name']).get('project_name')).lower()
    recipients = project_dal.get_users(project_name, True)

    finding_name = finding_dal.get_attributes(finding_id,
                                              ['finding']).get('finding')

    email_send_thread = threading.Thread(
        name='Updated vulnerabilities email thread',
        target=send_mail_updated_vulns,
        args=(recipients, {
            'user_email': user_email,
            'finding_name': finding_name,
            'number_vuln': number_vuln,
            'project': project_name.capitalize(),
            'treatment': str(data_vuln['treatment']).lower(),
            'updated_vuln_description': updated_vuln_description,
            'justification': data_vuln.get('treatment_justification', ''),
            'treatment_manager': data_vuln.get('treatment_manager', ''),
        }))

    email_send_thread.start()
def request_verification(finding_id: str, user_email: str, user_fullname: str,
                         justification: str, vuln_ids: List[str]) -> bool:
    finding = finding_dal.get_finding(finding_id)
    vulnerabilities = get_by_ids(finding_id, vuln_ids)
    vulnerabilities = [
        validate_requested_verification(vuln) for vuln in vulnerabilities
    ]
    vulnerabilities = [validate_closed(vuln) for vuln in vulnerabilities]
    if not vulnerabilities:
        raise VulnNotFound()
    comment_id = int(round(time() * 1000))
    tzn = pytz.timezone(settings.TIME_ZONE)  # type: ignore
    today = datetime.now(tz=tzn).today().strftime('%Y-%m-%d %H:%M:%S')
    historic_verification = cast(List[Dict[str, Union[str, int, List[str]]]],
                                 finding.get('historic_verification', []))
    historic_verification.append({
        'date': today,
        'user': user_email,
        'status': 'REQUESTED',
        'comment': comment_id,
        'vulns': vuln_ids
    })
    update_finding = finding_dal.update(
        finding_id, {'historic_verification': historic_verification})
    comment_data = {
        'comment_type': 'verification',
        'content': justification,
        'created': today,
        'email': user_email,
        'finding_id': int(finding_id),
        'fullname': user_fullname,
        'modified': today,
        'parent': 0,
    }
    comment_dal.create(comment_id, comment_data)
    update_vulns = [
        vuln_dal.request_verification(vuln) for vuln in vulnerabilities
    ]
    if all(update_vulns) and update_finding:
        finding_utils.send_remediation_email(
            user_email, finding_id, str(finding.get('finding', '')),
            str(finding.get('project_name', '')), justification)
        project_users = project_dal.get_users(
            str(finding.get('project_name', '')))
        notifications.notify_mobile(
            project_users, t('notifications.remediated.title'),
            t('notifications.remediated.content',
              finding=finding.get('finding'),
              project=str(finding.get('project_name', '')).upper()))
    else:
        rollbar.report_message('Error: An error occurred remediating', 'error')

    return all(update_vulns)
def verify_finding(finding_id: str, user_email: str, justification: str,
                   user_fullname: str) -> bool:
    success = False
    finding = get_finding(finding_id)
    project_name = str(finding.get('projectName', ''))
    finding_name = str(finding.get('finding', ''))
    historic_verification = cast(List[Dict[str, Union[str, int, datetime]]],
                                 finding.get('historicVerification', [{}]))
    if historic_verification[-1].get('status') == 'REQUESTED' and\
       not historic_verification[-1].get('vulns', []):
        tzn = pytz.timezone(settings.TIME_ZONE)  # type: ignore
        today = datetime.now(tz=tzn).today().strftime('%Y-%m-%d %H:%M:%S')
        comment_id = int(round(time() * 1000))
        new_state: Dict[str, Union[str, int, datetime]] = {
            'date': today,
            'user': user_email,
            'status': 'VERIFIED',
            'comment': comment_id,
        }
        comment_data = {
            'user_id': comment_id,
            'comment_type': 'verification',
            'content': justification,
            'fullname': user_fullname,
            'parent': historic_verification[-1].get('comment', 0),
        }
        historic_verification.append(new_state)
        add_comment(user_email,
                    comment_data,
                    finding_id,
                    is_remediation_comment=True)
        success = finding_dal.update(
            finding_id, {'historic_verification': historic_verification})

        if success:
            vuln_domain.update_vulnerabilities_date(user_email, finding_id)
            finding_utils.send_finding_verified_email(finding_id, finding_name,
                                                      project_name)
            project_users = project_dal.get_users(project_name)
            notifications.notify_mobile(
                project_users, t('notifications.verified.title'),
                t('notifications.verified.content',
                  finding=finding_name,
                  project=project_name.upper()))
        else:
            rollbar.report_message(
                'Error: An error occurred verifying the finding', 'error')
    else:
        raise NotVerificationRequested()

    return success
def send_finding_verified_email(finding_id: str, finding_name: str, project_name: str):
    recipients = project_dal.get_users(project_name)

    base_url = 'https://fluidattacks.com/integrates/dashboard#!'
    email_send_thread = threading.Thread(
        name='Verified finding email thread',
        target=send_mail_verified_finding,
        args=(recipients, {
            'project': project_name,
            'finding_name': finding_name,
            'finding_url':
                base_url + '/project/{project!s}/{finding!s}/tracking'
            .format(project=project_name, finding=finding_id),
            'finding_id': finding_id
        }))

    email_send_thread.start()
示例#6
0
def get_email_recipients(project_name: str,
                         comment_type: Union[str, bool]) -> List[str]:
    project_users = project_dal.get_users(project_name)
    recipients: List[str] = []

    approvers = FI_MAIL_REVIEWERS.split(',')
    recipients += approvers

    if comment_type == 'observation':
        analysts = [
            user for user in project_users
            if user_domain.get_data(user, 'role') == 'analyst'
        ]
        recipients += analysts
    else:
        recipients += project_users

    return recipients
def verify(info, finding_id: str, vulnerabilities: List[Dict[str, str]],
           closed_vulns: List[str], date) -> List[bool]:
    finding = finding_dal.get_finding(finding_id)
    success = [
        update_vuln_state(info, [vuln], {'state': 'closed'}, finding_id, date)
        for vuln in vulnerabilities if vuln.get('UUID') in closed_vulns
    ]
    finding_utils.send_finding_verified_email(
        finding_id, str(finding.get('finding', '')),
        str(finding.get('project_name', '')))
    project_users = project_dal.get_users(str(finding.get('project_name', '')))
    notifications.notify_mobile(
        project_users, t('notifications.verified.title'),
        t('notifications.verified.content',
          finding=str(finding.get('finding', '')),
          project=str(finding.get('project_name', '')).upper()))

    return success
def send_remediation_email(user_email: str, finding_id: str, finding_name: str,
                           project_name: str, justification: str):
    recipients = project_dal.get_users(project_name)
    base_url = 'https://fluidattacks.com/integrates/dashboard#!'
    email_send_thread = threading.Thread(
        name='Remediate finding email thread',
        target=send_mail_remediate_finding,
        args=(recipients, {
            'project': project_name.lower(),
            'finding_name': finding_name,
            'finding_url':
                base_url + '/project/{project!s}/{finding!s}/description'
            .format(project=project_name, finding=finding_id),
            'finding_id': finding_id,
            'user_email': user_email,
            'solution_description': justification
        }))

    email_send_thread.start()
def send_accepted_email(finding: Dict[str, FindingType], justification: str):
    project_name = str(finding.get('projectName', ''))
    finding_name = str(finding.get('finding', ''))
    last_historic_treatment = cast(List[Dict[str, str]], finding.get('historicTreatment'))[-1]
    recipients = project_dal.get_users(project_name)
    treatment = 'Accepted'
    if last_historic_treatment['treatment'] == 'ACCEPTED_UNDEFINED':
        treatment = 'Indefinitely accepted'
    email_send_thread = threading.Thread(
        name='Accepted finding email thread',
        target=send_mail_accepted_finding,
        args=(recipients, {
            'finding_name': finding_name,
            'finding_id': finding.get('finding_id'),
            'project': project_name.capitalize(),
            'justification': justification,
            'user_email': last_historic_treatment['user'],
            'treatment': treatment
        }))

    email_send_thread.start()
示例#10
0
def send_comment_mail(comment_data: CommentType,
                      entity_name: str,
                      user_mail: str,
                      comment_type: str = '',
                      entity: Union[str, Dict[str, FindingType], EventType,
                                    ProjectType] = ''):
    parent = comment_data['parent']
    base_url = 'https://fluidattacks.com/integrates/dashboard#!'
    email_context = {
        'user_email': user_mail,
        'comment': str(comment_data['content']).replace('\n', ' '),
        'comment_type': comment_type,
        'parent': parent,
    }
    if entity_name == 'finding':
        finding: Dict[str, FindingType] = cast(Dict[str, FindingType], entity)
        project_name = str(finding.get('projectName', ''))
        recipients = get_email_recipients(project_name, comment_type)

        is_draft = 'releaseDate' in finding
        email_context['finding_id'] = str(finding.get('findingId', ''))
        email_context['finding_name'] = str(finding.get('finding', ''))
        comment_url = (
            base_url +
            '/project/{project}/{finding_type}/{id}/{comment_type}s'.format(
                comment_type=comment_type,
                finding_type='findings' if is_draft else 'drafts',
                id=finding.get('findingId'),
                project=project_name))

    elif entity_name == 'event':
        event = cast(EventType, entity)
        event_id = str(event.get('event_id', ''))
        project_name = str(event.get('project_name', ''))
        recipients = project_dal.get_users(project_name, True)
        email_context['finding_id'] = event_id
        email_context['finding_name'] = f'Event #{event_id}'
        comment_url = ('https://fluidattacks.com/integrates/dashboard#!/'
                       f'project/{project_name}/events/{event_id}/comments')

    elif entity_name == 'project':
        project_name = str(entity)
        recipients = get_email_recipients(project_name, True)
        comment_url = (
            base_url +
            '/project/{project!s}/comments'.format(project=project_name))

    email_context['comment_url'] = comment_url
    email_context['project'] = project_name

    recipients_customers = [
        recipient for recipient in recipients if user_domain.get_data(
            recipient, 'role') in ['customer', 'customeradmin']
    ]
    recipients_not_customers = [
        recipient for recipient in recipients if user_domain.get_data(
            recipient, 'role') not in ['customer', 'customeradmin']
    ]

    email_context_customers = email_context.copy()
    if user_domain.get_data(user_mail,
                            'role') not in ['customer', 'customeradmin']:
        email_context_customers['user_email'] = \
            'Hacker at ' + str(user_domain.get_data(user_mail, 'company')).capitalize()
    email_send_thread = threading.Thread(
        name='New {} email thread'.format(entity_name),
        target=send_mail_comment,
        args=([recipients_not_customers,
               recipients_customers], [email_context,
                                       email_context_customers]))
    email_send_thread.start()
def get_users(project_name: str, active: bool = True) -> List[str]:
    return project_dal.get_users(project_name, active)