PhishLabs IOC EIR

Get Email Incident Reports from PhishLabs.

Data Enrichment & Threat Intelligence · PhishLabs

Details

IDPhishLabs IOC EIR
ProviderFortra
CategoryData Enrichment & Threat Intelligence
From Version5.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

This integration was integrated and tested with V1.0 of PhishLabs IOC EIR api

Use Cases

  • Get live EIR from PhishLabs
  • Get EIR by filters from PhishLabs

Detailed Description

Phishlabs Email Incident Response (EIR) is a solution that protects against threats that make it past your email security stack and into your employee inboxes. With Email Incident Response, enterprises can detect, prevent, and respond to these threats.

  • Suspicious Email Analysis
  • Email Threat Intelligence

Configure PhishLabs IOC EIR on Cortex XSOAR

  1. Navigate to Settings > Integrations  Servers & Services.
  2. Search for PhishLabs IOC EIR.
  3. Click Add instance to create and configure a new integration instance.
    • Name: a textual name for the integration instance.
    • Server URL (e.g. https://example.net)
    • User
    • Source Reliability. Reliability of the source providing the intelligence data. (The default value is B - Usually reliable)
    • Fetch incidents
    • First fetch timestamp ( e.g., 12 hours, 7 days)
    • Fetch limit
    • Trust any certificate (not secure)
    • Use system proxy settings
  4. Click Test to validate the new instance.

Fetch Incidents

Fetch incidents done by the following configuration:

  • Fetch limit - limit amount of incidents by fetch
  • First fetch timestamp - date for starting collecting incidents (1 days ago, 1 hours ago etc)
  • Incident type
[
  {
    "name": "PhishLabs IOC - EIR: INC0528925",
    "occurred": "2019-10-15T16:31:09Z",
    "rawJSON": {
            "id": "INC0528925",
            "service": "EIR",
            "title": "Deploymentliste release 10.0 in PROD am 15.10.2019",
            "description": "",
            "status": "Closed",
            "details": {
                "caseType": "Response",
                "classification": "No Threat Detected",
                "subClassification": "No Threat Detected",
                "severity": null,
                "emailReportedBy": "johnnydepp@gmail.com",
                "submissionMethod": "Attachment",
                "sender": "johnnydepp@gmail.com",
                "emailBody": "Test",
                "urls": [
                    {
                        "url": "google.com",
                        "malicious": false,
                        "maliciousDomain": false
                    }
                ],
                "attachments": [],
                "furtherReviewReason": null,
                "offlineUponReview": false
            },
            "created": "2019-10-15T16:31:08Z",
            "modified": "2019-10-15T16:31:09Z",
            "closed": "2019-10-15T16:31:09Z",
            "duration": 0
        }
  }
]

Commands

You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. After you successfully execute a command, a DBot message appears in the War Room with the command details.

  1. phishlabs-ioc-eir-get-incidents
  2. phishlabs-ioc-eir-get-incident-by-id

1. phishlabs-ioc-eir-get-incidents


Get EIR incidents from PhishLabs-IOC EIR service (dafault limit 25 incidents)

Base Command

phishlabs-ioc-eir-get-incidents

Input
Argument Name Description Required
status Filter incidents that are opened or closed. Optional
created_after Return Incidents created on or after the given timestamp Timestamp is in RFC3339 format(2019-04-12T23:20:50Z) Optional
created_before Return Incidents created on or before the given timestamp Timestamp is in RFC3339 format(2019-04-12T23:20:50Z) Optional
closed_after Return Incidents closed on or after the given timestamp Timestamp is in RFC3339 format(2019-04-12T23:20:50Z) Optional
closed_before Return Incidents closed on or before the given timestamp Timestamp is in RFC3339 format(2019-04-12T23:20:50Z) Optional
sort Return Incidents sorted by the given column. Optional
direction Return Incidents sorted by the given order. This will be applied to the given sort parameter. Optional
limit Limit amounts of incidents (0-50, default 25) Optional
offset Offset from last incident Optional
period Period to query on 1 days, 2 hours Optional

 

Context Output
Path Type Description
PhishLabsIOC.EIR.CaseType String Incident reason type
PhishLabsIOC.EIR.Classification String Incident classification
PhishLabsIOC.EIR.SubClassification String Detailed classification
PhishLabsIOC.EIR.Severity String Incident severity
PhishLabsIOC.EIR.SubmissionMethod String Email submission method
PhishLabsIOC.EIR.FurtherReviewReason String Incident further review reason
PhishLabsIOC.EIR.ID String Id of incident
PhishLabsIOC.EIR.Title String Title of reported incident
PhishLabsIOC.EIR.Description String Description of reporeted incident
PhishLabsIOC.EIR.Status Boolean Status of reported incident
PhishLabsIOC.EIR.Created Date Date of incident creation
PhishLabsIOC.EIR.Modified Date Date of incident last modified
PhishLabsIOC.EIR.Closed Date Date of incident closing
PhishLabsIOC.EIR.Duration Number Duration until closing incident in seconds
PhishLabsIOC.EIR.EmailReportedBy String User who reported the incident
PhishLabsIOC.EIR.Email.EmailBody String Email body
PhishLabsIOC.EIR.Email.Sender String Email sender
PhishLabsIOC.EIR.Email.URL.URL String Url found in body
PhishLabsIOC.EIR.Email.URL.Malicious Boolean Is the url malicious?
PhishLabsIOC.EIR.Email.URL.MaliciousDomain Boolean Is the url domain malicious?
PhishLabsIOC.EIR.Email.Attachment.FileName String Name of the attached file
PhishLabsIOC.EIR.Email.Attachment.MimeType String Attachemt mime type
PhishLabsIOC.EIR.Email.Attachment.MD5 String Attachemt md5 hash
PhishLabsIOC.EIR.Email.Attachment.SHA256 String Attachemt sha256 hash
PhishLabsIOC.EIR.Email.Attachment.Malicious Boolean Is the file malicious?
Email.To String The recipient of the email.
Email.From String The sender of the email.
Email.Body/HTML String The plain-text version of the email.
File.Name String The full file name (including file extension).
File.SHA256 Unknown The SHA256 hash of the file.
File.MD5 String The MD5 hash of the file.
File.Malicious.Vendor String The vendor that reported the file as malicious.
File.Malicious.Description String A description explaining why the file was determined to be malicious.
URL.Data String The URL
URL.Malicious.Vendor String The vendor reporting the URL as malicious.
URL.Malicious.Description String A description of the malicious URL.
DBotScore.Indicator String The indicator that was tested.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
DBotScore.Score String The actual score.

 

Command Example

!phishlabs-ioc-eir-get-incidents limit=3

Context Example
{
    "DBotScore": [
        {
            "Indicator": "https://google.com",
            "Score": 1,
            "Type": "URL",
            "Vendor": "PhishLabs IOC - EIR"
        }
    ],
    "Email": [
        {
            "Body/HTML": "Example body",
            "From": "LinkedIn Sales Navigator  not@domain.com",
            "To": "Michael Mammele not@domain.com"
        },
        {
            "Body/HTML": "Example body",
            "From": "Tony Prince not@domain.com",
            "To": "Tony Prince not@domain.com"
        },
        {
            "Body/HTML": "Example body",
            "From": "FileDoc2 not@domain.com",
            "To": "John LaCour not@domain.com"
        }
    ],
    "File": [],
    "PhishLabsIOC": {
        "EIR": [
            {
                "CaseType": "Link",
                "Classification": "No Threat Detected",
                "Closed": "2019-11-05T23:23:06Z",
                "Created": "2019-11-05T22:05:52Z",
                "Description": "",
                "Duration": 4635,
                "Email": {
                    "Attachment": [],
                    "EmailBody": "Example body",
                    "Sender": "LinkedIn Sales Navigator  not@domain.com",
                    "URL": [
                        {
                            "Malicious": false,
                            "MaliciousDomain": false,
                            "URL": "https://google.com"
                        }
                    ]
                },
                "EmailReportedBy": "Michael Mammele not@domain.com",
                "FurtherReviewReason": null,
                "ID": "INC0682881",
                "Modified": "2019-11-05T23:23:06Z",
                "Severity": null,
                "Status": "Closed",
                "SubClassification": "No Threat Detected",
                "SubmissionMethod": "Attachment",
                "Title": "See who else can influence your deals"
            }
    ]
}
Human Readable Output

PhishLabs IOC - EIR - incidents

ID Title Status Created Classification SubClassification EmailReportedBy
INC0682881 See who else can influence your deals Closed 2019-11-05T22:05:52Z No Threat Detected No Threat Detected Michael Mammele not@domain.com
INC0682040 FW: Tuesday, November 5, 2019 Closed 2019-11-05T20:30:48Z Malicious Link - Phishing Tony Prince not@domain.com
INC0681982 Tuesday, November 5, 2019 Closed 2019-11-05T20:25:22Z Malicious Link - Phishing John LaCour not@domain.com

2. phishlabs-ioc-eir-get-incident-by-id


Returns a single Incident based on the given ID.

Base Command

phishlabs-ioc-eir-get-incident-by-id

Input
Argument Name Description Required
incident_id ID of Incident, Get it from previous command Required

 

Context Output
Path Type Description
PhishLabsIOC.EIR.CaseType String Incident reason type
PhishLabsIOC.EIR.Classification String Incident classification
PhishLabsIOC.EIR.SubClassification String Detailed classification
PhishLabsIOC.EIR.Severity String Incident severity
PhishLabsIOC.EIR.SubmissionMethod String Email submission method
PhishLabsIOC.EIR.FurtherReviewReason String Incident further review reason
PhishLabsIOC.EIR.ID String Id of incident
PhishLabsIOC.EIR.Title String Title of reported incident
PhishLabsIOC.EIR.Description String Description of reporeted incident
PhishLabsIOC.EIR.Status Boolean Status of reported incident
PhishLabsIOC.EIR.Created Date Date of incident creation
PhishLabsIOC.EIR.Modified Date Date of incident last modified
PhishLabsIOC.EIR.Closed Date Date of incident closing
PhishLabsIOC.EIR.Duration Number Duration until closing incident in seconds
PhishLabsIOC.EIR.EmailReportedBy String User who reported the incident
PhishLabsIOC.EIR.Email.EmailBody String Email body
PhishLabsIOC.EIR.Email.Sender String Email sender
PhishLabsIOC.EIR.Email.URL.URL String Url found in body
PhishLabsIOC.EIR.Email.URL.Malicious Boolean Is the url malicious?
PhishLabsIOC.EIR.Email.URL.MaliciousDomain Boolean Is the url domain malicious?
PhishLabsIOC.EIR.Email.Attachment.FileName String Name of the attached file
PhishLabsIOC.EIR.Email.Attachment.MimeType String Attachemt mime type
PhishLabsIOC.EIR.Email.Attachment.MD5 String Attachemt md5 hash
PhishLabsIOC.EIR.Email.Attachment.SHA256 String Attachemt sha256 hash
PhishLabsIOC.EIR.Email.Attachment.Malicious Boolean Is the file malicious?
Email.To String The recipient of the email.
Email.From String The sender of the email.
Email.Body/HTML String The plain-text version of the email.
File.Name String The full file name (including file extension).
File.SHA256 Unknown The SHA256 hash of the file.
File.MD5 String The MD5 hash of the file.
File.Malicious.Vendor String The vendor that reported the file as malicious.
File.Malicious.Description String A description explaining why the file was determined to be malicious.
URL.Data String The URL
URL.Malicious.Vendor String The vendor reporting the URL as malicious.
URL.Malicious.Description String A description of the malicious URL.
DBotScore.Indicator String The indicator that was tested.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
DBotScore.Score String The actual score.
Command Example

!phishlabs-ioc-eir-get-incident-by-id incident_id=INC0671150

Context Example
{
    "DBotScore": [
        {
            "Indicator": "https://google.com",
            "Score": 1,
            "Type": "URL",
            "Vendor": "PhishLabs IOC - EIR"
        }
    ],
    "Email": [
        {
            "Body/HTML": "Example body",
            "From": "LinkedIn Sales Navigator  not@domain.com",
            "To": "Michael Mammele not@domain.com"
        }
    ],
    "File": [],
    "PhishLabsIOC": {
        "EIR": [
            {
                "CaseType": "Link",
                "Classification": "No Threat Detected",
                "Closed": "2019-11-05T23:23:06Z",
                "Created": "2019-11-05T22:05:52Z",
                "Description": "",
                "Duration": 4635,
                "Email": {
                    "Attachment": [],
                    "EmailBody": "Example body",
                    "Sender": "LinkedIn Sales Navigator  not@domain.com",
                    "URL": [
                        {
                            "Malicious": false,
                            "MaliciousDomain": false,
                            "URL": "https://google.com"
                        }
                    ]
                },
                "EmailReportedBy": "Michael Mammele not@domain.com",
                "FurtherReviewReason": null,
                "ID": "INC0682881",
                "Modified": "2019-11-05T23:23:06Z",
                "Severity": null,
                "Status": "Closed",
                "SubClassification": "No Threat Detected",
                "SubmissionMethod": "Attachment",
                "Title": "See who else can influence your deals"
            }
    ]
}

Configuration parameters

  • url — Server URL (e.g. https://example.net) (required)
  • credentials — User (required)
  • integrationReliability — Source Reliability (required)
  • isFetch — Fetch incidents
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • fetchTime — First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days)
  • fetchLimit — Fetch limit
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (2)

  • phishlabs-ioc-eir-get-incident-by-id

    Returns a single Incident based on the given ID.

  • phishlabs-ioc-eir-get-incidents

    Returns EIR incidents from PhishLabs-IOC EIR service. The default number of incidents returned is 25.

import pytest
from PhishLabsIOC_EIR import Client

"""Globals"""
INDICATORS_EC = [
    (
        "url-phishlabs",
        {"url": "https://google.com/", "malicious": "false", "maliciousDomain": "false"},
        {"URL": "https://google.com/", "Malicious": "false", "MaliciousDomain": "false"},
    ),
    (
        "attach-phishlabs",
        {
            "fileName": "test.pdf",
            "mimeType": "application/pdf",
            "md5": "6680e7e593c8286ac51e332d8f72aeec",
            "sha256": "1111111111111111111111111111111111111111111111111111",
            "malicious": "false",
        },
        {
            "fileName": "test.pdf",
            "MimeType": "application/pdf",
            "MD5": "6680e7e593c8286ac51e332d8f72aeec",
            "SHA256": "1111111111111111111111111111111111111111111111111111",
            "Malicious": "false",
        },
    ),
    (
        "email-ec",
        {
            "caseType": "Link",
            "classification": "No Threat Detected",
            "subClassification": "No Threat Detected",
            "severity": "null",
            "emailReportedBy": "Michael Mammele <support@threatx.com>",
            "submissionMethod": "Attachment",
            "sender": "LinkedIn Sales Navigator  <support@threatx.com>",
            "emailBody": "Test body",
            "attachments": [],
            "furtherReviewReason": "null",
            "offlineUponReview": "false",
        },
        {
            "To": "Michael Mammele <support@threatx.com>",
            "From": "LinkedIn Sales Navigator  <support@threatx.com>",
            "Body/HTML": "Test body",
        },
    ),
]

INDICATORS_DBOT_EC = [
    (
        Client(base_url="http://test.com"),
        "url-ec",
        {"url": "https://google.com/", "malicious": "false", "maliciousDomain": "false"},
        (
            {
                "Indicator": "https://google.com/",
                "Reliability": "B - Usually reliable",
                "Type": "URL",
                "Vendor": "PhishLabs IOC - EIR",
                "Score": 1,
            },
            {"Data": "https://google.com/", "Malicious": {"Vendor": "PhishLabs IOC - EIR", "Description": "false"}},
        ),
    ),
    (
        Client(base_url="http://test.com"),
        "file-ec",
        {
            "fileName": "test.pdf",
            "mimeType": "application/pdf",
            "md5": "6680e7e593c8286ac51e332d8f72aeec",
            "sha256": "1111111111111111111111111111111111111111111111111111",
            "malicious": "false",
        },
        (
            {
                "Indicator": "test.pdf",
                "Reliability": "B - Usually reliable",
                "Type": "File",
                "Vendor": "PhishLabs IOC - EIR",
                "Score": 1,
            },
            {
                "Name": "test.pdf",
                "SHA256": "1111111111111111111111111111111111111111111111111111",
                "MD5": "6680e7e593c8286ac51e332d8f72aeec",
                "Malicious": {"Vendor": "PhishLabs IOC - EIR", "Description": "false"},
            },
        ),
    ),
]


INDICATORS_TO_LIST_EC = [
    (
        Client(base_url="http://test.com"),
        "url-ec",
        [
            {"url": "https://google.com/u/gI5Qk", "malicious": "false", "maliciousDomain": "false"},
            {"url": "https://google.com/api/track/v2/5", "malicious": "false", "maliciousDomain": "false"},
            {"url": "https://google.com/", "malicious": "false", "maliciousDomain": "false"},
        ],
        (
            [
                {"Data": "https://google.com/u/gI5Qk", "Malicious": {"Vendor": "PhishLabs IOC - EIR", "Description": "false"}},
                {
                    "Data": "https://google.com/api/track/v2/5",
                    "Malicious": {"Vendor": "PhishLabs IOC - EIR", "Description": "false"},
                },
                {"Data": "https://google.com/", "Malicious": {"Vendor": "PhishLabs IOC - EIR", "Description": "false"}},
            ],
            [
                {
                    "Indicator": "https://google.com/u/gI5Qk",
                    "Reliability": "B - Usually reliable",
                    "Type": "URL",
                    "Vendor": "PhishLabs IOC - EIR",
                    "Score": 1,
                },
                {
                    "Indicator": "https://google.com/api/track/v2/5",
                    "Reliability": "B - Usually reliable",
                    "Type": "URL",
                    "Vendor": "PhishLabs IOC - EIR",
                    "Score": 1,
                },
                {
                    "Indicator": "https://google.com/",
                    "Reliability": "B - Usually reliable",
                    "Type": "URL",
                    "Vendor": "PhishLabs IOC - EIR",
                    "Score": 1,
                },
            ],
        ),
    )
]


RAW_RESPONSE_TO_CONTEXT = [
    [
        {
            "id": "INC0660360",
            "service": "EIR",
            "title": "Your operating system has been hacked by cybercriminals. Change the authorization method.",
            "description": "",
            "status": "Closed",
            "details": {
                "caseType": "Response",
                "classification": "Malicious",
                "subClassification": "Response - 419 Scam",
                "severity": "Low",
                "emailReportedBy": "PhishLabs Phishing Team <not@domain.com>",
                "submissionMethod": "Attachment",
                "sender": "<not@domain.com>",
                "emailBody": "Test",
                "urls": [{"url": "https://google.com/i5/resp", "malicious": "false", "maliciousDomain": "false"}],
                "attachments": [
                    {
                        "fileName": "test.pdf",
                        "mimeType": "application/pdf",
                        "md5": "6680e7e593c8286ac51e332d8f72aeec",
                        "sha256": "1111111111111111111111111111111111111111111111111111",
                        "malicious": "false",
                    }
                ],
                "furtherReviewReason": "null",
                "offlineUponReview": "false",
            },
            "created": "2019-11-01T20:55:33Z",
            "modified": "2019-11-01T21:39:57Z",
            "closed": "2019-11-01T21:39:57Z",
            "duration": 2665,
        }
    ],
    (
        [
            {
                "CaseType": "Response",
                "Classification": "Malicious",
                "SubClassification": "Response - 419 Scam",
                "Severity": "Low",
                "EmailReportedBy": "PhishLabs Phishing Team <not@domain.com>",
                "SubmissionMethod": "Attachment",
                "FurtherReviewReason": "null",
                "ID": "INC0660360",
                "Title": "Your operating system has been hacked by cybercriminals. Change the authorization method.",
                "Description": "",
                "Status": "Closed",
                "Created": "2019-11-01T20:55:33Z",
                "Modified": "2019-11-01T21:39:57Z",
                "Closed": "2019-11-01T21:39:57Z",
                "Duration": 2665,
                "Email": {
                    "EmailBody": "Test",
                    "Sender": "<not@domain.com>",
                    "URL": [{"URL": "https://google.com/i5/resp", "Malicious": "false", "MaliciousDomain": "false"}],
                    "Attachment": [
                        {
                            "fileName": "test.pdf",
                            "MimeType": "application/pdf",
                            "MD5": "6680e7e593c8286ac51e332d8f72aeec",
                            "SHA256": "1111111111111111111111111111111111111111111111111111",
                            "Malicious": "false",
                        }
                    ],
                },
            }
        ],
        [
            {
                "To": "PhishLabs Phishing Team <not@domain.com>",
                "From": "<not@domain.com>",
                "Body/HTML": "Test",
            }
        ],
        [
            {
                "Name": "test.pdf",
                "SHA256": "1111111111111111111111111111111111111111111111111111",
                "MD5": "6680e7e593c8286ac51e332d8f72aeec",
                "Malicious": {"Vendor": "PhishLabs IOC - EIR", "Description": "false"},
            }
        ],
        [{"Data": "https://google.com/i5/resp", "Malicious": {"Vendor": "PhishLabs IOC - EIR", "Description": "false"}}],
        [
            {
                "Indicator": "test.pdf",
                "Reliability": "B - Usually reliable",
                "Type": "File",
                "Vendor": "PhishLabs IOC - EIR",
                "Score": 1,
            },
            {
                "Indicator": "https://google.com/i5/resp",
                "Reliability": "B - Usually reliable",
                "Type": "URL",
                "Vendor": "PhishLabs IOC - EIR",
                "Score": 1,
            },
        ],
    ),
]

"""Function tests"""


class TestHelperFunctions:
    @pytest.mark.parametrize(argnames="type_ec, test_inputs, test_outputs", argvalues=INDICATORS_EC)
    def test_indicator_ec(self, type_ec, test_inputs, test_outputs):
        from PhishLabsIOC_EIR import indicator_ec

        result = indicator_ec(indicator=test_inputs, type_ec=type_ec)
        assert result == test_outputs

    @pytest.mark.parametrize(argnames="client, type_ec, test_inputs, test_outputs", argvalues=INDICATORS_DBOT_EC)
    def test_indicator_dbot_ec(self, client, type_ec, test_inputs, test_outputs):
        from PhishLabsIOC_EIR import indicator_dbot_ec

        result = indicator_dbot_ec(client=client, indicator=test_inputs, type_ec=type_ec)
        assert result == test_outputs

    @pytest.mark.parametrize(argnames="client, type_ec, test_inputs, test_outputs", argvalues=INDICATORS_TO_LIST_EC)
    def test_indicators_to_list_ec(self, client, type_ec, test_inputs, test_outputs):
        from PhishLabsIOC_EIR import indicators_to_list_ec

        result = indicators_to_list_ec(client=client, indicators=test_inputs, type_ec=type_ec)
        assert result == test_outputs

    def test_raw_response_to_context(self):
        from PhishLabsIOC_EIR import raw_response_to_context

        client = Client(base_url="http://test.com")
        result = raw_response_to_context(client=client, incidents=RAW_RESPONSE_TO_CONTEXT[0])
        assert result == RAW_RESPONSE_TO_CONTEXT[1]


def test_fetch__last_run_not_none(mocker):
    """Tests the fetch-incidents command function.

    Give: last run to request from
    When: running fetch command and no incidents returned
    Then: assert new last run is not None
    """
    from PhishLabsIOC_EIR import Client, fetch_incidents_command

    client = Client(base_url="https://test.com/api/v1", verify=False, reliability="A")

    mocker.patch.object(Client, "get_incidents", return_value={"metadata": {"count": 0}, "incidents": []})

    incident_report, last_run = fetch_incidents_command(
        client=client, last_run="2023-09-20T03:44:55Z", fetch_time="3 days", limit="2", last_ids=set()
    )

    assert last_run == {"lastRun": "2023-09-20T03:44:55Z", "lastIds": []}


def test_fetch_merge_open_closed(mocker):
    """Tests the fetch-incidents command function.

    Give: last run to request from
    When: running fetch command and no incidents returned
    Then: assert new last run is not None
    """
    from PhishLabsIOC_EIR import Client, fetch_incidents_command

    client = Client(base_url="https://test.com/api/v1", verify=False, reliability="A")

    mocker.patch.object(
        Client,
        "get_incidents",
        side_effect=[
            {
                "metadata": {"count": 2},
                "incidents": [
                    {"id": "1", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "Test"}},
                    {"id": "2", "created": "2023-09-20T03:47:55Z", "details": {"subClassification": "Test"}},
                ],
            },
            {
                "metadata": {"count": 2},
                "incidents": [
                    {"id": "4", "created": "2023-09-20T03:48:55Z", "details": {"subClassification": "Test"}},
                    {"id": "5", "created": "2023-09-20T03:49:55Z", "details": {"subClassification": "Test"}},
                ],
            },
            {
                "metadata": {"count": 1},
                "incidents": [{"id": "3", "created": "2023-09-20T03:45:55Z", "details": {"subClassification": "Test"}}],
            },
            {
                "metadata": {"count": 1},
                "incidents": [{"id": "4", "created": "2023-09-20T03:48:55Z", "details": {"subClassification": "Test"}}],
            },
            {"metadata": {"count": 0}, "incidents": []},
        ],
    )

    incident_report, last_run = fetch_incidents_command(
        client=client, last_run="2023-09-20T03:44:55Z", fetch_time="3 days", limit="4", last_ids=set()
    )

    assert last_run == {"lastRun": "2023-09-20T03:48:55Z", "lastIds": ["4"]}
    assert len(incident_report) == 4


def test_get_incidents_with_offset(mocker):
    """

    Given: limit number of incidents to fetch.
    When: running fetch command
    Then: assert the correct amount of incidents is returned

    """
    from PhishLabsIOC_EIR import Client, fetch_incidents_command

    def mock_get_incident(
        status=None,
        created_after=None,
        created_before=None,
        closed_before=None,
        closed_after=None,
        sort=None,
        direction=None,
        limit=25,
        offset=0,
        period=None,
    ):
        total_res = 4
        incidents = []
        if offset < total_res:
            for i in range(offset, total_res):
                incidents.append({"id": i, "created": "2023-09-20T03:44:55Z"})
        return {"metadata": {"count": total_res - offset}, "incidents": incidents}

    client = Client(base_url="https://test.com/api/v1", verify=False, reliability="A")

    mocker.patch.object(Client, "get_incidents", side_effect=mock_get_incident)
    incident_report, _ = fetch_incidents_command(
        client=client, last_run="2023-09-20T03:44:55Z", fetch_time="3 days", limit="4", last_ids=set()
    )

    assert len(incident_report) == 4


def test_duplicated_incident(mocker):
    """

    Given: incidents from Phislabs in 2 api calls.
    When: running fetch command
    Then: assert the correct amount of incidents is returned without dups

    """
    from PhishLabsIOC_EIR import Client, fetch_incidents_command

    client = Client(base_url="https://test.com/api/v1", verify=False, reliability="A")
    incidents = [
        {"id": "1", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "2", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "3", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
    ]
    mocker.patch.object(Client, "get_incidents", return_value={"metadata": {"count": 1}, "incidents": incidents})

    incident_report, new_last_run = fetch_incidents_command(
        client=client, last_run="2023-09-20T03:44:55Z", fetch_time="3 days", limit="10", last_ids=set()
    )

    assert len(incident_report) == 3
    assert "3" in new_last_run.get("lastIds")

    incidents = [
        {"id": "1", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "2", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "3", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "4", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "5", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
    ]
    mocker.patch.object(Client, "get_incidents", return_value={"metadata": {"count": 1}, "incidents": incidents})

    incident_report, new_last_run = fetch_incidents_command(
        client=client,
        last_run="2023-09-20T03:44:55Z",
        fetch_time="3 days",
        limit="10",
        last_ids=set(new_last_run.get("lastIds", set())),
    )

    assert len(incident_report) == 2
    assert len(new_last_run.get("lastIds")) == 5

    incidents = [
        {"id": "1", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "2", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "3", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "4", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "5", "created": "2023-09-20T03:44:55Z", "details": {"subClassification": "No Threat Detected"}},
        {"id": "6", "created": "2023-09-20T03:45:55Z", "details": {"subClassification": "No Threat Detected"}},
    ]
    mocker.patch.object(Client, "get_incidents", return_value={"metadata": {"count": 1}, "incidents": incidents})

    incident_report, new_last_run = fetch_incidents_command(
        client=client,
        last_run="2023-09-20T03:44:55Z",
        fetch_time="3 days",
        limit="10",
        last_ids=set(new_last_run.get("lastIds", set())),
    )

    assert len(incident_report) == 1
    assert new_last_run.get("lastIds") == ["6"]


def test_get_incident_by_id_command(mocker):
    """Tests the get_incident_by_id_command function.

    Given: An incident ID and a retry_count in the args dict.
    When: Running get_incident_by_id_command with the new args-based signature.
    Then: Assert the command returns the expected human readable, context, and raw response.
    """
    from PhishLabsIOC_EIR import Client, get_incident_by_id_command

    client = Client(base_url="https://test.com/api/v1", verify=False, reliability="B - Usually reliable")

    mock_response = {
        "incidents": [
            {
                "id": "INC0660360",
                "service": "EIR",
                "title": "Test incident title",
                "description": "",
                "status": "Closed",
                "details": {
                    "caseType": "Response",
                    "classification": "Malicious",
                    "subClassification": "Response - 419 Scam",
                    "severity": "Low",
                    "emailReportedBy": "Test User <test@domain.com>",
                    "submissionMethod": "Attachment",
                    "sender": "<sender@domain.com>",
                    "emailBody": "Test body",
                    "urls": [],
                    "attachments": [],
                    "furtherReviewReason": "null",
                    "offlineUponReview": "false",
                },
                "created": "2019-11-01T20:55:33Z",
                "modified": "2019-11-01T21:39:57Z",
                "closed": "2019-11-01T21:39:57Z",
                "duration": 2665,
            }
        ]
    }

    mocker.patch.object(Client, "get_incident_by_id", return_value=mock_response)

    args = {"incident_id": "INC0660360", "retry_count": "3"}
    human_readable, context_entry, raw_response = get_incident_by_id_command(client, args)

    assert "INC0660360" in str(human_readable)
    assert raw_response == mock_response
    assert context_entry is not None
    Client.get_incident_by_id.assert_called_once_with("INC0660360")