Cisco Umbrella Cloud Security Deprecated

Deprecated. Use Cisco Umbrella Cloud Security v2 instead.

Network Security · Cisco Umbrella cloud security

Details

IDCisco Umbrella Cloud Security
ProviderCisco Systems
CategoryNetwork Security
From Version6.0.0
Docker Imagedemisto/python3:3.12.11.4508456
Supported ModulesAgentix XSIAM

README

This integration was integrated and tested with version 1.0 of Cisco Umbrella Cloud Security.

Configure Cisco Umbrella Cloud Security in Cortex

Parameter Required
Organization ID True
API Key True
API Secret False
Trust any certificate (not secure) False
Use system proxy settings 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.

umbrella-get-destination-lists


Get’s all destination lists in organization

Base Command

umbrella-get-destination-lists

Input

Argument Name Description Required
orgId Organization ID. Optional

Context Output

Path Type Description
Umbrella.DestinationLists Unknown  

umbrella-add-domain


Adds domains to given destination list

Base Command

umbrella-add-domain

Input

Argument Name Description Required
orgId Optional organization ID. If not provided, will use the one provided in the integration configuration. Optional
destId Destination list ID. Required
domains List of domains to add to destination list (Format: domain1.com,domain2.com). Required
comment Note on what the domain is or why it is being added. Default is Added from XSOAR. Optional

Context Output

There is no context output for this command.

umbrella-get-destination-domains


Get’s the domains listed in a destination list

Base Command

umbrella-get-destination-domains

Input

Argument Name Description Required
orgId Optional orgId, by default uses the one set in the instance configuration. Optional
destId Destination list ID to get domains from. Use umbrella-get-destination-lists to get the list ID. Required

Context Output

Path Type Description
Umbrella.Destinations.createdAt Unknown When the domain within destination list was created
Umbrella.Destinations.type Unknown Type of destination within destination list
Umbrella.Destinations.destination Unknown Domain within destination list
Umbrella.Destinations.id Unknown ID of domain within destination list
Umbrella.Destinations.comment Unknown Comment associated with domain within destination list

umbrella-remove-domain


Removes domains to given destination list

Base Command

umbrella-remove-domain

Input

Argument Name Description Required
orgId Optional organization ID. If not provided, will use the one provided in the integration configuration. Optional
destId Destination list ID. Required
domainIds List of entry IDs to remove from destination list (Format: 1234,1235). Required

Context Output

There is no context output for this command.

umbrella-get-destination-domain


Gets the domain from a destination list

Base Command

umbrella-get-destination-domain

Input

Argument Name Description Required
orgId Optional orgId, by default uses the one set in the instance configuration. Optional
destId Destination list ID to get domains from. Use umbrella-get-destination-lists to get the list ID. Required

Context Output

Path Type Description
Umbrella.Destinations.createdAt Unknown When the domain within destination list was created
Umbrella.Destinations.type Unknown Type of destination within destination list
Umbrella.Destinations.destination Unknown Domain within destination list
Umbrella.Destinations.id Unknown ID of domain within destination list
Umbrella.Destinations.comment Unknown Comment associated with domain within destination list

umbrella-search-destination-domains


Search for multiple domains in a destination list

Base Command

umbrella-search-destination-domains

Input

Argument Name Description Required
orgId Optional orgId, by default uses the one set in the instance configuration. Optional
destId Destination list ID to get domains from. Use umbrella-get-destination-lists to get the list ID. Required
domains Domains to search for in a destination list. Required

Context Output

Path Type Description
Umbrella.Destinations.createdAt date When the domain within destination list was created
Umbrella.Destinations.type string Type of destination within destination list
Umbrella.Destinations.destination string Domain within destination list
Umbrella.Destinations.id number ID of domain within destination list
Umbrella.Destinations.comment string Comment associated with domain within destination list

Configuration parameters

  • orgId — Organization ID (required)
  • apiKey — API Key (required)
  • apiSecret — API Secret
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (6)

  • umbrella-add-domain

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

  • umbrella-get-destination-domain

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

  • umbrella-get-destination-domains

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

  • umbrella-get-destination-lists

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

  • umbrella-remove-domain

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

  • umbrella-search-destination-domains

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

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401

''' IMPORTS '''


import base64
import json
import traceback

''' CLIENT CLASS '''


class Client(BaseClient):
    def __init__(self, base_url, *args, **kwarg):
        super().__init__(base_url, *args, **kwarg)

    def get_destination_lists(self, organizationId):
        uri = f'{organizationId}/destinationlists'
        return self._http_request('GET', uri)

    def get_destinations(self, organizationId, destinationListId, params=None):
        uri = f'/{organizationId}/destinationlists/{destinationListId}/destinations'
        return self._http_request('GET', uri, params=params)

    def add_domain(self, organizationId, destinationListId, data):
        uri = f'{organizationId}/destinationlists/{destinationListId}/destinations'
        return self._http_request('POST', uri, data=data)

    def remove_domain(self, organizationId, destinationListId, data):
        # https://docs.umbrella.com/umbrella-api/reference#delete_v1-organizations-organizationid-destinationlists-destinationlistid-destinations-remove
        uri = f'{organizationId}/destinationlists/{destinationListId}/destinations/remove'
        return self._http_request('DELETE', uri, data=data)


''' HELPER FUNCTIONS '''


def get_first_page_of_destinations(client, organizationId, destinationListId):
    page_limit = 100
    page = 1
    r = client.get_destinations(organizationId, destinationListId, params={'page': page, 'limit': page_limit})

    return page_limit, page, r


def get_destination_domains(client, organizationId, destinationListId):
    page_limit, page, r = get_first_page_of_destinations(client, organizationId, destinationListId)

    destination_domains = []
    while r.get('data'):
        if r.get('meta').get('total') == 0:
            uri = f'/{organizationId}/destinationlists/{destinationListId}/destinations'
            demisto.info(f'Unexpected "total" value of 0 returned from Umbrella {uri} API call')
            break
        destination_domains += r.get('data')
        page += 1
        r = client.get_destinations(organizationId, destinationListId, params={'page': page, 'limit': page_limit})

    return destination_domains


def get_destination_domain(client, organizationId, destinationListId, domain):
    demisto.debug(f'domain: {domain}')
    page_limit, page, r = get_first_page_of_destinations(client, organizationId, destinationListId)

    destination_domain = None
    while r.get('data') and not destination_domain:
        if r.get('meta').get('total') == 0:
            uri = f'/{organizationId}/destinationlists/{destinationListId}/destinations'
            demisto.info(f'Unexpected "total" value of 0 returned from Umbrella {uri} API call')
            break
        for d in r.get('data'):
            if d.get('destination') == domain:
                destination_domain = d
                break
        page += 1
        r = client.get_destinations(organizationId, destinationListId, params={'page': page, 'limit': page_limit})

    return destination_domain


def search_destination_domains(client, organizationId, destinationListId, domains):
    demisto.debug(f'domains: {domains}')
    page_limit, page, r = get_first_page_of_destinations(client, organizationId, destinationListId)

    destination_domains = []
    while r.get('data'):
        if r.get('meta').get('total') == 0:
            uri = f'/{organizationId}/destinationlists/{destinationListId}/destinations'
            demisto.info(f'Unexpected "total" value of 0 returned from Umbrella {uri} API call')
            break
        destination_domains += r.get('data')
        page += 1
        r = client.get_destinations(organizationId, destinationListId, params={'page': page, 'limit': page_limit})

    destination_domains_found = []

    if destination_domains:
        for domain in domains:
            if domain in demisto.dt(destination_domains, 'destination'):
                destination_domains_found += [d for d in destination_domains if d.get('destination') == domain]
                demisto.debug(f'destination_domains_found: {destination_domains_found}')

    return destination_domains_found


''' COMMAND FUNCTIONS '''


def test_module(client: Client, **args) -> str:
    organizationId = args.get('orgId')

    if not organizationId:
        return "organizationId not provided"

    uri = f'/{organizationId}/destinationlists'

    client._http_request('GET', uri)

    return "ok"


def get_destination_lists_command(client: Client, **args) -> CommandResults:
    r = client.get_destination_lists(args.get('orgId'))

    data = []
    for destination_list in r['data']:
        data.append(
            {
                'name': destination_list['name'],
                'id': destination_list['id']
            }
        )

    return CommandResults(
        outputs_prefix="Umbrella.DestinationLists",
        outputs_key_field="id",
        outputs=data
    )


def add_domain_command(client: Client, **args) -> str:
    destinations = argToList(args.get('domains'))
    comment = args.get('comment')

    # max allowable limit of destinations to send in one request is 500
    limit = 500
    if len(destinations) > limit:
        destinations_remaining = destinations
        while destinations_remaining:
            demisto.debug(f'length of destinations_remaining: {len(destinations_remaining)}')
            destinations_limited = destinations_remaining[0:limit]
            payload = json.dumps([{'destination': destination, 'comment': comment} for destination in destinations_limited])
            r = client.add_domain(args.get('orgId'), args.get('destId'), data=payload)
            destinations_remaining = destinations_remaining[limit:]
    else:
        payload = json.dumps([{'destination': destination, 'comment': comment} for destination in destinations])
        r = client.add_domain(args.get('orgId'), args.get('destId'), data=payload)

    return f'Domain(s) {", ".join(destinations)} successfully added to list {r["data"]["name"]}'


def remove_domain_command(client: Client, **args) -> str:
    destinations = argToList(args.get('domainIds'))
    payload = "[" + ", ".join(destinations) + "]"

    client.remove_domain(args.get('orgId'), args.get('destId'), data=payload)

    return f'Domain(s) {", ".join(destinations)} successfully removed from list'


def get_destination_domains_command(client: Client, **args) -> CommandResults:
    destination_domains = get_destination_domains(client, args.get('orgId'), args.get('destId'))

    return CommandResults(
        outputs_prefix="Umbrella.Destinations",
        outputs_key_field="id",
        outputs=destination_domains,
        readable_output=tableToMarkdown('Domains in Destination List', destination_domains)
    )


def get_destination_domain_command(client: Client, **args) -> CommandResults:
    destination_domain = get_destination_domain(client, args.get('orgId'), args.get('destId'), args.get('domain'))

    return CommandResults(
        outputs_prefix="Umbrella.Destinations",
        outputs_key_field="id",
        outputs=destination_domain,
        readable_output=tableToMarkdown('Domain in Destination List', destination_domain)
    )


def search_destination_domains_command(client: Client, **args) -> CommandResults:
    domains = argToList(args.get('domains'))
    destination_domains = search_destination_domains(client, args.get('orgId'), args.get('destId'), domains)

    return CommandResults(
        outputs_prefix="Umbrella.Destinations",
        outputs_key_field="id",
        outputs=destination_domains,
        readable_output=tableToMarkdown('Domains in Destination List', destination_domains)
    )


def main():
    # If an arg supplying an orgId is provided, will override the one found in params
    args = {**demisto.params(), **demisto.args()}

    base_url = 'https://management.api.umbrella.com/v1/organizations'
    api_key = base64.b64encode(f'{demisto.getParam("apiKey")}:{demisto.getParam("apiSecret")}'.encode("ascii"))
    verify = not args.get('insecure', False)
    proxy = args.get('proxy', False)

    headers = {
        'Accept': "application/json",
        'Content-Type': "application/json",
        'Authorization': f'Basic {api_key.decode("ascii")}'
    }

    try:
        client = Client(
            base_url,
            verify=verify,
            headers=headers,
            proxy=proxy
        )

        commands = {
            'umbrella-get-destination-lists': get_destination_lists_command,
            'umbrella-add-domain': add_domain_command,
            'umbrella-remove-domain': remove_domain_command,
            'umbrella-get-destination-domains': get_destination_domains_command,
            'umbrella-get-destination-domain': get_destination_domain_command,
            'umbrella-search-destination-domains': search_destination_domains_command,
            'test-module': test_module
        }

        command = demisto.command()
        if command in commands:
            return_results(commands[command](client, **args))
        else:
            return_error(f'Command {command} is not available in this integration')

    # Log exceptions and return errors
    except Exception as e:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(f'Failed to execute {command} command.\nError:\n{str(e)}')


if __name__ in ['__main__', '__builtin__', 'builtins']:
    main()