Intezer v2

Malware detection and analysis based on code reuse.

Forensics & Malware Analysis · Intezer

Details

IDIntezer v2
ProviderSymphony Talent Group
CategoryForensics & Malware Analysis
From Version5.0.0
Docker Imagedemisto/py3-tools:1.0.0.114656
Supported ModulesAgentix XSIAM

README

Use the Intezer v2 integration to detect and analyze malware, based on code reuse.

Configure Intezer v2 in Cortex

Parameter Description Required
API Key   True
Intezer Analyze Base URL The API address to intezer Analyze - i.e. https://analyze.intezer.com/api/ False
Use system proxy settings   False
Trust any certificate (not secure)   False

Commands

You can execute these commands from the 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.

intezer-analyze-by-hash


Checks file reputation of the given hash, supports SHA256, SHA1 and MD5

Base Command

intezer-analyze-by-hash

Input

Argument Name Description Required
file_hash Hash of the file to query. Supports SHA256, MD5 and SHA1. Required
wait_for_result Waits for analysis result, support polling Optional
interval Number of seconds between poll requests Optional
timeout Number of seconds until polling timeout Optional

Context Output

Path Type Description
Intezer.Analysis.ID string Intezer analysis id
Intezer.Analysis.Status string status of the analysis
Intezer.Analysis.Type string type of the analysis

Command Example

!intezer-analyze-by-hash file_hash="<file hash>"

Context Example

{
    "Intezer.Analysis": {
        "Status": "Created", 
        "type": "File", 
        "ID": "59e2f081-45f3-4822-bf45-407670dcb4d7"
    }
}

Human Readable Output

Analysis created successfully: 59e2f081-45f3-4822-bf45-407670dcb4d7

intezer-analyze-url


Checks file reputation of the given URL

Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.

Base Command

intezer-analyze-url

Input

Argument Name Description Required
Url Url to query. Required

Context Output

Path Type Description
Intezer.Analysis.ID string Intezer analysis id
Intezer.Analysis.Status string status of the analysis
Intezer.Analysis.Type string type of the analysis
URL.Data string The submitted Url
URL.Malicious.Vendor string For malicious Url, the vendor that made the decision
URL.Metadata Unknown Metadata returned from Intezer analysis
URL.ExistsInIntezer Boolean Does the url exists on intezer

Command Example

!intezer-analyze-url url="<url>"

Context Example

{
    "Intezer.Analysis": {
        "Status": "Created", 
        "type": "Url", 
        "ID": "59e2f081-45f3-4822-bf45-407670dcb4d7"
    }
}

Human Readable Output

Analysis created successfully: 59e2f081-45f3-4822-bf45-407670dcb4d7

intezer-get-latest-report


Checks file reputation of the given hash, supports SHA256, SHA1 and MD5 by looking at the latest available report

Base Command

intezer-get-latest-report

Input

Argument Name Description Required
file_hash Hash of the file to query. Supports SHA256, MD5 and SHA1. Required

Context Output

Path Type Description
File.SHA256 string Hash SHA256
File.Malicious.Vendor string For malicious files, the vendor that made the decision
DBotScore.Indicator string The indicator we tested
DBotScore.Type string The type of the indicator
DBotScore.Vendor string Vendor used to calculate the score
DBotScore.Score number The actual score
File.Metadata Unknown Metadata returned from Intezer analysis (analysis id, analysis url, family, family type, sha256, verdict, sub_verdict). Metadata will be returned only for supported files.
File.ExistsInIntezer Boolean Does the file exists on intezer genome database

Command Example

intezer-get-latest-report file_hash="8cbf90aeab2c93b2819fcfd6262b2cdb"

Context Example

{
    "DBotScore": {
        "Vendor": "Intezer", 
        "Indicator": "<some sha>>", 
        "Score": 0, 
        "Type": "hash"
    }, 
    "File": {
        "ExistsInIntezer": true, 
        "SHA256": "<some sha256>", 
        "Metadata": {
            "analysis_id": "006c54ba-3159-43a0-98a0-1c5032145f47", 
            "sub_verdict": "known_malicious", 
            "analysis_url": "https://analyze.intezer.com/analyses/006c54ba-3159-43a0-98a0-1c5032145f47", 
            "verdict": "malicious", 
            "family_id": "0b13c0d4-7779-4c06-98fa-4d33ca98f8a9",
            "family_name": "WannaCry",
            "sha256": "<some sha256>",
            "is_private": true, 
            "analysis_time": "Wed, 19 Jun 2019 07:48:12 GMT"
        }
    }
}

Human Readable Output

Intezer File analysis result
----
SHA256: some-sha256
Verdict: malicious (known_malicious)
Family: WannaCry


Analysis Report
---
analysis_id 006c54ba-3159-43a0-98a0-1c5032145f47
analysis_time Tue, 29 Jun 2021 13:40:01 GMT
analysis_url https://analyze.intezer.com/analyses/006c54ba-3159-43a0-98a0-1c5032145f47
family_id 0b13c0d4-7779-4c06-98fa-4d33ca98f8a9
family_name WannaCry
is_private false
sha256          some-sha256
sub_verdict known_malicious
verdict         malicious

intezer-analyze-by-file


Checks file reputation for uploaded file (up to 150MB)

Base Command

intezer-analyze-by-file

Input

Argument Name Description Required
file_entry_id The file entry id to upload. Required
related_alert_ids An array of alert ids to associate with the file analysis. Required

Context Output

Path Type Description
Intezer.Analysis.ID string Intezer analysis id
Intezer.Analysis.Status string status of the analysis
Intezer.Analysis.Type string type of the analysis
File.SHA256 string Hash SHA256
File.Malicious.Vendor string For malicious files, the vendor that made the decision
File.Metadata Unknown Metadata returned from Intezer analysis (analysis id, analysis url, family, family type, sha256, verdict, sub_verdict). Metadata will be returned only for supported files.
File.ExistsInIntezer Boolean Does the file exists on intezer genome database

Command Example

intezer-analyze-by-file file_entry_id=1188@6

Context Example

{
    "Intezer.Analysis": {
        "Status": "Created", 
        "type": "File", 
        "ID": "675515a1-62e9-4d55-880c-fd46a7963a56"
    }
}

Human Readable Output

Analysis created successfully: 675515a1-62e9-4d55-880c-fd46a7963a56

intezer-get-endpoint-analysis-result


Check the endpoint analysis status and get analysis result, supports polling.

Base Command

intezer-get-endpoint-analysis-result

Input

Argument Name Description Required
analysis_id The analysis ID we want to get results for. Required
wait_for_result Waits for analysis result, support polling Optional
interval Number of seconds between poll requests Optional
timeout Number of seconds until polling timeout Optional

Context Output

Path Type Description
DBotScore.Indicator string The indicator we tested
DBotScore.Type string The type of the indicator
DBotScore.Vendor string Vendor used to calculate the score
DBotScore.Score number The actual score
Endpoint.Metadata Unknown Metadata returned from Intezer analysis (endpoint analysis id, endpoint analysis url, families, verdict, host_name)

Command Example

intezer-get-endpoint-analysis-result analysis_id="9e3acdc3-b7ea-412b-88ae-7103eebc9398" wait_for_result="true"

intezer-get-url-analysis-result


Check the url analysis status and get analysis result, supports polling.

Base Command

intezer-get-url-analysis-result

Input

Argument Name Description Required
analysis_id The analysis ID we want to get results for. Required
wait_for_result Waits for analysis result, support polling Optional
interval Number of seconds between poll requests Optional
timeout Number of seconds until polling timeout Optional

Context Output

Path Type Description
DBotScore.Indicator string The indicator we tested
DBotScore.Type string The type of the indicator
DBotScore.Vendor string Vendor used to calculate the score
DBotScore.Score number The actual score
URL.Data string The submitted Url
URL.Malicious.Vendor string For malicious Url, the vendor that made the decision
URL.Metadata Unknown Metadata returned from Intezer analysis
URL.ExistsInIntezer Boolean Does the url exists on intezer

Command Example

intezer-get-url-analysis-result analysis_id="9e3acdc3-b7ea-412b-88ae-7103eebc9398" wait_for_result="true"

intezer-get-file-analysis-result


Check the file analysis status and get analysis result, supports polling.

Base Command

intezer-get-file-analysis-result

Input

Argument Name Description Required
analysis_id The analysis ID we want to get results for. Required
wait_for_result Waits for analysis result, support polling Optional
interval Number of seconds between poll requests Optional
timeout Number of seconds until polling timeout Optional

Context Output

Path Type Description  
DBotScore.Indicator string The indicator we tested  
DBotScore.Type string The type of the indicator  
DBotScore.Vendor string Vendor used to calculate the score  
DBotScore.Score number The actual score  
File.SHA256 string Hash SHA256  
File.SHA1 string Hash SHA1  
File.MD5 string Hash MD5  
File.Malicious.Vendor string For malicious files, the vendor that made the decision  
File.Metadata Unknown Metadata returned from Intezer analysis (analysis id, analysis url, family, family type, sha256, verdict, sub_verdict). Metadata will be returned only for supported files.  
File.ExistsInIntezer Boolean Does the file exists on intezer genome database  

Command Example

intezer-get-file-analysis-result analysis_id="9e3acdc3-b7ea-412b-88ae-7103eebc9398" wait_for_result="true"

intezer-get-analysis-result


Check the analysis status and get analysis result, support file and endpoint analysis

Base Command

intezer-get-analysis-result

Input

Argument Name Description Required
analysis_id The analysis ID we want to get results for. Optional
analysis_type The type of the analysis. Possible values are: File, Endpoint, Url. Default is File. Optional
indicator_name indicator to classify. Optional

Context Output

Path Type Description
DBotScore.Indicator string The indicator we tested
DBotScore.Type string The type of the indicator
DBotScore.Vendor string Vendor used to calculate the score
DBotScore.Score number The actual score
File.SHA256 string Hash SHA256
File.SHA1 string Hash SHA1
File.MD5 string Hash MD5
File.Malicious.Vendor string For malicious files, the vendor that made the decision
File.Metadata Unknown Metadata returned from Intezer analysis (analysis id, analysis url, family, family type, sha256, verdict, sub_verdict). Metadata will be returned only for supported files.
File.ExistsInIntezer Boolean Does the file exists on intezer genome database
URL.Data string The submitted Url
Url.URL string The submitted Url (deprecated)
URL.Malicious.Vendor string For malicious Url, the vendor that made the decision
Url.Malicious.Vendor string For malicious Url, the vendor that made the decision (deprecated)
URL.Metadata Unknown Metadata returned from Intezer analysis
Url.Metadata Unknown Metadata returned from Intezer analysis (deprecated)
URL.ExistsInIntezer Boolean Does the url exists on intezer
Url.ExistsInIntezer Boolean Does the url exists on intezer (deprecated)
Endpoint.Metadata Unknown Metadata returned from Intezer analysis (endpoint analysis id, endpoint analysis url, families, verdict, host_name)

Command Example

intezer-get-analysis-result analysis_id="9e3acdc3-b7ea-412b-88ae-7103eebc9398"

Context Example

{
    "DBotScore": {
        "Vendor": "Intezer", 
        "Indicator": "<some sha>>", 
        "Score": 0, 
        "Type": "hash"
    }, 
    "File": {
        "ExistsInIntezer": true, 
        "SHA256": "<some sha256>", 
        "Metadata": {
            "analysis_id": "006c54ba-3159-43a0-98a0-1c5032145f47", 
            "sub_verdict": "known_malicious", 
            "analysis_url": "https://analyze.intezer.com/analyses/006c54ba-3159-43a0-98a0-1c5032145f47", 
            "verdict": "malicious", 
            "family_id": "0b13c0d4-7779-4c06-98fa-4d33ca98f8a9",
            "family_name": "WannaCry",
            "sha256": "<some sha256>",
            "is_private": true, 
            "analysis_time": "Wed, 19 Jun 2019 07:48:12 GMT"
        }
    },
    "Url: {
        "ExistsInIntezer": true,
        "URL": "foo.com",
        "Metadata": {
        "analysis_id": "70d09f68-c7a3-43a3-a8de-07ec31fbf4ed",
        "domain_info": {
            "creation_date": "1997-08-13 04:00:00.000000",
            "domain_name": "foo.com",
            "registrar": "TUCOWS, INC."
        },
        "indicators": [
        {
            "classification": "informative",
            "text": "URL is accessible"
        },
        {
            "classification": "informative",
            "text": "Assigned IPv4 domain"
        },
        {
            "classification": "informative",
            "text": "Vaild IPv4 domain"
        }
        ],
        "ip": "34.206.39.153",
        "redirect_chain": [
        {
            "response_status": 301,
            "url": "https://foo.com/"
        },
        {
            "response_status": 200,
            "url": "http://www.foo.com/"
        }
        ],
        "scanned_url": "http://www.foo.com/",
        "submitted_url": "foo.com",
        "downloaded_file": {
            "analysis_id": "8db9a401-a142-41be-9a31-8e5f3642db62",
            "analysis_summary": {
               "verdict_description": "This file contains code from malicious software, therefore it's very likely that it's malicious.",
               "verdict_name": "malicious",
               "verdict_title": "Malicious",
               "verdict_type": "malicious"
            },
            "sha256": "4293c1d8574dc87c58360d6bac3daa182f64f7785c9d41da5e0741d2b1817fc7"
         },
        "summary": {
            "description": "No suspicious activity was detected for this URL",
            "title": "No Threats",
            "verdict_name": "no_threats",
            "verdict_type": "no_threats"
        }
    }
}

Human Readable Output

Intezer File analysis result
----
SHA256: some-sha256
Verdict: malicious (known_malicious)
Family: WannaCry


Analysis Report
---
analysis_id 006c54ba-3159-43a0-98a0-1c5032145f47
analysis_time Tue, 29 Jun 2021 13:40:01 GMT
analysis_url https://analyze.intezer.com/analyses/006c54ba-3159-43a0-98a0-1c5032145f47
family_id 0b13c0d4-7779-4c06-98fa-4d33ca98f8a9
family_name WannaCry
is_private false
sha256          some-sha256
sub_verdict known_malicious
verdict         malicious

intezer-get-sub-analyses


Get a list of the analysis sub analyses

Base Command

intezer-get-sub-analyses

Input

Argument Name Description Required
analysis_id The analysis ID we want to get the sub analyses for. Required

Context Output

Path Type Description
Intezer.Analysis.ID string Intezer analysis id
Intezer.Analysis.SubAnalysesIDs Unknown List of all sub analyses of the give analysis

Command Example

intezer-get-sub-analyses analysis_id=006c54ba-3159-43a0-98a0-1c5032145f47

Context Example

{
    "Intezer.Analysis": {
        "Status": "Done", 
        "type": "File", 
        "ID": "675515a1-62e9-4d55-880c-fd46a7963a56",
        "SubAnalysesIDs": [
            "2bf5baa9-6964-4171-b060-5e3d8de8741f"
        ]
    }
}

Human Readable Output

Sub Analyses -
[
...
List of analyses ids
...
]

intezer-get-family-info


Get family information from Intezer Analyze

Base Command

intezer-get-family-info

Input

Argument Name Description Required
family_id The Family ID. Required

Context Output

Path Type Description
Intezer.Family.ID string Family id in intezer genome database
Intezer.Family.Name string Family name
Intezer.Family.Type string Family Type

Command Example

intezer-get-family-info family_id=006c54ba-3159-43a0-98a0-1c5032145f47

Context Example

{
    "Intezer.Family": {
        "ID": "e710e4b3-3dd1-40ff-be74-9d8a95466ae4", 
        "Type": "malware", 
        "Name": "CobaltStrike"
    }
}

Human Readable Output

Family Info
---

FamilyId    006c54ba-3159-43a0-98a0-1c5032145f47
FamilyName  Some Family Name
FamilyType  Malware

intezer-get-analysis-code-reuse


Get All code reuse report for an analysis or sub analysis
To get the code reuse results of a sub analysis you also must specify the “parent analysis”,

For example - If you ran the command intezer-get-sub-analyses analysis_id=123
and got the sub analysis 456, you need to specify both in the command

Base Command

intezer-get-analysis-code-reuse

Input

Argument Name Description Required
analysis_id The analysis ID (parent analysis in case we’re trying to get sub abalysis) we want to get the code reuse for. Required
sub_analysis_id The Sub Analysis we want to get the code reuse for. Optional

Context Output

Path Type Description
Intezer.Analysis.ID string The composed analysis ID
Intezer.Analysis.CodeReuse Unknown General Code Reuse of the analysis
Intezer.Analysis.CodeReuseFamilies Unknown List of the families appearing in the code reuse
Intezer.Analysis.SubAnalyses.CodeReuse Unknown General Code Reuse of the analysis
Intezer.Analysis.SubAnalyses.CodeReuseFamilies Unknown List of the families appearing in the code reuse
Intezer.Analysis.SubAnalyses.RootAnalysis string The Composed analysis id

Command Example

# Get the code reuse of an analysis
intezer-get-analysis-code-reuse analysis_id=<Root analysis>

# Get the root analysis sub analyses
intezer-get-sub-analyses analysis_id=<Root analysis>

# Use one of the results to get the sub analysis code reuse
intezer-get-analysis-code-reuse analysis_id=<Root analysis> sub_analysis_id=<Sub Analysis Id>

Context Example

{
    "Intezer.Analysis": {
        "Status": "Done", 
        "type": "File", 
        "ID": "675515a1-62e9-4d55-880c-fd46a7963a56",
        "SubAnalyses": [
            {
                "ID": "Some sub analysis id",
                "RootAnalysis": "675515a1-62e9-4d55-880c-fd46a7963a56",
                "CodeReuse": {
                    "common_gene_count": 10,
                    "gene_count": 100,
                    "gene_type": "native_windows",
                    "unique_gene_count": 50
                },
                "CodeReuseFamilies": [
                    {
                        "family_id": "5be245ca-793c-4991-9329-c42d6365a530",
                        "family_name": "Microsoft Corporation",
                        "family_type": "application",
                        "reused_gene_count": 8
                    }
                ]
            }
        ]
    }
}

Human Readable Output

This will show information about the analysis code reuse and families

Code Reuse
---
common_gene_count   544
gene_count          543
gene_type           native_windows
unique_gene_count   0

Families:
---

WannaCry
family_id         0b13c0d4-7779-4c06-98fa-4d33ca98f8a9
family_name         WannaCry
family_type         malware
reused_gene_count 362

Lazarus
family_id         7ae9c0f1-5e81-4ed1-928d-d966a1b1525c
family_name         Lazarus
family_type         malware
reused_gene_count 33

... More Families if available

intezer-get-analysis-metadata


Get metadata for an analysis or sub analysis
To get the metadata of a sub analysis you also must specify the “parent analysis”,

For example - If you ran the command intezer-get-sub-analyses analysis_id=123
and got the sub analysis 456, you need to specify both in the command

Base Command

intezer-get-analysis-metadata

Input

Argument Name Description Required
analysis_id The analysis ID we want to get the metadata for. Required
sub_analysis_id The Sub Analysis we want to get the metadata for. Optional

Context Output

Path Type Description
Intezer.Analysis.ID string The composed analysis ID
Intezer.Analysis.Metadata Unknown The Analysis metadata
Intezer.Analysis.SubAnalyses.Metadata Unknown The Sub Analysis metadata

Command Example

# Get the metadata of an analysis
intezer-get-analysis-metadata analysis_id=<Root analysis>

# Get the root analysis sub analyses
intezer-get-sub-analyses analysis_id=<Root analysis>

# Use one of the results to get the sub analysis code reuse
intezer-get-analysis-metadata analysis_id=<Root analysis> sub_analysis_id=<Sub Analysis Id>

Context Example

{
    "Intezer.Analysis": {
        "Status": "Done", 
        "type": "File", 
        "ID": "675515a1-62e9-4d55-880c-fd46a7963a56",
        "SubAnalyses": [
            {
                "ID": "some sub analyses id",
                "RootAnalysis": "675515a1-62e9-4d55-880c-fd46a7963a56",
                "Metadata": {
                    "sha1": "<sha1>",
                    "sha256": "<sha256>",
                    "md5": "<md5>",
                    "product": "product name",
                    "product_version": "5.4",
                    "ssdeep": "<ssdeep>",
                    "size_in_bytes": 15540,
                    "architecture": "i386",
                    "original_filename": "myfile.exe",
                    "compilation_timestamp": "2019:07:26 18:23:19+00:00",
                    "file_type": "pe",
                    "company": "Microsoft"
                }
            }
        ]
    }
}

Human Readable Output

Analysis Metadata
---

architecture         i386
company                 Microsoft Corporation
compilation_timestamp 2009:07:13 23:19:35+00:00
file_type         pe
md5                 md5
original_filename LODCTR.EXE
product                 Microsoft® Windows® Operating System
product_version         6.1.7600.16385 ^^^
sha1                 sha1
sha256                 sha256
size_in_bytes         245760
ssdeep                 ssdeep

intezer-get-analysis-iocs


Gets the list of network and files IOCs of a specific analysis id.

Base Command

intezer-get-analysis-iocs

Input

Argument Name Description Required
analysis_id The analysis ID we want to get the IOCs for. Required

Context Output

Path Type Description
Intezer.Analysis.ID string The composed analysis ID
Intezer.Analysis.IOCs Dict The Analysis IOCs

Context Example

{
    "Intezer.Analysis": {
        "Status": "Done",
        "type": "File",
        "ID": "675515a1-62e9-4d55-880c-fd46a7963a56",
        "IOCs": {
            "files": [
                {
                    "path": "test_file_1.csv",
                    "sha256": "eeb1199f7db006e4d20086171cc312cf5bdf53682cc37997223ad0c15a27dc88",
                    "verdict": "malicious",
                    "family": "Turla",
                    "type": "Main file"
                }
            ],
            "network": [
                {
                    "ioc": "1.1.1.1",
                    "source": [
                        "Network communication"
                    ],
                    "type": "ip"
                },
                {
                    "ioc": "raw.exampledomain.com",
                    "source": [
                        "Network communication"
                    ],
                    "type": "domain"
                }
            ]
        }
    }
}

Human Readable Output

### Network IOCs

| ioc                   | source                | type   |
|-----------------------|-----------------------|--------|
| 1.1.1.1.1             | Network communication | ip     |
| raw.exampledomain.com | Network communication | domain |

### Files IOCs

| family  | path             | sha256                                                           | type           | verdict   |
|---------|------------------|------------------------------------------------------------------|----------------|-----------|
| Turla   | test_file_1.csv  | eeb1199f7db006e4d20086171cc312cf5bdf53682cc37997223ad0c15a27dc88 | Main file      | malicious |

intezer-submit-alert


Submit a new alert, including the raw alert information, to Intezer for processing.

Base Command

intezer-submit-alert

Input

Argument Name Description Required
raw_alert The raw alert as it stored in the context. Required
mapping The mapping for the raw alert data. Required
source The source of the alert. Required

Context Output

Path Type Description
Intezer.Alert.ID string The Alert ID
Intezer.Alert.Status string The status of the Alert

Context Example

{
    "Intezer.Alert": {
        "Status": "Done",
        "ID": "675515a1-62e9-4d55-880c-fd46a7963a56"
    }
}

intezer-submit-suspected-phishing-email


Submit a suspicious phishing email in a raw format (.MSG or .EML) to Intezer for processing.

Base Command

intezer-submit-suspected-phishing-email

Input

Argument Name Description Required
email_file_entry_id The email file entry id to upload. Required

Context Output

Path Type Description
Intezer.Alert.ID string The Alert ID
Intezer.Alert.Status string The status of the Alert

Context Example

{
    "Intezer.Alert": {
        "Status": "Done",
        "ID": "675515a1-62e9-4d55-880c-fd46a7963a56"
    }
}

intezer-get-alert-result


Get an ingested alert triage and response information using alert ID.

Base Command

intezer-get-alert-result

Input

Argument Name Description Required
alert_id The alert id to query. Required
wait_for_result Waits for alert result, support polling. Optional

Context Output

Path Type Description
Intezer.Alert.ID string The Alert ID
Intezer.Alert.Status string The Alert status
Intezer.Alert.Result Object The full report of the alert
Intezer.Alert.Result.intezer_alert_url Object The url for the alert result on Intezer Analyze
DBotScore.Indicator string The indicator we tested
DBotScore.Type string The type of the indicator
DBotScore.Vendor string Vendor used to calculate the score
DBotScore.Score string The actual score
File.SHA256 string Hash SHA256
File.SHA1 string Hash SHA1
File.MD5 string Hash MD5
URL.Data string The tested URL
URL.Malicious.Vendor string For malicious URL, the vendor that made the decision
URL.Relationships object The relationships between two urls
Intezer.Alert.Result.raw_alert object The raw alert as submitted to Intezer
Intezer.Alert.Result.triage_result.alert_verdict_display string The verdict of the alert
Intezer.Alert.Result.source_display string The calculated verdict of the Alert
Intezer.Alert.Result.triage_result.risk_category_display string The risk category of the Alert
Intezer.Alert.Result.response.user_recommended_actions_display string The actions recommended by Intezer to be taken

Command Example

# Get an alert result
intezer-get-alert-result alert_id=<Alert ID> wait_for_result=true

Context Example

{
    "Intezer.Analysis": {
        "Status": "Done", 
        "ID": "675515a1-62e9-4d55-880c-fd46a7963a56",
        "DBotScore": {
            "Vendor": "Intezer", 
            "Indicator": "<some sha>>", 
            "Score": 0, 
            "Type": "file/url/domain/ip/endpoint"
            },
        "Result": {
            "alert": {'alert_id': '111223', 'alert_title': '111223', 'alert_url': None, 'creation_time': '2023-07-24T12:26:06',
               'creation_time_display': '24 Jul 23 | 12:26 UTC', 'device': {}, 'severity': 'high',
               'severity_display': 'High'},
            'alert_id': '111223',
            'alert_sub_types': ['custom'],
            'intezer_alert_url': 'https://analyze.intezer.com/alerts/111223',
            'raw_alert': {},
            'response': {'automated_response_actions': [],
                          'iocs': {'files': [
                              {'family': None,
                               'path': 'some_path.sample',
                               'sha256': '<hash>',
                               'type': 'main_file',
                               'verdict': 'malicious'}
                          ],
                              'network': [
                                  {'ioc': '101.111.222.333', 'source': ['Network communication'],
                                   'type': 'ip'},
                              ]},
                          'status': 'escalated', 'status_display': 'Escalated',
                          'user_recommended_actions': [],
                          'user_recommended_actions_display': ''},
            'scans': [{'collection_status': 'collected', 'file_analysis': {
                'analysis_id': '<some_analysis_id>', 'analysis_time': '2023-07-24T11:00:28',
                'analysis_url': 'https://analyze.intezer.com/analyses/<some_analysis_id>',
                'file_name': 'file_name.sample',
                'iocs': {'files': [
                    {'family': None, 'path': 'some_path.sample',
                     'sha256': '<hash_of_file>', 'type': 'main_file',
                     'verdict': 'malicious'}],
                    'network': [
                        {'ioc': 'https://3-4.oss-c.malicious.domain.com/md.exe', 'source': ['Network communication'],
                         'type': 'url'}]}, 'sha256': '<hash>',
                'sub_verdict': 'known_malicious', 'ttps': [
                    {'tactic': 'Command And Control', 'tactic_id': 'TA0011', 'technique': 'Encrypted Channel',
                     'technique_id': 'T1573'}], 'sender': 'cs', 'source': 'cs',
                'source_display': 'CrowdStrike',
                'triage_result': {'alert_verdict': 'confirmed_threat', 'alert_verdict_display': 'Confirmed Threat',
                                  'risk_category': 'generic_threat', 'risk_category_display': 'Generic Threat',
                                  'risk_level': 'high',
                                  'risk_score': 20, 'ttps': [
                        {'source': 'analysis', 'tactic': 'Command And Control', 'tactic_id': 'TA0011',
                         'technique': 'Encrypted Channel', 'technique_id': 'T1573'},
                        {'source': 'analysis', 'tactic': 'Execution', 'tactic_id': 'TA0002', 'technique': 'Shared Modules',
                         'technique_id': 'T1129'}]
                                  }}}]
            }
        ]
    }
}

Human Readable Output

### Intezer Alert Result

Verdict: Confirmed Threat
Risk category: Generic Threat
Alert Link: https://analyze.intezer.com/alerts/111223

Configuration parameters

  • APIKey — API Key (required)
  • AnalyzeBaseURL — Intezer Analyze Base URL
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)

Commands (16)

  • intezer-analyze-by-file

    Checks file reputation for uploaded file (up to 150MB).

  • intezer-analyze-by-hash

    Checks file reputation of the given hash, supports SHA256, SHA1 and MD5.

  • intezer-analyze-url

    Checks reputation of an Url.

  • intezer-get-alert-result

    Get an ingested alert triage and response information using alert ID.

  • intezer-get-analysis-code-reuse

    Get All code reuse report for an analysis. To get a sub analysis code-reuse you need to specify an analysis_id and a sub_analysis id!.

  • intezer-get-analysis-iocs

    Gets the list of network and files IOCs of a specific analysis id.

  • intezer-get-analysis-metadata

    Get analysis metadata. To get a sub analysis metadata you need to specify an analysis_id and a sub_analysis id!.

  • intezer-get-analysis-result

    Check the analysis status and get analysis result, support file and endpoint analysis.

  • intezer-get-endpoint-analysis-result

    Returns the analysis result.

  • intezer-get-family-info

    Get family information from Intezer Analyze.

  • intezer-get-file-analysis-result

    Returns the analysis result.

  • intezer-get-latest-report

    Checks file reputation of the given hash, supports SHA256, SHA1 and MD5 by looking at the latest available report.

  • intezer-get-sub-analyses

    Get a list of the analysis sub analyses.

  • intezer-get-url-analysis-result

    Returns the analysis result.

  • intezer-submit-alert

    Submit a new alert, including the raw alert information, to Intezer for processing.

  • intezer-submit-suspected-phishing-email

    Submit a suspicious phishing email in a raw format (.MSG or .EML) to Intezer for processing.

import tempfile
import uuid
from http import HTTPStatus
from unittest.mock import patch

import intezer_sdk.errors
import pytest
from CommonServerPython import *
from intezer_sdk import consts
from intezer_sdk.alerts import Alert
from intezer_sdk.analysis import FileAnalysis, UrlAnalysis
from intezer_sdk.api import IntezerApi
from intezer_sdk.consts import AlertStatusCode
from IntezerV2 import (
    analyze_by_hash_command,
    analyze_by_uploaded_file_command,
    analyze_url_command,
    check_analysis_status_and_get_results_command,
    check_is_available,
    enrich_dbot_and_display_alert_results,
    get_alert_result_command,
    get_analysis_code_reuse_command,
    get_analysis_iocs_command,
    get_analysis_metadata_command,
    get_analysis_sub_analyses_command,
    get_endpoint_analysis_result_command,
    get_family_info_command,
    get_file_analysis_result_command,
    get_latest_result_command,
    get_url_analysis_result_command,
    submit_alert_command,
    submit_suspected_phishing_email_command,
)

fake_api_key = str(uuid.uuid4())
intezer_api = IntezerApi(consts.API_VERSION, fake_api_key, consts.BASE_URL)

full_url = f"{consts.BASE_URL}{consts.API_VERSION}"


def _setup_access_token(requests_mock):
    requests_mock.post(f"{full_url}/get-access-token", json={"result": "access-token"})


# region analyze_by_hash_command
def test_analyze_by_hash_command_success(requests_mock):
    # Arrange
    analysis_id = "analysis-id"

    _setup_access_token(requests_mock)
    requests_mock.post(
        f"{full_url}/analyze-by-hash", status_code=HTTPStatus.CREATED, json={"result_url": f"/analyses/{analysis_id}"}
    )

    args = {"file_hash": "123test"}

    # Act
    command_results = analyze_by_hash_command(args, intezer_api)

    # Assert
    assert command_results.outputs["ID"] == analysis_id


def test_analyze_by_hash_command_success_polling_true(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis-id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.post(
        f"{full_url}/analyze-by-hash", status_code=HTTPStatus.CREATED, json={"result_url": f"/analyses/{analysis_id}"}
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
            },
            "status": "in_progress",
        },
    )

    args = {"file_hash": "123test", "wait_for_result": True}

    # Act
    command_results = analyze_by_hash_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == "Fetching Intezer analysis. Please wait..."


def test_analyze_by_hash_command_missing_hash(requests_mock):
    # Arrange

    _setup_access_token(requests_mock)
    requests_mock.post(f"{full_url}/analyze-by-hash", status_code=HTTPStatus.NOT_FOUND)

    file_hash = "123test"
    args = {"file_hash": file_hash}

    # Act
    command_results = analyze_by_hash_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == f"The Hash {file_hash} was not found on Intezer genome database"


def test_analyze_by_hash_command_already_running(requests_mock):
    # Arrange
    _setup_access_token(requests_mock)
    requests_mock.post(f"{full_url}/analyze-by-hash", json={}, status_code=HTTPStatus.CONFLICT)

    file_hash = "123test"
    args = {"file_hash": file_hash}

    # Act
    command_results = analyze_by_hash_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == "Analysis is still in progress"


# endregion

# region get_latest_result_command


def test_get_latest_result_command_success(requests_mock):
    # Arrange
    sha256 = "sha256"
    md5 = "md5"
    sha1 = "sha1"
    analysis_id = "analysis_id"
    root_sub_analysis = "root_analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/files/{sha256}",
        json={
            "result": {
                "analysis_id": analysis_id,
                "sub_verdict": "trusted",
                "sha256": sha256,
                "verdict": "trusted",
                "analysis_url": "bla",
            }
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256, "source": "root", "sub_analysis_id": root_sub_analysis}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{root_sub_analysis}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5,
            "sha1": sha1,
            "sha256": sha256,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    args = {"file_hash": sha256}

    # Act
    command_results = get_latest_result_command(args, intezer_api)

    # Assert
    indicators = [dbotscore["Indicator"] for dbotscore in command_results.outputs[outputPaths["dbotscore"]]]

    assert len(command_results.outputs) == 3
    assert all(indicator in indicators for indicator in [sha256, md5, sha1])


def test_get_latest_result_command_file_missing(requests_mock):
    # Arrange
    sha256 = "sha256"
    _setup_access_token(requests_mock)
    requests_mock.get(f"{full_url}/files/{sha256}", status_code=HTTPStatus.NOT_FOUND)

    args = {"file_hash": sha256}

    # Act
    command_results = get_latest_result_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == f"The Hash {sha256} was not found on Intezer genome database"


# endregion

# region analyze_by_uploaded_file_command


def test_analyze_by_uploaded_file_command_success(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis-id"

    _setup_access_token(requests_mock)
    requests_mock.post(f"{full_url}/analyze", status_code=HTTPStatus.CREATED, json={"result_url": f"/analyses/{analysis_id}"})

    args = {"file_entry_id": "123@123"}

    # Act
    with tempfile.NamedTemporaryFile() as file:
        file_path_patch = mocker.patch("demistomock.getFilePath")
        file_path_patch.return_value = {"path": file.name, "name": file.name}
        command_results = analyze_by_uploaded_file_command(args, intezer_api)

    # Assert
    assert command_results.outputs["ID"] == analysis_id
    assert command_results.scheduled_command is None
    assert command_results.outputs == {"ID": analysis_id, "Status": "Created", "Type": "File"}


def test_analyze_by_uploaded_file_command_polling_true(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis-id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.post(f"{full_url}/analyze", status_code=HTTPStatus.CREATED, json={"result_url": f"/analyses/{analysis_id}"})

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
            },
            "status": "in_progress",
        },
    )

    args = {"file_entry_id": "123@123", "wait_for_result": True}

    # Act
    with tempfile.NamedTemporaryFile() as file:
        file_path_patch = mocker.patch("demistomock.getFilePath")
        file_path_patch.return_value = {"path": file.name, "name": file.name}
        command_results = analyze_by_uploaded_file_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == "Fetching Intezer analysis. Please wait..."
    assert command_results.outputs is None


def test_analyze_by_uploaded_file_command_analysis_already_running(requests_mock, mocker):
    # Arrange

    _setup_access_token(requests_mock)
    requests_mock.post(f"{full_url}/analyze", json={}, status_code=HTTPStatus.CONFLICT)

    args = {"file_entry_id": "123@123"}

    # Act
    with tempfile.NamedTemporaryFile() as file:
        file_path_patch = mocker.patch("demistomock.getFilePath")
        file_path_patch.return_value = {"path": file.name, "name": file.name}
        command_results = analyze_by_uploaded_file_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == "Analysis is still in progress"


# endregion

# region check_analysis_status_and_get_results_command


def test_check_analysis_status_and_get_results_command_single_success(requests_mock):
    # Arrange
    sha256 = "sha256"
    md5 = "md5"
    sha1 = "sha1"
    analysis_id = "analysis_id"
    root_sub_analysis = "root_sub_analysis"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
                "sub_verdict": "trusted",
                "sha256": sha256,
                "verdict": "trusted",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256, "source": "root", "sub_analysis_id": root_sub_analysis}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{root_sub_analysis}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5,
            "sha1": sha1,
            "sha256": sha256,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    args = {"analysis_id": analysis_id}

    # Act
    command_results_list = check_analysis_status_and_get_results_command(args, intezer_api)

    # Assert
    assert len(command_results_list) == 1

    indicators = [dbotscore["Indicator"] for dbotscore in command_results_list[0].outputs[outputPaths["dbotscore"]]]
    assert all(indicator in indicators for indicator in [sha256, md5, sha1])


def test_check_analysis_status_and_get_results_url_command_single_success(requests_mock):
    # Arrange
    url = "https://intezer.com"
    scanned_url = "https://intezer.com/r"
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    file_analysis_id = "8db9a401-a142-41be-9a31-8e5f3642db62"
    file_root_analysis_id = "root_analysis_id"
    sha256 = "sha256"
    md5 = "md5"
    sha1 = "sha1"
    requests_mock.get(
        f"{full_url}/url/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
                "summary": {"title": "malicious", "verdict_name": "malicious", "verdict_type": "malicious"},
                "indicators": [
                    {"classification": "informative", "text": "URL is accessible"},
                    {"classification": "informative", "text": "Assigned IPv4 domain"},
                    {"classification": "informative", "text": "Vaild IPv4 domain"},
                    {"classification": "suspicious", "text": "suspicious"},
                    {"classification": "malicious", "text": "malicious"},
                ],
                "redirect_chain": [
                    {"response_status": 301, "url": "https://foo.com/"},
                    {"response_status": 200, "url": "http://www.foo.com/"},
                ],
                "scanned_url": scanned_url,
                "submitted_url": url,
                "downloaded_file": {
                    "analysis_id": file_analysis_id,
                    "analysis_summary": {
                        "verdict_description": "This file contains code from malicious s"
                        "oftware, therefore it's very likely that it's malicious.",
                        "verdict_name": "malicious",
                        "verdict_title": "Malicious",
                        "verdict_type": "malicious",
                    },
                    "sha256": "4293c1d8574dc87c58360d6bac3daa182f64f7785c9d41da5e0741d2b1817fc7",
                },
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{file_analysis_id}",
        json={
            "result": {
                "analysis_id": file_analysis_id,
                "sub_verdict": "malicious",
                "sha256": "a" * 64,
                "verdict": "malicious",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{file_analysis_id}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256, "source": "root", "sub_analysis_id": file_root_analysis_id}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{file_analysis_id}/sub-analyses/{file_root_analysis_id}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5,
            "sha1": sha1,
            "sha256": sha256,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    args = {"analysis_id": analysis_id, "analysis_type": "Url"}

    # Act
    command_results_list = check_analysis_status_and_get_results_command(args, intezer_api)

    # Assert
    assert len(command_results_list) == 1
    assert len(command_results_list[0].outputs[outputPaths["dbotscore"]]) == 5

    first_result = command_results_list[0]
    indicators = [dbotscore["Indicator"] for dbotscore in first_result.outputs[outputPaths["dbotscore"]]]
    assert all(indicator in indicators for indicator in [sha256, md5, sha1, url, scanned_url])
    assert all(dbot["Score"] == 3 for dbot in first_result.outputs[outputPaths["dbotscore"]])


def test_check_analysis_status_and_get_results_command_single_success_endpoint(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    computer_name = "kfir-pc"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/endpoint-analyses/{analysis_id}",
        json={
            "status": "succeeded",
            "result": {
                "analysis_id": analysis_id,
                "sub_verdict": "trusted",
                "verdict": "trusted",
                "analysis_url": "bla",
                "computer_name": computer_name,
                "scan_start_time": "Wed, 19 Jun 2022 07:48:12 GMT",
            },
        },
    )

    args = {"analysis_id": analysis_id, "analysis_type": "Endpoint"}

    # Act
    command_results_list = check_analysis_status_and_get_results_command(args, intezer_api)

    # Assert
    assert len(command_results_list) == 1

    first_result = command_results_list[0]
    assert first_result.outputs[outputPaths["dbotscore"]]["Indicator"] == computer_name
    assert first_result.outputs["Intezer.Analysis(val.ID && val.ID == obj.ID)"]["ID"] == analysis_id


def test_get_endpoint_analysis_missing(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(f"{full_url}/endpoint-analyses/{analysis_id}", status_code=HTTPStatus.NOT_FOUND)

    args = {"analysis_id": analysis_id, "analysis_type": "Endpoint"}

    # Act
    command_results = check_analysis_status_and_get_results_command(args, intezer_api)

    # Assert
    assert command_results[0].readable_output == f"Could not find the endpoint analysis '{analysis_id}'"


def test_check_analysis_status_and_get_results_command_multiple_analyses(requests_mock):
    # Arrange
    sha256_1 = "sha256"
    sha1_1 = "sha1"
    md5_1 = "md5"
    analysis_id_1 = "analysis_id"
    root_analysis_id_1 = "root_analysis_id"

    sha256_2 = "sha256-2"
    sha1_2 = "sha1-2"
    md5_2 = "md5-2"
    analysis_id_2 = "analysis_id-2"
    root_analysis_id_2 = "root_analysis_id_2"

    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_1}",
        json={
            "result": {
                "analysis_id": analysis_id_1,
                "sub_verdict": "trusted",
                "sha256": sha256_1,
                "verdict": "trusted",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_1}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256_1, "source": "root", "sub_analysis_id": root_analysis_id_1}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_1}/sub-analyses/{root_analysis_id_1}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5_1,
            "sha1": sha1_1,
            "sha256": sha256_1,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_2}",
        json={
            "result": {
                "analysis_id": analysis_id_2,
                "sub_verdict": "trusted",
                "sha256": sha256_2,
                "verdict": "trusted",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_2}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256_2, "source": "root", "sub_analysis_id": root_analysis_id_2}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_2}/sub-analyses/{root_analysis_id_2}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5_2,
            "sha1": sha1_2,
            "sha256": sha256_2,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    args = {"analysis_id": f"{analysis_id_1},{analysis_id_2}"}

    # Act
    command_results_list = check_analysis_status_and_get_results_command(args, intezer_api)

    # Assert
    assert len(command_results_list) == 2

    first_result = command_results_list[0]
    indicators = [dbotscore["Indicator"] for dbotscore in first_result.outputs[outputPaths["dbotscore"]]]
    assert all(indicator in indicators for indicator in [sha256_1, md5_1, sha1_1])

    second_result = command_results_list[1]
    indicators = [dbotscore["Indicator"] for dbotscore in second_result.outputs[outputPaths["dbotscore"]]]
    assert all(indicator in indicators for indicator in [sha256_2, md5_2, sha1_2])


def test_check_analysis_status_and_get_results_command_multiple_analyses_one_fails(requests_mock):
    # Arrange
    sha256_1 = "sha256"
    md5_1 = "md5"
    sha1_1 = "sha1"
    analysis_id_1 = "analysis_id"
    root_analysis_id_1 = "root_analysis_id"

    analysis_id_2 = "analysis_id-2"

    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_1}",
        json={
            "result": {
                "analysis_id": analysis_id_1,
                "sub_verdict": "trusted",
                "sha256": sha256_1,
                "verdict": "trusted",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_1}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256_1, "source": "root", "sub_analysis_id": root_analysis_id_1}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_1}/sub-analyses/{root_analysis_id_1}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5_1,
            "sha1": sha1_1,
            "sha256": sha256_1,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id_2}",
        status_code=HTTPStatus.NOT_FOUND,
    )

    args = {"analysis_id": f"{analysis_id_1},{analysis_id_2}"}

    # Act
    command_results_list = check_analysis_status_and_get_results_command(args, intezer_api)

    # Assert
    assert len(command_results_list) == 2

    first_result = command_results_list[0]
    indicators = [dbotscore["Indicator"] for dbotscore in first_result.outputs[outputPaths["dbotscore"]]]
    assert all(indicator in indicators for indicator in [sha256_1, md5_1, sha1_1])

    second_result = command_results_list[1]
    assert second_result.readable_output == f"The Analysis {analysis_id_2} was not found on Intezer Analyze"


# endregion

# region get_analysis_sub_analyses_command


def test_get_analysis_sub_analyses_command_success(requests_mock):
    # Arrange
    sha256 = "sha256"
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
                "sub_verdict": "trusted",
                "sha256": sha256,
                "verdict": "trusted",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses",
        json={
            "sub_analyses": [
                {
                    "sub_analysis_id": "123123",
                    "source": "dynamic",
                    "sha256": "sha256",
                }
            ]
        },
    )

    args = {"analysis_id": analysis_id}

    # Act
    command_results = get_analysis_sub_analyses_command(args, intezer_api)

    # Assert
    assert len(command_results.outputs["SubAnalysesIDs"]) == 1


def test_get_analysis_sub_analyses_command_analysis_doesnt_exist(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(f"{full_url}/analyses/{analysis_id}", status_code=HTTPStatus.NOT_FOUND)

    args = {"analysis_id": analysis_id}

    # Act
    command_results = get_analysis_sub_analyses_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == f"The Analysis {analysis_id} was not found on Intezer Analyze"


# endregion


# region get_file_analysis_result_command
def test_get_file_analysis_result_command_success(requests_mock, mocker):
    # Arrange
    sha256 = "sha256"
    md5 = "md5"
    sha1 = "sha1"
    analysis_id = "analysis_id"
    root_sub_analysis = "root_sub_analysis"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
                "sub_verdict": "trusted",
                "sha256": sha256,
                "verdict": "trusted",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256, "source": "root", "sub_analysis_id": root_sub_analysis}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{root_sub_analysis}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5,
            "sha1": sha1,
            "sha256": sha256,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_file_analysis_result_command(args, intezer_api)

    # Assert
    indicators = [dbotscore["Indicator"] for dbotscore in command_result.outputs[outputPaths["dbotscore"]]]
    assert all(indicator in indicators for indicator in [sha256, md5, sha1])


def test_get_url_analysis_still_running_polling(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/url/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
            },
            "status": "in_progress",
        },
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_url_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command._args["analysis_id"] == analysis_id
    assert command_result.scheduled_command._args["hide_polling_output"]
    assert command_result.scheduled_command._args["wait_for_result"]


def test_get_url_analysis_result_command_analysis_failed(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)
    requests_mock.get(
        f"{full_url}/url/{analysis_id}",
        status_code=HTTPStatus.NOT_FOUND,
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_url_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.readable_output == f"The Analysis {analysis_id} was not found on Intezer Analyze"


# endregion


# region get_endpoint_analysis_result_command
def test_get_endpoint_analysis_still_running_polling(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/endpoint-analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
            },
            "status": "in_progress",
        },
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_endpoint_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command._args["analysis_id"] == analysis_id
    assert command_result.scheduled_command._args["hide_polling_output"]
    assert command_result.scheduled_command._args["wait_for_result"]


def test_get_endpoint_analysis_queued_polling(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/endpoint-analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
            },
            "status": "queued",
        },
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_endpoint_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command._args["analysis_id"] == analysis_id
    assert command_result.scheduled_command._args["hide_polling_output"]
    assert command_result.scheduled_command._args["wait_for_result"]


def test_get_endpoint_analysis_polling_false(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(f"{full_url}/endpoint-analyses/{analysis_id}", status_code=HTTPStatus.CONFLICT)

    args = {"analysis_id": analysis_id, "wait_for_result": False}

    # Act
    command_result = get_endpoint_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command is None
    assert command_result.outputs == {"ID": analysis_id, "Status": "InProgress", "Type": "Endpoint"}


def test_get_endpoint_analysis_result_command_analysis_missing(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(f"{full_url}/endpoint-analyses/{analysis_id}", status_code=HTTPStatus.NOT_FOUND)

    # Act
    args = {"analysis_id": analysis_id, "wait_for_result": True}
    command_result = get_endpoint_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.readable_output == f"Could not find the endpoint analysis '{analysis_id}'"


def test_get_endpoint_analysis_result_command_polling_true(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/endpoint-analyses/{analysis_id}",
        status_code=HTTPStatus.CONFLICT,
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_endpoint_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command._args["analysis_id"] == analysis_id
    assert command_result.scheduled_command._args["hide_polling_output"]


def test_get_endpoint_analysis_result_success(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"
    computer_name = "matan-pc"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/endpoint-analyses/{analysis_id}",
        json={
            "status": "succeeded",
            "result": {
                "analysis_id": analysis_id,
                "sub_verdict": "trusted",
                "verdict": "trusted",
                "analysis_url": "bla",
                "computer_name": computer_name,
                "scan_start_time": "Wed, 19 Jun 2022 07:48:12 GMT",
            },
        },
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_results = get_endpoint_analysis_result_command(args, intezer_api)

    # Assert
    assert command_results.outputs[outputPaths["dbotscore"]]["Indicator"] == computer_name
    assert command_results.outputs["Intezer.Analysis(val.ID && val.ID == obj.ID)"]["ID"] == analysis_id


def test_get_endpoint_analysis_result_http_error(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(f"{full_url}/endpoint-analyses/{analysis_id}", status_code=HTTPStatus.BAD_REQUEST)

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act + Assert
    with pytest.raises(Exception):
        get_endpoint_analysis_result_command(args, intezer_api)


# endregion


# region get_url_analysis_result_command
def test_get_url_analysis_result_command_success(requests_mock, mocker):
    # Arrange
    sha256 = "sha256"
    url = "https://foo.com"
    scanned_url = "https://foo.com"
    file_analysis_id = "file_analysis_id"
    md5 = "md5"
    sha1 = "sha1"
    analysis_id = "analysis_id"
    file_root_analysis_id = "file_root_analysis_id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/url/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
                "summary": {"title": "malicious", "verdict_name": "malicious", "verdict_type": "malicious"},
                "indicators": [
                    {"classification": "informative", "text": "URL is accessible"},
                    {"classification": "informative", "text": "Assigned IPv4 domain"},
                    {"classification": "informative", "text": "Vaild IPv4 domain"},
                    {"classification": "suspicious", "text": "suspicious"},
                    {"classification": "malicious", "text": "malicious"},
                ],
                "redirect_chain": [
                    {"response_status": 301, "url": "https://foo.com/"},
                    {"response_status": 200, "url": "http://www.foo.com/"},
                ],
                "scanned_url": scanned_url,
                "submitted_url": url,
                "downloaded_file": {
                    "analysis_id": file_analysis_id,
                    "analysis_summary": {
                        "verdict_description": "This file contains code from malicious s"
                        "oftware, therefore it's very likely that it's malicious.",
                        "verdict_name": "malicious",
                        "verdict_title": "Malicious",
                        "verdict_type": "malicious",
                    },
                    "sha256": "4293c1d8574dc87c58360d6bac3daa182f64f7785c9d41da5e0741d2b1817fc7",
                },
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{file_analysis_id}",
        json={
            "result": {
                "analysis_id": file_analysis_id,
                "sub_verdict": "malicious",
                "sha256": "a" * 64,
                "verdict": "malicious",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )

    requests_mock.get(
        f"{full_url}/analyses/{file_analysis_id}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256, "source": "root", "sub_analysis_id": file_root_analysis_id}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{file_analysis_id}/sub-analyses/{file_root_analysis_id}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5,
            "sha1": sha1,
            "sha256": sha256,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_url_analysis_result_command(args, intezer_api)

    # Assert
    assert len(command_result.outputs[outputPaths["dbotscore"]]) == 4

    indicators = [dbotscore["Indicator"] for dbotscore in command_result.outputs[outputPaths["dbotscore"]]]
    assert all(indicator in indicators for indicator in [sha256, md5, sha1, url, scanned_url])
    assert all(dbot["Score"] == 3 for dbot in command_result.outputs[outputPaths["dbotscore"]])


def test_get_url_analysis_result_command_failed(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/url/{analysis_id}",
        status_code=HTTPStatus.NOT_FOUND,
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_url_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.readable_output == f"The Analysis {analysis_id} was not found on Intezer Analyze"


def test_get_url_analysis_result_command_polling(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/url/{analysis_id}",
        status_code=HTTPStatus.CONFLICT,
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_url_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command._args["analysis_id"] == analysis_id
    assert command_result.scheduled_command._args["hide_polling_output"]


def test_get_file_analysis_polling_false(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(f"{full_url}/analyses/{analysis_id}", status_code=HTTPStatus.CONFLICT)

    args = {"analysis_id": analysis_id, "wait_for_result": False}

    # Act
    command_result = get_file_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command is None
    assert command_result.outputs == {"ID": analysis_id, "Status": "InProgress", "Type": "File"}


def test_get_file_analysis_result_command_analysis_failed(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        status_code=HTTPStatus.NOT_FOUND,
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_file_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.readable_output == f"The Analysis {analysis_id} was not found on Intezer Analyze"


def test_get_file_analysis_result_http_error(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(f"{full_url}/analyses/{analysis_id}", status_code=HTTPStatus.BAD_REQUEST)

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act + Assert
    with pytest.raises(Exception):
        get_file_analysis_result_command(args, intezer_api)


def test_get_file_analysis_still_running_polling(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
            },
            "status": "in_progress",
        },
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_file_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command._args["analysis_id"] == analysis_id
    assert command_result.scheduled_command._args["hide_polling_output"]
    assert command_result.scheduled_command._args["wait_for_result"]


def test_get_file_analysis_result_command_polling(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis_id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        status_code=HTTPStatus.CONFLICT,
    )

    args = {"analysis_id": analysis_id, "wait_for_result": True}

    # Act
    command_result = get_file_analysis_result_command(args, intezer_api)

    # Assert
    assert command_result.scheduled_command._args["analysis_id"] == analysis_id
    assert command_result.scheduled_command._args["hide_polling_output"]


# endregion

# region get_analysis_code_reuse_command


def test_get_analysis_code_reuse_command_success_root(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/root/code-reuse",
        json={"families": [{"family_id": "123", "family_name": "Name", "reused_gene_count": 123}], "unique_gene_count": 0},
    )

    args = {"analysis_id": analysis_id}

    # Act
    command_results = get_analysis_code_reuse_command(args, intezer_api)

    # Assert
    outputs = command_results.outputs["Intezer.Analysis(obj.ID == val.ID)"]
    assert outputs["ID"] == analysis_id
    assert len(outputs["CodeReuseFamilies"]) == 1
    assert "CodeReuse" in outputs


def test_get_analysis_code_reuse_command_success(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    sub_analysis_id = "sub_analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{sub_analysis_id}/code-reuse",
        json={"families": [{"family_id": "123", "family_name": "Name", "reused_gene_count": 123}], "unique_gene_count": 0},
    )

    args = {"analysis_id": analysis_id, "sub_analysis_id": sub_analysis_id}

    # Act
    command_results = get_analysis_code_reuse_command(args, intezer_api)

    # Assert
    outputs = command_results.outputs["Intezer.Analysis(obj.RootAnalysis == val.ID).SubAnalyses(obj.ID == val.ID)"]
    assert outputs["ID"] == sub_analysis_id
    assert outputs["RootAnalysis"] == analysis_id
    assert len(outputs["CodeReuseFamilies"]) == 1
    assert "CodeReuse" in outputs


def test_get_analysis_code_reuse_command_analysis_doesnt_exist(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    sub_analysis_id = "sub_analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{sub_analysis_id}/code-reuse", status_code=HTTPStatus.NOT_FOUND
    )

    args = {"analysis_id": analysis_id, "sub_analysis_id": sub_analysis_id}

    # Act
    command_results = get_analysis_code_reuse_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == f"The Analysis {analysis_id} was not found on Intezer Analyze"


def test_get_analysis_code_reuse_command_no_code_reuse(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    sub_analysis_id = "sub_analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{sub_analysis_id}/code-reuse", status_code=HTTPStatus.CONFLICT
    )

    args = {"analysis_id": analysis_id, "sub_analysis_id": sub_analysis_id}

    # Act
    command_results = get_analysis_code_reuse_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == "No code reuse for this analysis"


# endregion

# region get_analysis_metadata_command


def test_get_analysis_metadata_command_success_root(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/root/metadata", json={"sha256": "sha256", "product_name": "something"}
    )

    args = {"analysis_id": analysis_id}

    # Act
    command_results = get_analysis_metadata_command(args, intezer_api)

    # Assert
    outputs = command_results.outputs["Intezer.Analysis(obj.ID == val.ID)"]
    assert outputs["ID"] == analysis_id
    assert "Metadata" in outputs


def test_get_analysis_metadata_command_success(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    sub_analysis_id = "sub_analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{sub_analysis_id}/metadata",
        json={"sha256": "sha256", "product_name": "something"},
    )

    args = {"analysis_id": analysis_id, "sub_analysis_id": sub_analysis_id}

    # Act
    command_results = get_analysis_metadata_command(args, intezer_api)

    # Assert
    outputs = command_results.outputs["Intezer.Analysis(obj.RootAnalysis == val.ID).SubAnalyses(obj.ID == val.ID)"]
    assert outputs["ID"] == sub_analysis_id
    assert outputs["RootAnalysis"] == analysis_id
    assert "Metadata" in outputs


def test_get_analysis_metadata_command_analysis_doesnt_exist(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    sub_analysis_id = "sub_analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{sub_analysis_id}/metadata", status_code=HTTPStatus.NOT_FOUND
    )

    args = {"analysis_id": analysis_id, "sub_analysis_id": sub_analysis_id}

    # Act
    command_results = get_analysis_metadata_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == f"The Analysis {analysis_id} was not found on Intezer Analyze"


# endregion

# region get_analysis_iocs_command


def test_get_analysis_iocs_command_success(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
                "sub_verdict": "trusted",
                "sha256": "sha256",
                "verdict": "trusted",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/iocs",
        json={
            "result": {
                "files": [
                    {
                        "path": "test_file_1.csv",
                        "sha256": "eeb1199f7db006e4d20086171cc312cf5bdf53682cc37997223ad0c15a27dc88",
                        "verdict": "malicious",
                        "family": "Turla",
                        "type": "Main file",
                    }
                ],
                "network": [
                    {"ioc": "1.1.1.1", "source": ["Network communication"], "type": "ip"},
                    {"ioc": "raw.exampledomain.com", "source": ["Network communication"], "type": "domain"},
                ],
            }
        },
    )

    args = {"analysis_id": analysis_id}

    # Act
    command_results = get_analysis_iocs_command(args, intezer_api)

    # Assert
    outputs = command_results.outputs["Intezer.Analysis(obj.ID == val.ID)"]
    assert outputs.get("ID") == analysis_id
    assert "IOCs" in outputs


def test_get_analysis_iocs_command_no_iocs(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
                "sub_verdict": "trusted",
                "sha256": "sha256",
                "verdict": "trusted",
                "analysis_url": "bla",
            },
            "status": "succeeded",
        },
    )
    requests_mock.get(f"{full_url}/analyses/{analysis_id}/iocs", status_code=HTTPStatus.NOT_FOUND)

    args = {"analysis_id": analysis_id}

    # Act
    command_results = get_analysis_iocs_command(args, intezer_api)

    # Assert
    outputs = command_results.outputs["Intezer.Analysis(obj.ID == val.ID)"]
    assert outputs.get("ID") == analysis_id
    assert command_results.readable_output == "No IOCs found"
    assert "IOCs" in outputs
    assert outputs["IOCs"] is None


def test_get_analysis_iocs_command_analysis_doesnt_exist(requests_mock):
    # Arrange
    analysis_id = "analysis_id"
    _setup_access_token(requests_mock)
    requests_mock.get(f"{full_url}/analyses/{analysis_id}", status_code=HTTPStatus.NOT_FOUND)

    args = {"analysis_id": analysis_id}

    # Act
    command_results = get_analysis_iocs_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == f"The Analysis {analysis_id} was not found on Intezer Analyze"


# endregion

# region get_family_info_command


def test_get_family_info_command_success(requests_mock):
    # Arrange
    family_id = "family_id"
    family_name = "Kfir"
    family_type = "Malicious"
    _setup_access_token(requests_mock)
    requests_mock.get(
        f"{full_url}/families/{family_id}/info", json={"result": {"family_name": family_name, "family_type": family_type}}
    )

    args = {"family_id": family_id}

    # Act
    command_results = get_family_info_command(args, intezer_api)

    # Assert
    assert command_results.outputs["Name"] == family_name
    assert command_results.outputs["Type"] == family_type


def test_get_family_info_command_analysis_doesnt_exist(requests_mock):
    # Arrange
    family_id = "family_id"
    _setup_access_token(requests_mock)
    requests_mock.get(f"{full_url}/families/{family_id}/info", status_code=HTTPStatus.NOT_FOUND)

    args = {"family_id": family_id}

    # Act
    command_results = get_family_info_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == f"The Family {family_id} was not found on Intezer Analyze"


# endregion


# region check_is_available
def test_check_is_available_success(requests_mock):
    requests_mock.get(
        f"{full_url}/is-available",
        json={"ok": "ok"},
    )

    requests_mock.post(
        f"{full_url}/get-access-token",
        json={"result": "some_token"},
    )

    response = check_is_available({}, intezer_api)
    assert response == "ok"


def test_check_is_available_http_error(requests_mock):
    requests_mock.get(f"{full_url}/is-available", status_code=HTTPStatus.BAD_REQUEST)

    requests_mock.post(
        f"{full_url}/get-access-token",
        json={"result": "some_token"},
    )

    response = check_is_available({}, intezer_api)
    assert "Error occurred when reaching Intezer Analyze. Please check Analyze Base URL." in response


# endregion


# region analyze_url_command
def test_analyze_url_command_success(requests_mock):
    # Arrange
    analysis_id = "analysis-id"

    _setup_access_token(requests_mock)
    requests_mock.post(f"{full_url}/url", status_code=HTTPStatus.CREATED, json={"result_url": f"/url/{analysis_id}"})

    args = {"url": "https://intezer.com"}

    # Act
    command_results = analyze_url_command(args, intezer_api)

    # Assert
    assert command_results.outputs["ID"] == analysis_id


def test_analyze_url_command_success_polling_true(requests_mock, mocker):
    # Arrange
    analysis_id = "analysis-id"

    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.post(f"{full_url}/url", status_code=HTTPStatus.CREATED, json={"result_url": f"/url/{analysis_id}"})

    requests_mock.get(
        f"{full_url}/url/{analysis_id}",
        json={
            "result": {
                "analysis_id": analysis_id,
            },
            "status": "in_progress",
        },
    )

    args = {"url": "https://intezer.com", "wait_for_result": True}

    # Act
    command_results = analyze_url_command(args, intezer_api)

    # Assert
    assert command_results.readable_output == "Fetching Intezer analysis. Please wait..."


def test_analyze_url_command_missing_url(requests_mock):
    # Arrange

    _setup_access_token(requests_mock)
    requests_mock.post(f"{full_url}/url", status_code=HTTPStatus.BAD_REQUEST, json={"error": "Bad url"})

    url = "123test"
    args = {"url": url, "analysis_type": "Url"}

    # Act
    command_results = analyze_url_command(args, intezer_api)

    # Assert
    assert (
        "The Url 123test was not found on Intezer. Error Server returned bad request error: Bad url"
    ) in command_results.readable_output


def test_analyze_url_command_url_not_found(requests_mock):
    # Arrange
    _setup_access_token(requests_mock)
    requests_mock.post(f"{full_url}/url", status_code=HTTPStatus.BAD_REQUEST, json={"error": "Bad url"})

    args = {"analysis_type": "Url"}

    # Act
    with pytest.raises(ValueError):
        analyze_url_command(args, intezer_api)


# endregion

# region submit_alert_command


def test_submit_alert_command_success(requests_mock):
    # Arrange
    _setup_access_token(requests_mock)
    alert_id = "112233"
    requests_mock.post(f"{full_url}/alerts/ingest", status_code=HTTPStatus.OK, json={"alert_id": alert_id, "result": True})

    mapping = {"test": "mapping"}

    args = {"raw_alert": {"id": 123}, "mapping": json.dumps(mapping), "source": "cs"}

    # Act
    command_results = submit_alert_command(args, intezer_api)

    # Assert
    assert command_results.outputs["ID"] == alert_id
    assert command_results.outputs["Status"] == "Created"
    assert command_results.readable_output == f"Alert created successfully: {alert_id}"


def test_submit_alert_command_invalid_mapping_file(requests_mock):
    # Arrange
    _setup_access_token(requests_mock)
    alert_id = "112233"
    requests_mock.post(
        f"{full_url}/alerts/ingest", status_code=HTTPStatus.BAD_REQUEST, json={"alert_id": alert_id, "result": True}
    )

    mapping = {"test": "mapping"}

    args = {"raw_alert": {"id": 123}, "mapping": json.dumps(mapping), "source": "cs"}

    # Act + Assert
    with pytest.raises(intezer_sdk.errors.InvalidAlertMappingError):
        submit_alert_command(args, intezer_api)


# endregion

# region submit_suspected_phishing_email_command


def test_submit_suspected_phishing_email_command_success(requests_mock, mocker):
    # Arrange
    _setup_access_token(requests_mock)
    alert_id = "112233"
    requests_mock.post(f"{full_url}/alerts/ingest/binary", status_code=HTTPStatus.OK, json={"alert_id": alert_id, "result": True})

    args = {"email_file_entry_id": "123@123"}

    # Act
    with tempfile.NamedTemporaryFile() as file:
        file.write(b"123")
        file.seek(0)
        file_path_patch = mocker.patch("demistomock.getFilePath")
        file_path_patch.return_value = {"path": file.name, "name": file.name}
        command_results = submit_suspected_phishing_email_command(args, intezer_api)

    # Assert
    assert command_results.outputs["ID"] == alert_id
    assert command_results.outputs["Status"] == "Created"
    assert command_results.readable_output == f"Suspected email was sent successfully, alert_id: {alert_id}"


# endregion


# region get_alert_response_command


def test_get_alert_response_command_alert_not_found(requests_mock, mocker):
    # Arrange
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(f"{full_url}/alerts/get-by-id", status_code=HTTPStatus.NOT_FOUND, json={"alert_id": "123"})

    args = {"alert_id": "123", "wait_for_result": True}

    # Act
    command_result = get_alert_result_command(args, intezer_api)

    # Assert
    command_result.readable_output = "Could not find alert with the alert_id of 123"


def test_get_alert_response_command_alert_in_progress(requests_mock, mocker):
    # Arrange
    _setup_access_token(requests_mock)
    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)

    requests_mock.get(
        f"{full_url}/alerts/get-by-id", status_code=HTTPStatus.OK, json={"result": {"123": "123"}, "status": "in_progress"}
    )

    args = {"alert_id": "123", "wait_for_result": True}

    # Act
    command_result = get_alert_result_command(args, intezer_api)

    # Assert
    assert command_result.readable_output == "Fetching Intezer alert. Please wait..."


def test_get_alert_response_command_alert_success(requests_mock, mocker):
    # Arrange
    _setup_access_token(requests_mock)

    mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None)
    mocker.patch("IntezerV2.enrich_dbot_and_display_alert_results", return_value=CommandResults(readable_output="test"))

    requests_mock.get(
        f"{full_url}/alerts/get-by-id", status_code=HTTPStatus.OK, json={"result": {"123": "123"}, "status": "succeeded"}
    )

    args = {"alert_id": "123", "wait_for_result": True}

    # Act
    command_result = get_alert_result_command(args, intezer_api)

    # Assert
    assert command_result.readable_output == "test"


def test_enrich_dbot_and_display_alert_results_no_scans(requests_mock, mocker):
    # Arrange
    _setup_access_token(requests_mock)
    alert_id = "123"
    alert = Alert(alert_id, api=intezer_api)
    alert.scans = []
    alert.status = AlertStatusCode.FINISHED
    alert.intezer_alert_url = "some_url"
    alert.family_name = None
    mocker.patch.object(
        Alert,
        "result",
        return_value={"scans": [], "triage_result": {"alert_verdict_display": "dangerous", "risk_category_display": "malicious"}},
    )

    # Act
    with patch("IntezerV2.return_results") as results_mock:
        enrich_dbot_and_display_alert_results(alert, intezer_api)

    # Assert
    assert results_mock.call_count == 1


def test_enrich_dbot_and_display_alert_results_artifact_analyses(requests_mock, mocker):
    # Arrange
    _setup_access_token(requests_mock)
    alert_id = "123"
    alert = Alert(alert_id, api=intezer_api)
    alert.scans = []
    alert.status = AlertStatusCode.FINISHED
    alert.intezer_alert_url = "some_url"
    alert.family_name = None
    malicious_ip = "some_ip"
    mocker.patch.object(
        Alert,
        "result",
        return_value={
            "scans": [
                {
                    "artifact_analysis": {
                        "artifact_type": "ip",
                        "artifact_value": malicious_ip,
                        "family_name": "Vobfus",
                        "verdict": "malicious",
                    },
                    "collection_status": "collected",
                    "scan_type": "artifact",
                }
            ],
            "triage_result": {"alert_verdict_display": "dangerous", "risk_category_display": "malicious"},
        },
    )

    # Act
    with patch("IntezerV2.return_results") as results_mock:
        enrich_dbot_and_display_alert_results(alert, intezer_api)

    # Assert
    first_result: CommandResults = results_mock.call_args.args[0][0]
    assert len(results_mock.call_args.args[0]) == 2
    assert first_result.indicator.dbot_score.indicator_type == "ip"
    assert first_result.indicator.dbot_score.indicator == malicious_ip
    assert first_result.indicator.dbot_score.score == Common.DBotScore.BAD


def test_enrich_dbot_and_display_alert_results_file_analysis(requests_mock, mocker):
    # Arrange
    _setup_access_token(requests_mock)
    alert_id = "123"
    alert = Alert(alert_id, api=intezer_api)
    alert.status = AlertStatusCode.FINISHED
    alert.intezer_alert_url = "some_url"
    alert.family_name = None

    analysis_id = "123"
    root_sub_analysis = "456"
    analysis = FileAnalysis(api=intezer_api)
    analysis.analysis_id = analysis_id
    analysis.analysis_type = "file"
    sha256 = "a" * 64
    md5 = "b" * 32
    sha1 = "c" * 40
    analysis._report = {
        "analysis_id": analysis_id,
        "analysis_time": "Mon, 24 Jul 2023 15:45:58 GMT",
        "analysis_url": f"https://analyze.intezer.com/analyses/{analysis_id}",
        "file_name": "body-html.html",
        "is_private": True,
        "sha256": sha256,
        "sub_verdict": "inconclusive",
        "verdict": "unknown",
    }

    alert.scans = [analysis]

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses",
        json={"sub_analyses": [{"sha256": sha256, "source": "root", "sub_analysis_id": root_sub_analysis}]},
    )

    requests_mock.get(
        f"{full_url}/analyses/{analysis_id}/sub-analyses/{root_sub_analysis}/metadata",
        json={
            "file_type": "non executable",
            "md5": md5,
            "sha1": sha1,
            "sha256": sha256,
            "size_in_bytes": 838,
            "ssdeep": "12:dfhfgjh:sdfghfgjfgh",
        },
    )

    mocker.patch.object(
        Alert,
        "result",
        return_value={
            "scans": [{"scan_type": "file", "file_analysis": analysis.result()}],
            "triage_result": {"alert_verdict_display": "dangerous", "risk_category_display": "malicious"},
        },
    )

    # Act
    with patch("IntezerV2.return_results") as results_mock:
        enrich_dbot_and_display_alert_results(alert, intezer_api)

    # Assert
    first_result: CommandResults = results_mock.call_args.args[0][0]
    assert len(results_mock.call_args.args[0]) == 2
    assert first_result.indicator.dbot_score.indicator_type == "file"
    assert first_result.indicator.dbot_score.indicator == sha256
    assert first_result.indicator.dbot_score.score == Common.DBotScore.NONE
    assert first_result.indicator.md5 == md5
    assert first_result.indicator.sha1 == sha1
    assert first_result.indicator.sha256 == sha256


def test_enrich_dbot_and_display_alert_results_url_analysis(requests_mock, mocker):
    # Arrange
    _setup_access_token(requests_mock)
    alert_id = "123"
    alert = Alert(alert_id, api=intezer_api)
    alert.status = AlertStatusCode.FINISHED
    alert.intezer_alert_url = "some_url"
    alert.family_name = None

    analysis_id = "123"
    analysis = UrlAnalysis(api=intezer_api)
    analysis.analysis_id = analysis_id
    url = "https://www.google.com"
    analysis._report = {
        "analysis_id": analysis_id,
        "analysis_time": "Mon, 24 Jul 2023 15:45:58 GMT",
        "analysis_url": f"https://analyze.intezer.com/analyses/{analysis_id}",
        "scanned_url": url,
        "submitted_url": url,
        "summary": {"verdict_type": "malicious"},
    }

    alert.scans = [analysis]

    mocker.patch.object(
        Alert,
        "result",
        return_value={
            "scans": [{"scan_type": "file", "file_analysis": analysis.result()}],
            "triage_result": {"alert_verdict_display": "dangerous", "risk_category_display": "malicious"},
        },
    )

    # Act
    with patch("IntezerV2.return_results") as results_mock:
        enrich_dbot_and_display_alert_results(alert, intezer_api)

    # Assert
    first_result: CommandResults = results_mock.call_args.args[0][0]
    assert len(results_mock.call_args.args[0]) == 2
    assert first_result.indicator.dbot_score.indicator_type == "url"
    assert first_result.indicator.dbot_score.indicator == url
    assert first_result.indicator.dbot_score.score == Common.DBotScore.BAD