Cisco Umbrella Cloud Security v2

Cisco Umbrella is a cloud security platform providing the first line of defense against internet threats. It uses DNS-layer security to block malicious requests before a connection is established, offering protection against malware, ransomware, phishing, and more. It offers real-time reporting, integrates with other Cisco solutions for layered security, and uses machine learning to uncover and predict threats.

Network Security · Cisco Umbrella cloud security

Details

IDCisco Umbrella Cloud Security v2
ProviderCisco Systems
CategoryNetwork Security
From Version6.9.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Cisco Umbrella is a cloud security platform providing the first line of defense against internet threats. It uses DNS-layer security to block malicious requests before a connection is established, offering protection against malware, ransomware, phishing, and more. It offers real-time reporting, integrates with other Cisco solutions for layered security, and uses machine learning to uncover and predict threats.
This integration was tested with version 2 of Cisco Umbrella Cloud Security

Configure Cisco Umbrella Cloud Security v2 in Cortex

Parameter Required
API Key True
API Secret True
Use system proxy settings False
Trust any certificate (not secure) False
Base URL True

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.

umbrella-destinations-list


Get destinations within a destination list. A destination is a URL, IP or fully qualified domain name.

Base Command

umbrella-destinations-list

Input

Argument Name Description Required
destination_list_id The ID of the destination list. Destination lists can be fetched with the umbrella-destination-lists-list command. Required
destination_ids Comma-separated list of destination IDs to be retrieved from a list of destinations. Optional
destinations Comma-separated list of destinations to retrieve, a destination may be a domain, URL, or IP address. Optional
page Page number of paginated results. Minimum 1; Default 1. Optional
page_size The number of items per page. Minimum 1; Maximum 100; Default 50. Optional
limit The number of items per page. Minimum 1. Default is 50. Optional

Context Output

Path Type Description
Umbrella.Destinations.id String The unique ID of the destination.
Umbrella.Destinations.destination String A destination may be a domain, URL, or IP address.
Umbrella.Destinations.type String The type of destination within the destination list.
Umbrella.Destinations.comment String A comment about the destination.
Umbrella.Destinations.createdAt Date The date and time when the destination list was created.

Command example

!umbrella-destinations-list destination_list_id=17425859 limit=3

Context Example

{
    "Umbrella": {
        "Destinations": [
            {
                "comment": "Added from XSOAR",
                "createdAt": "2023-07-19 18:21:11",
                "destination": "www.facebook.com",
                "id": "154",
                "type": "domain"
            },
            {
                "comment": "Lior",
                "createdAt": "2023-07-06 04:42:55",
                "destination": "cisco.com",
                "id": "30058",
                "type": "domain"
            },
            {
                "comment": "Sabri",
                "createdAt": "2023-07-06 04:42:55",
                "destination": "www.pokemon.com",
                "id": "138036",
                "type": "domain"
            }
        ]
    }
}

Human Readable Output

Destination(s)

Id Destination Type Comment Created At
154 www.facebook.com domain Added from XSOAR 2023-07-19 18:21:11
30058 cisco.com domain Pikachu 2023-07-06 04:42:55
138036 www.pokemon.com domain Choose 2023-07-06 04:42:55

umbrella-destination-add


Add a destination to a destination list. A destination is a URL, IPv4, CIDR or fully qualified domain name. Accepted types for destination list with the access “allow” are: DOMAIN, IPv4 and CIDR. Accepted types for destination list with the access “block” are: URL and DOMAIN.

Base Command

umbrella-destination-add

Input

Argument Name Description Required
destination_list_id The ID of the destination list. Destination lists can be fetched with the umbrella-destination-lists-list command. Required
destinations Comma-separated list of destinations. A destination may be a URL, IPv4, CIDR or fully qualified domain name. Required
comment A comment about all the inserted destinations. Default is Added from XSOAR. Optional

Context Output

Path Type Description
Umbrella.DestinationLists.id Number The unique ID of the destination list.
Umbrella.DestinationLists.organizationId Number The organization ID.
Umbrella.DestinationLists.access String The type of access for the destination list. Valid values are: allow or block.
Umbrella.DestinationLists.isGlobal Boolean Specifies whether the destination list is a global destination list. There is only one default destination list of type ‘allow’ or ‘block’ for an organization.
Umbrella.DestinationLists.name String The name of the destination list.
Umbrella.DestinationLists.thirdpartyCategoryId Number The third-party category ID of the destination list.
Umbrella.DestinationLists.createdAt Number The date and time when the destination list was created.
Umbrella.DestinationLists.modifiedAt Number The date and time when the destination list was modified.
Umbrella.DestinationLists.isMspDefault Boolean Specifies whether MSP is the default.
Umbrella.DestinationLists.markedForDeletion Boolean Specifies whether the destination list is marked for deletion.
Umbrella.DestinationLists.bundleTypeId Number The number that represents the type of the Umbrella policy associated with the destination list. Umbrella returns ‘1’ for the DNS policy or ‘2’ for the Web policy.
Umbrella.DestinationLists.meta.destinationCount Number The total number of destinations in a destination list.

Base Command

umbrella-destination-add

Input

Argument Name Description Required
destination_list_id The ID of the destination list. Destination Lists can be fetched with umbrella-destination-lists-list. Required
destinations Comma separated list of destinations. A destination may be a URL, IPv4, CIDR or fully qualified domain name. Required
comment A comment about all the inserted destinations. Default value: “Added from XSOAR”. Default is Added from XSOAR. Optional

Context Output

Path Type Description
Umbrella.DestinationLists.id Number The unique ID of the destination list.
Umbrella.DestinationLists.organizationId Number The organization ID.
Umbrella.DestinationLists.access String The type of access for the destination list. Valid values are: allow or block.
Umbrella.DestinationLists.isGlobal Boolean Specifies whether the destination list is a global destination list. There is only one default destination list of type ‘allow’ or ‘block’ for an organization.
Umbrella.DestinationLists.name String The name of the destination list.
Umbrella.DestinationLists.thirdpartyCategoryId Number The third-party category ID of the destination list.
Umbrella.DestinationLists.createdAt Number The date and time when the destination list was created.
Umbrella.DestinationLists.modifiedAt Number The date and time when the destination list was modified.
Umbrella.DestinationLists.isMspDefault Boolean Specifies whether MSP is the default.
Umbrella.DestinationLists.markedForDeletion Boolean Specifies whether the destination list is marked for deletion.
Umbrella.DestinationLists.bundleTypeId Number The number that represents the type of the Umbrella policy associated with the destination list. Umbrella returns ‘1’ for the DNS policy or ‘2’ for the Web policy.
Umbrella.DestinationLists.meta.destinationCount Number The total number of destinations in a destination list.

Command example

!umbrella-destination-add destination_list_id=17463731 destinations="www.LiorSabri.com,1.1.1.1"

Human Readable Output

The destination(s) “[‘www.LiorSabri.com’, ‘1.1.1.1’]” were successfully added to the destination list “17463731”

umbrella-destination-delete


Remove a destination from a destination list. A destination is a URL, IP or fully qualified domain name.

Base Command

umbrella-destination-delete

Input

Argument Name Description Required
destination_list_id The ID of the destination list. Destination lists can be fetched with the umbrella-destination-lists-list command. Required
destination_ids Comma-separated list of destination IDs. Destinations can be fetched with the umbrella-destination-list command. Required

Context Output

Path Type Description
Umbrella.DestinationLists.id Number The unique ID of the destination list.
Umbrella.DestinationLists.organizationId Number The organization ID.
Umbrella.DestinationLists.access String The type of access for the destination list. Valid values are: allow or block.
Umbrella.DestinationLists.isGlobal Boolean Specifies whether the destination list is a global destination list. There is only one default destination list of type ‘allow’ or ‘block’ for an organization.
Umbrella.DestinationLists.name String The name of the destination list.
Umbrella.DestinationLists.thirdpartyCategoryId Number The third-party category ID of the destination list.
Umbrella.DestinationLists.createdAt Number The date and time when the destination list was created.
Umbrella.DestinationLists.modifiedAt Number The date and time when the destination list was modified.
Umbrella.DestinationLists.isMspDefault Boolean Specifies whether MSP is the default.
Umbrella.DestinationLists.markedForDeletion Boolean Specifies whether the destination list is marked for deletion.
Umbrella.DestinationLists.bundleTypeId Number The number that represents the type of the Umbrella policy associated with the destination list. Umbrella returns ‘1’ for the DNS policy or ‘2’ for the Web policy.
Umbrella.DestinationLists.meta.destinationCount Number The total number of destinations in a destination list.

Command example

!umbrella-destination-delete destination_list_id=17463733 destination_ids=25826

Human Readable Output

The destination(s) “[25826]” were successfully removed from the destination list “17463733”

umbrella-destination-lists-list


Get destination lists. A list of destinations (for example, domain name or URL) to which you can block or allow access.

Base Command

umbrella-destination-lists-list

Input

Argument Name Description Required
destination_list_id The ID of the destination list to retrieve. Optional
page Page number of paginated results. Minimum 1; Default 1. Optional
page_size The number of items per page. Minimum 1; Maximum 100; Default 50. Optional
limit The maximum number of records to retrieve. Minimum 1. Default is 50. Optional

Context Output

Path Type Description
Umbrella.DestinationLists.id Number The unique ID of the destination list.
Umbrella.DestinationLists.organizationId Number The organization ID.
Umbrella.DestinationLists.access String The type of access for the destination list. Valid values are: allow or block.
Umbrella.DestinationLists.isGlobal Boolean Specifies whether the destination list is a global destination list. There is only one default destination list of type ‘allow’ or ‘block’ for an organization.
Umbrella.DestinationLists.name String The name of the destination list.
Umbrella.DestinationLists.thirdpartyCategoryId Number The third-party category ID of the destination list.
Umbrella.DestinationLists.createdAt Number The date and time when the destination list was created.
Umbrella.DestinationLists.modifiedAt Number The date and time when the destination list was modified.
Umbrella.DestinationLists.isMspDefault Boolean Specifies whether MSP is the default.
Umbrella.DestinationLists.markedForDeletion Boolean Specifies whether the destination list is marked for deletion.
Umbrella.DestinationLists.bundleTypeId Number The number that represents the type of the Umbrella policy associated with the destination list. Umbrella returns ‘1’ for the DNS policy or ‘2’ for the Web policy.
Umbrella.DestinationLists.meta.destinationCount Number The total number of destinations in a destination list.
Umbrella.DestinationLists.meta.domainCount Number The total number of domains in a destination list. Domains are part of the total number of destinations in a destination list.
Umbrella.DestinationLists.meta.ipv4Count Number The total number of IP addresses in a destination list. IP addresses are part of the total number of destinations in a destination list.
Umbrella.DestinationLists.meta.urlCount Number The total number of URLs in a destination list. URLs are part of the total number of destinations in a destination list.
Umbrella.DestinationLists.meta.applicationCount Number The total number or applications in a destination list. Applications are part of the total number of destinations in a destination list.

Command example

!umbrella-destination-lists-list limit=3

Context Example

{
    "Umbrella": {
        "DestinationLists": [
            {
                "access": "allow",
                "bundleTypeId": 1,
                "createdAt": 1690184121,
                "id": 17463749,
                "isGlobal": false,
                "isMspDefault": false,
                "markedForDeletion": false,
                "meta": {
                    "applicationCount": 0,
                    "destinationCount": 1,
                    "domainCount": 0,
                    "ipv4Count": 1,
                    "urlCount": 0
                },
                "modifiedAt": 1690184121,
                "name": "Lior",
                "organizationId": 123456,
                "thirdpartyCategoryId": null
            },
            {
                "access": "allow",
                "bundleTypeId": 1,
                "createdAt": 1690184234,
                "id": 17463756,
                "isGlobal": false,
                "isMspDefault": false,
                "markedForDeletion": false,
                "meta": {
                    "applicationCount": 0,
                    "destinationCount": 8,
                    "domainCount": 4,
                    "ipv4Count": 4,
                    "urlCount": 0
                },
                "modifiedAt": 1690184435,
                "name": "LiorSB",
                "organizationId": 123456,
                "thirdpartyCategoryId": null
            },
            {
                "access": "allow",
                "bundleTypeId": 1,
                "createdAt": 1638798710,
                "id": 15609454,
                "isGlobal": true,
                "isMspDefault": false,
                "markedForDeletion": false,
                "meta": {
                    "applicationCount": 0,
                    "destinationCount": 14,
                    "domainCount": 10,
                    "ipv4Count": 4,
                    "urlCount": 0
                },
                "modifiedAt": 1690183660,
                "name": "Global Allow List",
                "organizationId": 123456,
                "thirdpartyCategoryId": null
            }
        ]
    }
}

Human Readable Output

Destination List

Id Name Access Is Global Destination Count
17463749 Lior allow false 1
17463756 LiorSB allow false 8
15609454 Global Allow List allow true 14

umbrella-destination-list-create


Create a destination list. A list of destinations (for example, domain name or URL) to which you can block or allow access. Accepted types for destination list with the access “allow” are: DOMAIN, IPv4 and CIDR. Accepted types for destination list with the access “block” are: URL and DOMAIN.

Base Command

umbrella-destination-list-create

Input

Argument Name Description Required
bundle_type The type of the Umbrella policy associated with the destination list. If the field is not specified, the default value is ‘DNS’. Possible values are: DNS, WEB. Optional
access The type of access for the destination list. Valid values are “allow” or “block”. Accepted types for destination list with the access “allow” are: DOMAIN, IPv4 and CIDR. Accepted types for destination list with the access “block” are: URL and DOMAIN. Possible values are: allow, block. Required
is_global Specifies whether the destination list is a global destination list. There is only one default destination list of type ‘allow’ or ‘block’ for an organization. Possible values are: True, False. Required
name The name of the destination list. Required
destinations Comma-separated list of destinations. A destination may be a URL, IPv4, CIDR or fully qualified domain name. Optional
destinations_comment A comment about all the inserted destinations. Default is Added from XSOAR. Optional

Context Output

Path Type Description
Umbrella.DestinationLists.id Number The unique ID of the destination list.
Umbrella.DestinationLists.organizationId Number The organization ID.
Umbrella.DestinationLists.access String The type of access for the destination list. Valid values are: allow or block.
Umbrella.DestinationLists.isGlobal Boolean Specifies whether the destination list is a global destination list. There is only one default destination list of type ‘allow’ or ‘block’ for an organization.
Umbrella.DestinationLists.name String The name of the destination list.
Umbrella.DestinationLists.thirdpartyCategoryId Number The third-party category ID of the destination list.
Umbrella.DestinationLists.createdAt Number The date and time when the destination list was created.
Umbrella.DestinationLists.modifiedAt Number The date and time when the destination list was modified.
Umbrella.DestinationLists.isMspDefault Boolean Specifies whether MSP is the default.
Umbrella.DestinationLists.markedForDeletion Boolean Specifies whether the destination list is marked for deletion.
Umbrella.DestinationLists.bundleTypeId Number The number that represents the type of the Umbrella policy associated with the destination list. Umbrella returns ‘1’ for the DNS policy or ‘2’ for the Web policy.
Umbrella.DestinationLists.meta.destinationCount Number The total number of destinations in a destination list.

Command example

!umbrella-destination-list-create access=allow is_global=False name=LiorSBList bundle_type=WEB destinations="https://pokemon.com"

Context Example

{
    "Umbrella": {
        "DestinationLists": {
            "access": "allow",
            "bundleTypeId": 1,
            "createdAt": 1690208665,
            "id": 17464621,
            "isGlobal": false,
            "isMspDefault": false,
            "markedForDeletion": false,
            "meta": {
                "destinationCount": 1
            },
            "modifiedAt": 1690208665,
            "name": "LiorSBList",
            "organizationId": 123456,
            "thirdpartyCategoryId": null
        }
    }
}

Human Readable Output

Destination List

Id Name Access Is Global Destination Count
17464621 LiorSBList allow false 1

umbrella-destination-list-update


Edit a destination list. A list of destinations (for example, domain name or URL) to which you can block or allow access.

Base Command

umbrella-destination-list-update

Input

Argument Name Description Required
destination_list_id The ID of the destination list. Destination lists can be fetched with the umbrella-destination-lists-list command. Required
name The name of the destination list. Required

Context Output

Path Type Description
Umbrella.DestinationLists.id Number The unique ID of the destination list.
Umbrella.DestinationLists.organizationId Number The organization ID.
Umbrella.DestinationLists.access String The type of access for the destination list. Valid values are: allow or block.
Umbrella.DestinationLists.isGlobal Boolean Specifies whether the destination list is a global destination list. There is only one default destination list of type ‘allow’ or ‘block’ for an organization.
Umbrella.DestinationLists.name String The name of the destination list.
Umbrella.DestinationLists.thirdpartyCategoryId Number The third-party category ID of the destination list.
Umbrella.DestinationLists.createdAt Number The date and time when the destination list was created.
Umbrella.DestinationLists.modifiedAt Number The date and time when the destination list was modified.
Umbrella.DestinationLists.isMspDefault Boolean Specifies whether MSP is the default.
Umbrella.DestinationLists.markedForDeletion Boolean Specifies whether the destination list is marked for deletion.
Umbrella.DestinationLists.bundleTypeId Number The number that represents the type of the Umbrella policy associated with the destination list. Umbrella returns ‘1’ for the DNS policy or ‘2’ for the Web policy.
Umbrella.DestinationLists.meta.destinationCount Number The total number of destinations in a destination list.

Command example

!umbrella-destination-list-update destination_list_id=17463733 name=LiorUpdated

Context Example

{
    "Umbrella": {
        "DestinationLists": {
            "access": "allow",
            "bundleTypeId": 1,
            "createdAt": 1690183414,
            "id": 17463733,
            "isGlobal": false,
            "isMspDefault": false,
            "markedForDeletion": false,
            "meta": {
                "destinationCount": 0
            },
            "modifiedAt": 1690208670,
            "name": "LiorUpdated",
            "organizationId": 123456,
            "thirdpartyCategoryId": null
        }
    }
}

Human Readable Output

Destination List

Id Name Access Is Global Destination Count
17463733 LiorUpdated allow false 0

umbrella-destination-list-delete


Delete a destination list. A list of destinations (for example, domain name or URL) to which you can block or allow access.

Base Command

umbrella-destination-list-delete

Input

Argument Name Description Required
destination_list_id The ID of the destination list. Destination lists can be fetched with the umbrella-destination-lists-list command. Required

Context Output

There is no context output for this command.

Command example

!umbrella-destination-list-delete destination_list_id=17463733

Human Readable Output

The destination list “17463733” was successfully deleted

Breaking changes from the previous version of this integration - Cisco Umbrella Cloud Security v2

The following sections list the changes in this version.

Commands

The following commands were removed in this version

  • umbrella-get-destination-lists - this command was replaced by umbrella-destination-lists-list.
  • umbrella-add-domain - this command was replaced by umbrella-destination-add.
  • umbrella-remove-domain - this command was replaced by umbrella-destination-delete.
  • umbrella-get-destination-domain - this command was replaced by umbrella-destinations-list.
  • umbrella-get-destination-domains - this command was replaced by umbrella-destinations-list.
  • umbrella-search-destination-domains - this command was replaced by umbrella-destinations-list.

Arguments

The following arguments were removed in this version

In the umbrella-get-destination-lists command:

  • orgId - this argument was removed.
    In the umbrella-add-domain command:
  • orgId - this argument was removed.
    In the umbrella-remove-domain command:
  • orgId - this argument was removed.
    In the umbrella-get-destination-domain command:
  • orgId - this argument was removed.
    In the umbrella-get-destination-domains command:
  • orgId - this argument was removed.
    In the umbrella-search-destination-domains command:
  • orgId - this argument was removed.

The behavior of the following arguments was changed

In the umbrella-add-domain command:

  • destId - this argument was replaced by destination_list_id.
  • domains - this argument was replaced by destinations.
    In the umbrella-remove-domain command:
  • destId - this argument was replaced by destination_list_id.
  • domainIds - this argument was replaced by destination_ids.
    In the umbrella-get-destination-domain command:
  • destId - this argument was replaced by destination_list_id.
    In the umbrella-get-destination-domains command:
  • destId - this argument was replaced by destination_list_id.
    In the umbrella-search-destination-domains command:
  • destId - this argument was replaced by destination_list_id.
  • domains - this argument was replaced by destinations.

Configuration parameters

  • credentials — API Key (required)
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)
  • baseURL — Base URL (required)

Commands (13)

  • umbrella-add-domain Deprecated

    Deprecated. Use the `umbrella-destination-add` instead.

  • umbrella-destination-add

    Add a destination to a destination list. A destination is a URL, IPv4, CIDR or fully qualified domain name. Accepted types for destination list with the access "allow" are: DOMAIN, IPv4 and CIDR. Accepted types for destination list with the access "block" are: URL and DOMAIN.

  • umbrella-destination-delete

    Remove a destination from a destination list. A destination is a URL, IP or fully qualified domain name.

  • umbrella-destination-list-create

    Create a destination list. A list of destinations (for example, domain name or URL) to which you can block or allow access. Accepted types for destination list with the access "allow" are: DOMAIN, IPv4 and CIDR. Accepted types for destination list with the access "block" are: URL and DOMAIN.

  • umbrella-destination-list-delete

    Delete a destination list. A list of destinations (for example, domain name or URL) to which you can block or allow access.

  • umbrella-destination-list-update

    Edit a destination list. A list of destinations (for example, domain name or URL) to which you can block or allow access.

  • umbrella-destination-lists-list

    Get destination lists. A list of destinations (for example, domain name or URL) to which you can block or allow access.

  • umbrella-destinations-list

    Get destinations within a destination list. A destination is a URL, IP or fully qualified domain name.

  • umbrella-get-destination-domain Deprecated

    Deprecated. Use the `umbrella-destinations-list` instead.

  • umbrella-get-destination-domains Deprecated

    Deprecated. Use the `umbrella-destinations-list` instead.

  • umbrella-get-destination-lists Deprecated

    Deprecated. Use the `umbrella-destination-lists-list` instead.

  • umbrella-remove-domain Deprecated

    Deprecated. Use the `umbrella-destination-delete` instead.

  • umbrella-search-destination-domains Deprecated

    Deprecated. Use the `umbrella-destinations-list` instead.

import json
import os
from unittest.mock import patch

import CiscoUmbrellaCloudSecurityv2
import CommonServerPython
import pytest

TEST_DATA = "test_data"
BASE_URL = "http://example.com"
DESTINATION_ENDPOINT = CommonServerPython.urljoin(
    BASE_URL,
    CiscoUmbrellaCloudSecurityv2.Client.DESTINATION_LIST_ENDPOINT,
)


def load_mock_response(file_name: str) -> str:
    """
    Load mock file that simulates an API response.
    Args:
        file_name (str): Name of the mock response JSON file to return.
    Returns:
        str: Mock file content.
    """
    file_path = os.path.join(TEST_DATA, file_name)

    with open(file_path, encoding="utf-8") as mock_file:
        return json.loads(mock_file.read())


@pytest.fixture()
def mock_client(requests_mock) -> CiscoUmbrellaCloudSecurityv2.Client:
    """
    Establish a mock connection to the client with a username and password.

    Returns:
        Client: Mock connection to client.
    """
    requests_mock.post(
        url=f"{BASE_URL}/auth/v2/token",
        json={
            "access_token": "Pichu",
        },
    )

    return CiscoUmbrellaCloudSecurityv2.Client(
        base_url=BASE_URL,
        api_key="Pikachu",
        api_secret="Riachu",
    )


@patch("CiscoUmbrellaCloudSecurityv2.MAX_LIMIT", 4)
def test_list_destinations_command(requests_mock, mock_client):
    """
    Scenario:
    - Test listing destinations of a destination list

    Given:
    - A destination list ID

    When:
    - Running the umbrella-destinations-list command.

    Then:
    - Ensure that the CommandResults outputs_prefix is correct.
    - Ensure that the CommandResults outputs_key_field is correct.
    - Ensure that the CommandResults outputs is correct.
    - Ensure that the CommandResults raw_response is correct.
    """
    args = {
        "destination_list_id": "123",
        "limit": 7,
    }

    responses = []

    for i in range(1, 3):
        response = load_mock_response(f"destinations{i}.json")
        responses.append(response)

        url: str = CommonServerPython.urljoin(
            DESTINATION_ENDPOINT,
            f'{args["destination_list_id"]}/destinations?page={i}&limit={4}',
        )
        requests_mock.get(url=url, json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.list_destinations_command(mock_client, args)

    expected_outputs = responses[0]["data"] + responses[1]["data"][:3]
    response["meta"]["total"] = len(expected_outputs)
    response["data"] = expected_outputs

    assert command_results.outputs_prefix == (
        f"{CiscoUmbrellaCloudSecurityv2.INTEGRATION_OUTPUT_PREFIX}.{CiscoUmbrellaCloudSecurityv2.DESTINATION_OUTPUT_PREFIX}"
    )
    assert command_results.outputs_key_field == CiscoUmbrellaCloudSecurityv2.ID_OUTPUTS_KEY_FIELD
    assert command_results.outputs == expected_outputs
    assert command_results.raw_response == response


@patch("CiscoUmbrellaCloudSecurityv2.MAX_LIMIT", 4)
def test_list_destinations_command_fetch_destinations(requests_mock, mock_client):
    """
    Scenario:
    - Test fetching destinations of a destination list

    Given:
    - A destination list ID

    When:
    - Running the umbrella-destinations-list command.

    Then:
    - Ensure that the CommandResults outputs_prefix is correct.
    - Ensure that the CommandResults outputs_key_field is correct.
    - Ensure that the CommandResults outputs is correct.
    - Ensure that the CommandResults raw_response is correct.
    """
    args = {
        "destination_list_id": "123",
        "destinations": ["www.LiorSB.com", "1.1.1.1"],
        "destination_ids": ["111", "333", "555", "1010"],
    }

    responses = []

    for i in range(1, 4):
        response = load_mock_response(f"destinations{i}.json")
        responses.append(response)

        url: str = CommonServerPython.urljoin(
            DESTINATION_ENDPOINT,
            f'{args["destination_list_id"]}/destinations?page={i}&limit={4}',
        )
        requests_mock.get(url=url, json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.list_destinations_command(mock_client, args)

    expected_outputs = [
        responses[0]["data"][0],
        responses[0]["data"][2],
        responses[0]["data"][3],
        responses[1]["data"][0],
    ]
    response["meta"]["total"] = len(expected_outputs)
    response["data"] = expected_outputs

    assert command_results.outputs_prefix == (
        f"{CiscoUmbrellaCloudSecurityv2.INTEGRATION_OUTPUT_PREFIX}.{CiscoUmbrellaCloudSecurityv2.DESTINATION_OUTPUT_PREFIX}"
    )
    assert command_results.outputs_key_field == CiscoUmbrellaCloudSecurityv2.ID_OUTPUTS_KEY_FIELD
    assert command_results.outputs == expected_outputs
    assert command_results.raw_response == response


def test_add_destinations_command(requests_mock, mock_client):
    """
    Scenario:
    - Test adding destinations to a destination list

    Given:
    - A destination list ID and destinations

    When:
    - Running the umbrella-destination-add command.

    Then:
    - Ensure that the CommandResults raw_response is correct.
    - Ensure that the CommandResults readable_output is correct.
    """
    args = {
        "destination_list_id": "123",
        "destinations": ["1.1.1.1", "0.0.0.0"],
        "comment": "Lior is watching",
    }
    response = load_mock_response("destination_list.json")
    url = CommonServerPython.urljoin(DESTINATION_ENDPOINT, f'{args["destination_list_id"]}/destinations')

    requests_mock.post(url=url, json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.add_destination_command(mock_client, args)

    expected_readable_output = (
        f'The destination(s) "{args["destinations"]}" '
        f'were successfully added to the destination list "{args["destination_list_id"]}"'
    )

    assert command_results.readable_output == expected_readable_output
    assert command_results.raw_response == response


def test_delete_destination_command(requests_mock, mock_client):
    """
    Scenario:
    - Test deleting destinations from a destination list

    Given:
    - A destination list ID and destination IDs

    When:
    - Running the umbrella-destination-delete command.

    Then:
    - Ensure that the CommandResults readable_output is correct.
    - Ensure that the CommandResults raw_response is correct.
    """
    args = {
        "destination_list_id": "123",
        "destination_ids": [111, 222, 333],
    }
    response = load_mock_response("destination_list.json")
    url = CommonServerPython.urljoin(DESTINATION_ENDPOINT, f'{args["destination_list_id"]}/destinations')

    requests_mock.delete(url=f"{url}/remove", json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.delete_destination_command(
        mock_client, args
    )

    expected_readable_output = (
        f'The destination(s) "{args["destination_ids"]}" '
        f'were successfully removed from the destination list "{args["destination_list_id"]}"'
    )

    assert command_results.readable_output == expected_readable_output
    assert command_results.raw_response == response


def test_list_destination_lists_command(requests_mock, mock_client):
    """
    Scenario:
    - Test listing a specific destination list

    Given:
    - A destination list ID

    When:
    - Running the umbrella-destination-lists-list command.

    Then:
    - Ensure that the CommandResults outputs_prefix is correct.
    - Ensure that the CommandResults outputs_key_field is correct.
    - Ensure that the CommandResults outputs is correct.
    - Ensure that the CommandResults raw_response is correct.
    """
    args = {
        "destination_list_id": "12345",
    }
    response = load_mock_response("destination_list.json")
    url = CommonServerPython.urljoin(DESTINATION_ENDPOINT, args["destination_list_id"])
    requests_mock.get(url=url, json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.list_destination_lists_command(
        mock_client, args
    )

    assert command_results.outputs_prefix == (
        f"{CiscoUmbrellaCloudSecurityv2.INTEGRATION_OUTPUT_PREFIX}."
        f"{CiscoUmbrellaCloudSecurityv2.DESTINATION_LIST_OUTPUT_PREFIX}"
    )
    assert command_results.outputs_key_field == CiscoUmbrellaCloudSecurityv2.ID_OUTPUTS_KEY_FIELD
    assert command_results.outputs == response["data"]
    assert command_results.raw_response == response


def test_list_destination_lists_command_list_request(requests_mock, mock_client):
    """
    Scenario:
    - Test listing destination lists

    Given:
    - Nothing

    When:
    - Running the umbrella-destination-lists-list command.

    Then:
    - Ensure that the CommandResults outputs_prefix is correct.
    - Ensure that the CommandResults outputs_key_field is correct.
    - Ensure that the CommandResults outputs is correct.
    - Ensure that the CommandResults raw_response is correct.
    """
    response = load_mock_response("destination_lists.json")
    requests_mock.get(url=DESTINATION_ENDPOINT, json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.list_destination_lists_command(
        mock_client, {}
    )

    assert command_results.outputs_prefix == (
        f"{CiscoUmbrellaCloudSecurityv2.INTEGRATION_OUTPUT_PREFIX}."
        f"{CiscoUmbrellaCloudSecurityv2.DESTINATION_LIST_OUTPUT_PREFIX}"
    )
    assert command_results.outputs_key_field == CiscoUmbrellaCloudSecurityv2.ID_OUTPUTS_KEY_FIELD
    assert command_results.outputs == response["data"]
    assert command_results.raw_response == response


def test_create_destination_list_command(requests_mock, mock_client):
    """
    Scenario:
    - Test creating a destination list

    Given:
    - Name, access, is_global, bundle_type, destinations, destinations_comment
        for a new destination list

    When:
    - Running the umbrella-destination-list-create command.

    Then:
    - Ensure that the CommandResults outputs_prefix is correct.
    - Ensure that the CommandResults outputs_key_field is correct.
    - Ensure that the CommandResults outputs is correct.
    - Ensure that the CommandResults raw_response is correct.
    """
    args = {
        "name": "Lior chose Pikachu",
        "access": CiscoUmbrellaCloudSecurityv2.Access.ALLOW.value,
        "is_global": "false",
        "bundle_type": "DNS",
        "destinations": ["1.1.1.1", "0.0.0.0"],
        "destinations_comment": "Comment",
    }
    response = load_mock_response("destination_list.json")["data"]

    requests_mock.post(url=DESTINATION_ENDPOINT, json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.create_destination_list_command(
        mock_client, args
    )

    assert command_results.outputs_prefix == (
        f"{CiscoUmbrellaCloudSecurityv2.INTEGRATION_OUTPUT_PREFIX}."
        f"{CiscoUmbrellaCloudSecurityv2.DESTINATION_LIST_OUTPUT_PREFIX}"
    )
    assert command_results.outputs_key_field == CiscoUmbrellaCloudSecurityv2.ID_OUTPUTS_KEY_FIELD
    assert command_results.outputs == response
    assert command_results.raw_response == response


def test_update_destination_list_command(requests_mock, mock_client):
    """
    Scenario:
    - Test updating a destination list

    Given:
    - A destination list ID and a new name

    When:
    - Running the umbrella-destination-list-update command.

    Then:
    - Ensure that the CommandResults outputs_prefix is correct.
    - Ensure that the CommandResults outputs_key_field is correct.
    - Ensure that the CommandResults outputs is correct.
    - Ensure that the CommandResults raw_response is correct.
    """
    args = {
        "destination_list_id": "123",
        "name": "Lior Sabri",
    }
    response = load_mock_response("destination_list.json")
    url = CommonServerPython.urljoin(DESTINATION_ENDPOINT, args["destination_list_id"])

    requests_mock.patch(url=url, json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.update_destination_list_command(
        mock_client, args
    )

    assert command_results.outputs_prefix == (
        f"{CiscoUmbrellaCloudSecurityv2.INTEGRATION_OUTPUT_PREFIX}."
        f"{CiscoUmbrellaCloudSecurityv2.DESTINATION_LIST_OUTPUT_PREFIX}"
    )
    assert command_results.outputs_key_field == CiscoUmbrellaCloudSecurityv2.ID_OUTPUTS_KEY_FIELD
    assert command_results.outputs == response["data"]
    assert command_results.raw_response == response


def test_delete_destination_list_command(requests_mock, mock_client):
    """
    Scenario:
    - Test deleting a destination list

    Given:
    - A destination list ID

    When:
    - delete_destination_list_command

    Then:
    - Ensure that the CommandResults readable_output is correct.
    - Ensure that the CommandResults raw_response is correct.
    """
    args = {
        "destination_list_id": "123",
    }
    response = load_mock_response("delete.json")

    url = CommonServerPython.urljoin(DESTINATION_ENDPOINT, args["destination_list_id"])

    requests_mock.delete(url=url, json=response)

    command_results: CommonServerPython.CommandResults = CiscoUmbrellaCloudSecurityv2.delete_destination_list_command(
        mock_client, args
    )

    expected_readable_output = f'The destination list "{args["destination_list_id"]}" was successfully deleted'

    assert command_results.readable_output == expected_readable_output
    assert command_results.raw_response == response


def test_get_access_token(requests_mock, mock_client):
    """
    Scenario:
    - Test the flow of getting an access token
    When:
    - Running the get_access_token method.
    Then:
    - Ensure that an access token is returned.
    """

    response = {"token_type": "bearer", "access_token": "Pichu", "expires_in": 3600}
    requests_mock.post(url=f"{BASE_URL}/auth/v2/token", json=response)

    access_token = CiscoUmbrellaCloudSecurityv2.Client.get_access_token(mock_client)

    assert access_token == response.get("access_token")