コード例 #1
0
ファイル: ticket.py プロジェクト: ovh/cerberus-core
def delay_jobs(ticket=None, delay=None, back=True):
    """
        Delay pending jobs for given `abuse.models.Ticket`

        :param `abuse.models.Ticket` ticket: The Cerberus ticket
        :param int delay: Postpone duration
        :param bool back: In case of unpause, reschedule jobs with effectively elapsed time
    """
    if not delay:
        Logger.error(unicode('Missing delay. Skipping...'))
        return

    if not isinstance(ticket, Ticket):
        try:
            ticket = Ticket.objects.get(id=ticket)
        except (AttributeError, ObjectDoesNotExist, TypeError, ValueError):
            Logger.error(unicode('Ticket %d cannot be found in DB. Skipping...' % (ticket)))
            return

    # a job is here a tuple (Job instance, datetime instance)
    pending_jobs = {job[0].id: job for job in utils.scheduler.get_jobs(until=timedelta(days=7), with_times=True)}

    for job in ticket.jobs.all():
        if pending_jobs.get(job.asynchronousJobId):
            current_date = pending_jobs[job.asynchronousJobId][1]
            new_date = current_date - delay if back else current_date + delay
            utils.scheduler.change_execution_time(
                pending_jobs[job.asynchronousJobId][0],
                new_date
            )
コード例 #2
0
ファイル: database.py プロジェクト: ovh/cerberus-core
def _generates_onclose_kpi(ticket):
    """
        Kpi on ticket close
    """
    try:
        ImplementationFactory.instance.get_singleton_of('KPIServiceBase').close_ticket(ticket)
    except KPIServiceException as ex:
        Logger.error(unicode('Error while pushing KPI - %s' % (ex)))
コード例 #3
0
ファイル: action.py プロジェクト: ovh/cerberus-core
def __cancel_by_status(ticket):
    """
        Action cancelled because of ticket status
    """
    current_job = get_current_job()
    Logger.error(unicode('Ticket %d is %s, Skipping...' % (ticket.id, ticket.status)))
    ServiceActionJob.objects.filter(
        asynchronousJobId=current_job.id
    ).update(
        status='cancelled',
        comment='ticket is %s' % (ticket.status)
    )
コード例 #4
0
ファイル: report.py プロジェクト: ovh/cerberus-core
def __index_report_to_searchservice(parsed_email, filename, reports_id):
    """ Index a report to the SearchService
    """
    try:
        Logger.debug(unicode('Pushing email %s document to SearchService' % (filename)))
        ImplementationFactory.instance.get_singleton_of('SearchServiceBase').index_email(
            parsed_email,
            filename,
            reports_id
        )
    except SearchServiceException as ex:
        # Not fatal => don't stop current routine
        Logger.error(unicode('Unable to index mail %s in SearchService -> %s' % (filename, ex)))
コード例 #5
0
ファイル: ticket.py プロジェクト: ovh/cerberus-core
def _get_ip_for_action(ticket):
    """
        Extract and check IP address
    """
    # Get ticket IP(s)
    reports = ticket.reportTicket.all()
    ips_on_ticket = [itm.ip for rep in reports for itm in rep.reportItemRelatedReport.filter(~Q(ip=None), itemType='IP')]
    ips_on_ticket.extend([itm.fqdnResolved for rep in reports for itm in rep.reportItemRelatedReport.filter(~Q(fqdnResolved=None), itemType__in=['FQDN', 'URL'])])
    ips_on_ticket = list(set(ips_on_ticket))

    if len(ips_on_ticket) != 1:
        Logger.error(unicode('Multiple or no IP on this ticket'))
        return

    return ips_on_ticket[0]
コード例 #6
0
ファイル: database.py プロジェクト: ovh/cerberus-core
def _genereates_oncreate_kpi(ticket):
    """
        Kpi on ticket creation
    """
    Logger.debug(
        unicode('new ticket %d' % (ticket.id)),
        extra={
            'ticket': ticket.id,
            'action': 'new ticket',
            'public_id': ticket.publicId
        }
    )

    try:
        ImplementationFactory.instance.get_singleton_of('KPIServiceBase').new_ticket(ticket)
    except KPIServiceException as ex:
        Logger.error(unicode('Error while pushing KPI - %s' % (ex)))
コード例 #7
0
ファイル: database.py プロジェクト: ovh/cerberus-core
def log_new_report(report):
    """
        Log report creation
    """
    Logger.debug(
        unicode('New report %d' % (report.id)),
        extra={
            'from': report.provider.email,
            'action': 'new report',
            'report': report.id,
        }
    )

    if ImplementationFactory.instance.is_implemented('KPIServiceBase'):
        try:
            ImplementationFactory.instance.get_singleton_of('KPIServiceBase').new_report(report)
        except KPIServiceException as ex:
            Logger.error(unicode('Error while pushing KPI - %s' % (ex)))
コード例 #8
0
ファイル: phishing.py プロジェクト: ovh/cerberus-core
def close_because_all_down(report=None, denied_by=None):
    """
        Create and close a ticket when all report's items are down

        :param `abuse.models.Report` report: A Cerberus `abuse.models.Report` instance
        :param int denied_by: The id of the `abuse.models.User` who takes the decision to close the ticket
    """
    if not isinstance(report, Report):
        try:
            report = Report.objects.get(id=report)
        except (AttributeError, ObjectDoesNotExist, TypeError, ValueError):
            Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report)))
            return

    if not report.ticket:
        report.ticket = common.create_ticket(report, denied_by)
        report.save()

    # Add temp proof(s) for mail content
    temp_proofs = []
    if not report.ticket.proof.count():
        temp_proofs = common.get_temp_proofs(report.ticket)

    # Send email to Provider
    try:
        validate_email(report.provider.email.strip())
        Logger.info(unicode('Sending email to provider'))
        __send_email(report.ticket, report.provider.email, settings.CODENAMES['no_more_content'])
        report.ticket.save()
        Logger.info(unicode('Mail sent to provider'))
        ImplementationFactory.instance.get_singleton_of('MailerServiceBase').close_thread(report.ticket)

        # Delete temp proof(s)
        for proof in temp_proofs:
            Proof.objects.filter(id=proof.id).delete()
    except (AttributeError, TypeError, ValueError, ValidationError):
        pass

    # Closing ticket and add tags
    common.close_ticket(report, resolution_codename=settings.CODENAMES['no_more_content'])
    report.ticket.tags.remove(Tag.objects.get(name=settings.TAGS['phishing_autoreopen']))
    report.ticket.tags.add(Tag.objects.get(name=settings.TAGS['phishing_autoclosed']))
    Logger.info(unicode('Ticket %d and report %d closed' % (report.ticket.id, report.id)))
コード例 #9
0
ファイル: ticket.py プロジェクト: ovh/cerberus-core
def mass_contact(ip_address=None, category=None, campaign_name=None, email_subject=None, email_body=None, user_id=None):
    """
        Try to identify customer based on `ip_address`, creates Cerberus ticket
        then send email to customer and finally close ticket.

        The use case is: a trusted provider sent you a list of vulnerable DNS servers (DrDOS amp) for example.
        To prevent abuse on your network, you notify customer of this vulnerability.

        :param str ip_address: The IP address
        :param str category: The category of the abuse
        :param str campaign_name: The name if the "mass-conctact" campaign
        :param str email_subject: The subject of the email to send to defendant
        :param str email_body: The body of the email to send to defendant
        :param int user_id: The id of the Cerberus `abuse.models.User` who created the campaign
    """
    # Check params
    _, _, _, values = inspect.getargvalues(inspect.currentframe())
    if not all(values.values()):
        Logger.error(unicode('invalid parameters submitted %s' % str(values)))
        return

    try:
        validate_ipv46_address(ip_address)
    except (TypeError, ValidationError):
        Logger.error(unicode('invalid ip addresses submitted'))
        return

    # Get Django model objects
    try:
        category = Category.objects.get(name=category)
        user = User.objects.get(id=user_id)
    except (AttributeError, ObjectDoesNotExist, TypeError):
        Logger.error(unicode('invalid user or category'))
        return

    # Identify service for ip_address
    try:
        services = ImplementationFactory.instance.get_singleton_of('CustomerDaoBase').get_services_from_items(ips=[ip_address])
        schema.valid_adapter_response('CustomerDaoBase', 'get_services_from_items', services)
    except CustomerDaoException as ex:
        Logger.error(unicode('Exception while identifying defendants for ip %s -> %s ' % (ip_address, str(ex))))
        raise CustomerDaoException(ex)

    # Create report/ticket
    if services:
        Logger.debug(unicode('creating report/ticket for ip address %s' % (ip_address)))
        with pglocks.advisory_lock('cerberus_lock'):
            __create_contact_tickets(services, campaign_name, ip_address, category, email_subject, email_body, user)
        return True
    else:
        Logger.debug(unicode('no service found for ip address %s' % (ip_address)))
        return False
コード例 #10
0
ファイル: report.py プロジェクト: ovh/cerberus-core
def reparse_validated(report_id=None, user_id=None):
    """
        Reparse now validated `abuse.models.Report`

        :param int report_id: A Cerberus `abuse.models.Report` id
        :param int user_id: A Cerberus `abuse.models.User` id
    """
    try:
        report = Report.objects.get(id=report_id)
        user = User.objects.get(id=user_id)
    except (ObjectDoesNotExist, ValueError):
        Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report_id)))
        return

    if not report.defendant or not report.service:
        _create_closed_ticket(report, user)
    else:
        _reinject_validated(report, user)

    Logger.error(unicode('Report %d successfully processed' % (report_id)))
コード例 #11
0
ファイル: ticket.py プロジェクト: ovh/cerberus-core
def cancel_rq_scheduler_jobs(ticket_id=None, status='answered'):
    """
        Cancel all rq scheduler jobs for given `abuse.models.Ticket`

        :param int ticket_id: The id of the `abuse.models.Ticket`
        :param str status: The `abuse.models.Ticket.TICKET_STATUS' reason of the cancel
    """
    try:
        ticket = Ticket.objects.get(id=ticket_id)
    except (AttributeError, ObjectDoesNotExist, TypeError, ValueError):
        Logger.error(unicode('Ticket %d cannot be found in DB. Skipping...' % (ticket)))
        return

    for job in utils.scheduler.get_jobs():
        if job.func_name in ASYNC_JOB_TO_CANCEL and job.kwargs['ticket_id'] == ticket.id:
            utils.scheduler.cancel(job.id)

    for job in ticket.jobs.all():
        if job.asynchronousJobId in utils.scheduler:
            utils.scheduler.cancel(job.asynchronousJobId)
            job.status = 'cancelled by %s' % status
            job.save()
コード例 #12
0
ファイル: ticket.py プロジェクト: ovh/cerberus-core
def timeout(ticket_id=None):
    """
        If ticket timeout , apply action on service (if defendant not internal/VIP) and ticket is not assigned

        :param int ticket_id: The id of the Cerberus `abuse.models.Ticket`
    """
    try:
        ticket = Ticket.objects.get(id=ticket_id)
    except (AttributeError, ObjectDoesNotExist, ValueError):
        Logger.error(unicode('Ticket %d cannot be found in DB. Skipping...' % (ticket_id)))
        return

    if not _check_timeout_ticket_conformance(ticket):
        return

    action = ImplementationFactory.instance.get_singleton_of('ActionServiceBase').get_action_for_timeout(ticket)
    if not action:
        Logger.error(unicode('Ticket %d service %s: action not found, exiting ...' % (ticket_id, ticket.service.componentType)))
        return

    # Maybe customer fixed, closing ticket
    if ticket.category.name.lower() == 'phishing' and phishing.is_all_down_for_ticket(ticket):
        Logger.info(unicode('All items are down for ticket %d, closing ticket' % (ticket_id)))
        close_ticket(ticket, reason=settings.CODENAMES['fixed_customer'], service_blocked=False)
        return

    # Getting ip for action
    ip_addr = _get_ip_for_action(ticket)
    if not ip_addr:
        Logger.error(unicode('Error while getting IP for action, exiting'))
        ticket.status = ticket.previousStatus
        ticket.status = 'ActionError'
        database.log_action_on_ticket(
            ticket=ticket,
            action='change_status',
            previous_value=ticket.previousStatus,
            new_value=ticket.status
        )
        comment = Comment.objects.create(user=BOT_USER, comment='None or multiple ip addresses for this ticket')
        TicketComment.objects.create(ticket=ticket, comment=comment)
        database.log_action_on_ticket(
            ticket=ticket,
            action='add_comment'
        )
        ticket.save()
        return

    # Apply action
    service_action_job = _apply_timeout_action(ticket, ip_addr, action)
    if not service_action_job.result:
        Logger.debug(unicode('Error while executing service action, exiting'))
        return

    Logger.info(unicode('All done, sending close notification to provider(s)'))
    ticket = Ticket.objects.get(id=ticket.id)

    # Closing ticket
    close_ticket(ticket, reason=settings.CODENAMES['fixed'], service_blocked=True)
コード例 #13
0
ファイル: ticket.py プロジェクト: ovh/cerberus-core
def _check_timeout_ticket_conformance(ticket):

    if not ticket.defendant or not ticket.service:
        Logger.error(unicode('Ticket %d is invalid (no defendant/service), skipping...' % (ticket.id)))
        return False

    if ticket.status.lower() in ['closed', 'answered']:
        Logger.error(unicode('Ticket %d is invalid (no defendant/service or not Alarm), Skipping...' % (ticket.id)))
        return False

    if ticket.category.name.lower() not in ['phishing', 'copyright']:
        Logger.error(unicode('Ticket %d is in wrong category (%s, Skipping...' % (ticket.id, ticket.category.name)))
        return False

    if ticket.treatedBy:
        Logger.error(unicode('Ticket is %d assigned, skipping' % (ticket.id)))
        return False

    if ticket.jobs.count():
        Logger.error(unicode('Ticket %d has existing jobs, exiting ...' % (ticket.id)))
        return False

    return True
コード例 #14
0
ファイル: action.py プロジェクト: ovh/cerberus-core
def apply_then_close(ticket_id=None, action_id=None, ip_addr=None, resolution_id=None, user_id=None):
    """
        Action on service then close

        :param int ticket_id: The id of the Cerberus `Ticket`
        :param int action_id: The id of the Cerberus `ServiceAction`
        :param str ip_addr: The ip address
        :param int resolution_id: The id of the Cerberus `Resolution`
        :param int user_id: The id of the Cerberus `User`
    """
    # Checking conformance
    if not all((ticket_id, action_id, resolution_id, user_id)):
        msg = 'Invalid parameters submitted [ticket_id=%d, action_id=%s, resolution_id=%s, user_id=%s]'
        Logger.error(unicode(msg % (ticket_id, action_id, resolution_id, user_id)))
        return

    # Apply action
    applied = apply_action(ticket_id, action_id, ip_addr, user_id)
    if not applied:
        return

    # Closing ticket and updating ticket info
    ticket = Ticket.objects.get(id=ticket_id)
    user = User.objects.get(id=user_id)
    __close_ticket(ticket, resolution_id)
    database.log_action_on_ticket(
        ticket=ticket,
        action='change_status',
        user=user,
        previous_value=ticket.previousStatus,
        new_value=ticket.status,
        close_reason=ticket.resolution.codename
    )
    ticket.resolution_id = resolution_id
    ticket.save()

    Logger.info(unicode('Ticket %d processed. Next !' % (ticket_id)))
コード例 #15
0
ファイル: ticket.py プロジェクト: ovh/cerberus-core
def check_mass_contact_result(result_campaign_id=None, jobs=None):
    """
        Check "mass-contact" campaign jobs's result

        :param int result_campaign_id: The id of the `abuse.models.MassContactResult`
        :param list jobs: The list of associated Python-Rq jobs id
    """
    # Check params
    _, _, _, values = inspect.getargvalues(inspect.currentframe())
    if not all(values.values()) or not isinstance(jobs, list):
        Logger.error(unicode('invalid parameters submitted %s' % str(values)))
        return

    if not isinstance(result_campaign_id, MassContactResult):
        try:
            campaign_result = MassContactResult.objects.get(id=result_campaign_id)
        except (AttributeError, ObjectDoesNotExist, TypeError, ValueError):
            Logger.error(unicode('MassContactResult %d cannot be found in DB. Skipping...' % (result_campaign_id)))
            return

    result = []
    for job_id in jobs:
        job = utils.default_queue.fetch_job(job_id)
        if not job:
            continue
        while job.status.lower() == 'queued':
            sleep(0.5)
        result.append(job.result)

    count = Counter(result)
    campaign_result.state = 'Done'
    campaign_result.matchingCount = count[True]
    campaign_result.notMatchingCount = count[False]
    campaign_result.failedCount = count[None]
    campaign_result.save()
    Logger.info(unicode('MassContact campaign %d finished' % (campaign_result.campaign.id)))
コード例 #16
0
ファイル: action.py プロジェクト: ovh/cerberus-core
def apply_if_no_reply(ticket_id=None, action_id=None, ip_addr=None, resolution_id=None, user_id=None, close=False):
    """
        Action if no reply from customer

        :param int ticket_id: The id of the Cerberus `Ticket`
        :param int action_id: The id of the Cerberus `ServiceAction`
        :param str ip_addr: The ip address
        :param int resolution_id: The id of the Cerberus `Resolution`
        :param int user_id: The id of the Cerberus `User`
        :param bool close: If the ticket has to be closed after action
    """
    # Checking conformance
    if not all((ticket_id, action_id, user_id)):
        Logger.error(unicode(
            'Invalid parameters [ticket_id=%s, action_id=%s, user_id=%s]' % (ticket_id, action_id, user_id)
        ))
        return

    if close and not resolution_id:
        Logger.error(unicode('Close requested but no resolution submitted'))
        return

    if resolution_id and not Resolution.objects.filter(id=resolution_id).exists():
        Logger.error(unicode('Ticket resolution %d not found, Skipping...' % (resolution_id)))
        return

    # Apply action
    applied = apply_action(ticket_id, action_id, ip_addr, user_id)
    if not applied:
        return

    # Updating ticket info
    ticket = Ticket.objects.get(id=ticket_id)
    user = User.objects.get(id=user_id)
    ticket.previousStatus = ticket.status
    ticket.snoozeDuration = None
    ticket.snoozeStart = None

    close_reason = None
    if close and resolution_id:
        __close_ticket(ticket, resolution_id)
        close_reason = ticket.resolution.codename
    else:
        ticket.status = 'Alarm'

    ticket.save()
    database.log_action_on_ticket(
        ticket=ticket,
        action='change_status',
        user=user,
        previous_value=ticket.previousStatus,
        new_value=ticket.status,
        close_reason=close_reason
    )
    Logger.info(unicode('Ticket %d processed. Next !' % (ticket_id)))
コード例 #17
0
ファイル: phishing.py プロジェクト: ovh/cerberus-core
def block_url_and_mail(ticket_id=None, report_id=None):
    """
        Block url with PhishingService and send mail to defendant

        :param int ticket_id: The id of the Cerberus `abuse.models.Ticket`
        :param int report_id: The id of the Cerberus `abuse.models.Report`
    """
    if not isinstance(ticket_id, Ticket):
        try:
            ticket = Ticket.objects.get(id=ticket_id)
            if not ticket.defendant or not ticket.service:
                Logger.error(unicode('Ticket %d has no defendant/service' % (ticket_id)))
                return
        except (ObjectDoesNotExist, ValueError):
            Logger.error(unicode('Ticket %d cannot be found in DB. Skipping...' % (ticket_id)))
            return
    else:
        ticket = ticket_id

    if not isinstance(report_id, Report):
        try:
            report = Report.objects.get(id=report_id)
        except (ObjectDoesNotExist, ValueError):
            Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report_id)))
            return
    else:
        report = report_id

    for item in report.reportItemRelatedReport.filter(itemType='URL'):
        ImplementationFactory.instance.get_singleton_of('PhishingServiceBase').block_url(item.rawItem, item.report)

    database.add_phishing_blocked_tag(report)
    __send_email(ticket, report.defendant.details.email, settings.CODENAMES['phishing_blocked'], report.defendant.details.lang)
    ticket = Ticket.objects.get(id=ticket.id)

    ticket_snooze = settings.GENERAL_CONFIG['phishing']['wait']
    if not ticket.status == 'WaitingAnswer' and not ticket.snoozeDuration and not ticket.snoozeStart:
        ticket.previousStatus = ticket.status
        ticket.status = 'WaitingAnswer'
        ticket.snoozeDuration = ticket_snooze
        ticket.snoozeStart = datetime.now()

    ticket.save()
    Logger.info(unicode('Ticket %d now with status WaitingAnswer for %d' % (ticket.id, ticket_snooze)))
コード例 #18
0
ファイル: phishing.py プロジェクト: ovh/cerberus-core
def check_if_all_down(report=None, last=5):
    """ Check if all urls items for a report (phishing for example) are 'down'.

        :param `abuse.models.Report` report: A Cerberus `abuse.models.Report` instance to ping
        :param int last: Look for the n last record in db
        :return: the result
        :rtype: bool
    """
    if not isinstance(report, Report):
        try:
            report = Report.objects.get(id=report)
        except (AttributeError, ObjectDoesNotExist, TypeError, ValueError):
            Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report)))
            return

    items = report.reportItemRelatedReport.all()
    items = list(set([item for item in items if item.itemType == 'URL']))
    if not items:
        return False

    country = report.defendant.details.country if report.defendant else 'FR'

    for item in items:
        __update_item_status(item, country)

    items = report.reportItemRelatedReport.all()
    items = list(set([item for item in items if item.itemType == 'URL']))
    scoring = {item.id: 0 for item in items}

    for item in items:
        status_score = database.get_item_status_score(item.id, last=last)
        for score in status_score:
            scoring[item.id] += score

    if all(v >= settings.GENERAL_CONFIG['phishing']['down_threshold'] for v in scoring.itervalues()):
        Logger.error(unicode('All urls are down for report %d' % (report.id)))
        return True

    Logger.error(unicode('Some url are still up for report %d' % (report.id)))
    return False
コード例 #19
0
ファイル: report.py プロジェクト: ovh/cerberus-core
def archive_if_timeout(report_id=None):
    """
        Archived report if not attached

        :param int report_id: The report id
    """
    if not report_id:
        Logger.error(unicode('Invalid parameters submitted [report_id=%d]' % (report_id)))
        return

    try:
        report = Report.objects.get(id=report_id)
    except (ObjectDoesNotExist, ValueError):
        Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report_id)))
        return

    if report.status != 'New':
        Logger.error(unicode('Report %d not New, status : %s , Skipping ...' % (report_id, report.status)))
        return

    report.ticket = None
    report.status = 'Archived'
    report.save()
    Logger.info(unicode('Report %d successfully archived' % (report_id)))
コード例 #20
0
ファイル: ticket.py プロジェクト: ovh/cerberus-core
def create_ticket_from_phishtocheck(report=None, user=None):
    """
        Create/attach report to ticket + block_url + mail to defendant + email to provider

        :param int report: The id of the `abuse.models.Report`
        :param int user: The id of the `abuse.models.User`
    """
    if not isinstance(report, Report):
        try:
            report = Report.objects.get(id=report)
        except (AttributeError, ObjectDoesNotExist, TypeError, ValueError):
            Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report)))
            return

    if not isinstance(user, User):
        try:
            user = User.objects.get(id=user)
        except (AttributeError, ObjectDoesNotExist, TypeError, ValueError):
            Logger.error(unicode('User %d cannot be found in DB. Skipping...' % (user)))
            return

    # Create/attach to ticket
    ticket = database.search_ticket(report.defendant, report.category, report.service)
    new_ticket = False

    if not ticket:
        ticket = database.create_ticket(report.defendant, report.category, report.service, priority=report.provider.priority)
        new_ticket = True
        utils.scheduler.enqueue_in(
            timedelta(seconds=settings.GENERAL_CONFIG['phishing']['wait']),
            'ticket.timeout',
            ticket_id=ticket.id,
            timeout=3600,
        )

    common.get_temp_proofs(ticket, only_urls=True)

    report.ticket = ticket
    report.status = 'Attached'
    report.save()
    database.log_action_on_ticket(
        ticket=ticket,
        action='attach_report',
        report=report,
        new_ticket=new_ticket
    )
    database.log_action_on_ticket(
        ticket=ticket,
        action='validate_phishtocheck',
        user=user,
        report=report
    )

    # Sending email to provider
    if settings.TAGS['no_autoack'] not in report.provider.tags.all().values_list('name', flat=True):

        common.send_email(
            ticket,
            [report.provider.email],
            settings.CODENAMES['ack_received'],
            acknowledged_report_id=report.id,
        )

    utils.default_queue.enqueue('phishing.block_url_and_mail', ticket_id=ticket.id, report_id=report.id)
    return ticket
コード例 #21
0
ファイル: report.py プロジェクト: ovh/cerberus-core
def create_from_email(email_content=None, filename=None, lang='EN', send_ack=False):
    """
        Create Cerberus report(s) based on email content

        If send_ack is True and report is attached to a ticket,
        then an acknowledgement is sent to the email provider.

        :param str email_content: The raw email content
        :param str filename: The name of the raw email file
        :param str lang: Langage to use if send_ack is True
        :param bool send_ack: If an acknowledgment have to be sent to provider
        :raises CustomerDaoException: if exception while identifying defendants from items
        :raises MailerServiceException: if exception while updating ticket's emails
        :raises StorageServiceException: if exception while accessing storage
    """
    # This function use a lock/commit_on_succes on db when creating reports
    #
    # Huge blocks of code are under transaction because it's important to
    # rollback if ANYTHING goes wrong in the report creation workflow.
    #
    # Concurrent transactions (with multiple workers), on defendant/service creation
    # can result in unconsistent data, So a pg_lock is used.
    #
    # `abuse.models.Defendant` and `abuse.models.Service` HAVE to be unique.

    if not email_content:
        Logger.error(unicode('Missing email content'))
        return

    if not filename:  # Worker have to push email to Storage Service
        filename = hashlib.sha256(email_content).hexdigest()
        __save_email(filename, email_content)

    # Parse email content
    abuse_report = Parser.parse(email_content)
    Logger.debug(unicode('New email from %s' % (abuse_report.provider)), extra={'from': abuse_report.provider, 'action': 'new email'})

    # Check if provider is not blacklisted
    if abuse_report.provider in settings.PARSING['providers_to_ignore']:
        Logger.error(unicode('Provider %s is blacklisted, skipping ...' % (abuse_report.provider)))
        return

    # Check if it's an answer to a ticket(s)
    tickets = ImplementationFactory.instance.get_singleton_of('MailerServiceBase').is_email_ticket_answer(abuse_report)
    if tickets:
        for ticket, category, recipient in tickets:
            if all((ticket, category, recipient)) and not ticket.locked:  # OK it's an anwser, updating ticket and exiting
                _update_ticket_if_answer(ticket, category, recipient, abuse_report, filename)
        return

    # Check if items are linked to customer and get corresponding services
    try:
        services = ImplementationFactory.instance.get_singleton_of('CustomerDaoBase').get_services_from_items(
            urls=abuse_report.urls,
            ips=abuse_report.ips,
            fqdn=abuse_report.fqdn
        )
        schema.valid_adapter_response('CustomerDaoBase', 'get_services_from_items', services)
    except CustomerDaoException as ex:
        Logger.error(unicode('Exception while identifying defendants from items for mail %s -> %s ' % (filename, str(ex))))
        raise CustomerDaoException(ex)

    # Create report(s) with identified services
    if not services:
        created_reports = [__create_without_services(abuse_report, filename)]
    else:
        with pglocks.advisory_lock('cerberus_lock'):
            __create_defendants_and_services(services)
        created_reports = __create_with_services(abuse_report, filename, services)

    # Upload attachments
    if abuse_report.attachments:
        _save_attachments(filename, abuse_report.attachments, reports=created_reports)

    # Send acknowledgement to provider (only if send_ack = True and report is attached to a ticket)
    for report in created_reports:
        if send_ack and report.ticket:
            try:
                __send_ack(report, lang=lang)
            except MailerServiceException as ex:
                raise MailerServiceException(ex)

    # Index to SearchService
    if ImplementationFactory.instance.is_implemented('SearchServiceBase'):
        __index_report_to_searchservice(abuse_report, filename, [rep.id for rep in created_reports])

    Logger.info(unicode('All done successfully for email %s' % (filename)))
コード例 #22
0
ファイル: action.py プロジェクト: ovh/cerberus-core
def apply_action(ticket_id=None, action_id=None, ip_addr=None, user_id=None):
    """
        Apply given action on customer service

        :param int ticket_id: The id of the Cerberus `Ticket`
        :param int action_id: The id of the Cerberus `ServiceAction`
        :param int user_id: The id of the Cerberus `User`
        :rtype: bool
        :returns: if action has been applied
    """
    current_job = get_current_job()

    # Checking conformance
    if not all((ticket_id, action_id, user_id)):
        msg = 'Invalid parameters submitted [ticket_id=%d, action_id=%s, user_id=%s]'
        Logger.error(unicode(msg % (ticket_id, action_id, user_id)))
        return False

    # Fetching Django model object
    Logger.info(unicode('Starting process ticket %d with params [%d]' % (ticket_id, action_id)))
    try:
        ticket = Ticket.objects.get(id=ticket_id)
        user = User.objects.get(id=user_id)
    except (ObjectDoesNotExist, ValueError):
        Logger.error(unicode('Ticket %d or user %d cannot be found in DB. Skipping...' % (ticket_id, user_id)))
        return False

    if ticket.status in ['Closed', 'Answered']:
        __cancel_by_status(ticket)
        ticket.previousStatus = ticket.status
        ticket.status = 'ActionError'
        ticket.save()
        database.log_action_on_ticket(
            ticket=ticket,
            action='change_status',
            user=user,
            previous_value=ticket.previousStatus,
            new_value=ticket.status,
        )
        return False

    # Call action service
    try:
        result = ImplementationFactory.instance.get_singleton_of(
            'ActionServiceBase'
        ).apply_action_on_service(
            ticket_id,
            action_id,
            ip_addr,
            user.id
        )
        _update_job(current_job.id, todo_id=result.todo_id, status=result.status, comment=result.comment)
        return True
    except ActionServiceException as ex:
        Logger.info(unicode('Service Action not apply for ticket %d' % (ticket_id)))
        _update_job(current_job.id, status='actionError', comment=str(ex))
        ticket.previousStatus = ticket.status
        ticket.status = 'ActionError'
        ticket.save()
        database.log_action_on_ticket(
            ticket=ticket,
            action='change_status',
            user=user,
            previous_value=ticket.previousStatus,
            new_value=ticket.status,
        )
        return False