Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Marketplace Contribution] Cisco Umbrella cloud security - Content Pack Update #32939

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import demistomock as demisto # noqa: F401
from CommonServerPython import * # noqa: F401

import enum
import http
from collections.abc import Callable
from typing import Any, TypeVar

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

BASE_URL = 'https://api.umbrella.com'

Expand Down Expand Up @@ -83,17 +84,39 @@ def login(self) -> None:
Log in to the API using the API key and API secret.
The access token is stored in the headers of the request.
"""
response = self._http_request(
method='POST',
url_suffix=Client.AUTH_SUFFIX,
auth=(self.api_key, self.api_secret),
)
access_token = self.get_access_token()
self._headers['Authorization'] = f'Bearer {access_token}'

try:
access_token = response['access_token']
self._headers['Authorization'] = f'Bearer {access_token}'
except Exception as e:
raise DemistoException(f'Failed logging in: {response}') from e
def get_access_token(self):
"""
Get an access token that was previously created if it is still valid, else, generate a new access token from
the API key and secret.
"""
# Check if there is an existing valid access token
integration_context = get_integration_context()
if integration_context.get('access_token') and integration_context.get('expiry_time') > date_to_timestamp(datetime.now()):
return integration_context.get('access_token')
else:
try:
res = self._http_request(
method='POST',
url_suffix=Client.AUTH_SUFFIX,
headers={'Content-Type': 'application/x-www-form-urlencoded'},
auth=(self.api_key, self.api_secret),
data={'grant_type': 'client_credentials'}
)
if res.get('access_token'):
expiry_time = date_to_timestamp(datetime.now(), date_format='%Y-%m-%dT%H:%M:%S')
expiry_time += res.get('expires_in', 0) * 1000 - 10
context = {
'access_token': res.get('access_token'),
'expiry_time': expiry_time
}
set_integration_context(context)
return res.get('access_token')
except Exception as e:
return_error(f'Error occurred while creating an access token. Please check the instance configuration.'
f'\n\n{e.args[0]}')

def _get_destination_payload(
self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,18 @@ script:
- name: destination_list_id
description: The ID of the destination list. Destination lists can be fetched with the `umbrella-destination-lists-list` command.
required: true
isArray: false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not intentionally move all of these isArray and required. Do you want me to add them back in?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's fine, it could be a result of running the format command, you can keep them.

- name: destination_ids
description: Comma-separated list of destination IDs to be retrieved from a list of destinations.
required: false
isArray: true
- name: destinations
description: Comma-separated list of destinations to retrieve, a destination may be a domain, URL, or IP address.
required: false
isArray: true
- name: page
description: Page number of paginated results. Minimum 1; Default 1.
required: false
isArray: false
- name: page_size
description: The number of items per page. Minimum 1; Maximum 100; Default 50.
required: false
isArray: false
- name: limit
description: The number of items per page. Minimum 1.
required: false
isArray: false
defaultValue: '50'
outputs:
- type: String
Expand All @@ -73,15 +64,11 @@ script:
- name: destination_list_id
description: The ID of the destination list. Destination lists can be fetched with the `umbrella-destination-lists-list` command.
required: true
isArray: false
- name: destinations
description: Comma-separated list of destinations. A destination may be a URL, IPv4, CIDR or fully qualified domain name.
required: true
isArray: false
- name: comment
description: A comment about all the inserted destinations.
required: false
isArray: false
defaultValue: Added from XSOAR
outputs:
- type: Number
Expand Down Expand Up @@ -126,7 +113,6 @@ script:
- name: destination_list_id
description: The ID of the destination list. Destination lists can be fetched with the `umbrella-destination-lists-list` command.
required: true
isArray: false
- name: destination_ids
description: Comma-separated list of destination IDs. Destinations can be fetched with the `umbrella-destination-list` command.
required: true
Expand Down Expand Up @@ -173,20 +159,12 @@ script:
arguments:
- name: destination_list_id
description: The ID of the destination list to retrieve.
required: false
isArray: false
- name: page
description: Page number of paginated results. Minimum 1; Default 1.
required: false
isArray: false
- name: page_size
description: The number of items per page. Minimum 1; Maximum 100; Default 50.
required: false
isArray: false
- name: limit
description: The maximum number of records to retrieve. Minimum 1.
required: false
isArray: false
defaultValue: '50'
outputs:
- type: Number
Expand Down Expand Up @@ -242,40 +220,32 @@ script:
arguments:
- name: bundle_type
description: The type of the Umbrella policy associated with the destination list. If the field is not specified, the default value is 'DNS'.
required: false
isArray: false
auto: PREDEFINED
predefined:
- 'DNS'
- 'WEB'
- name: access
description: '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.'
required: true
isArray: false
auto: PREDEFINED
predefined:
- 'allow'
- 'block'
- name: is_global
description: 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.
required: true
isArray: false
auto: PREDEFINED
predefined:
- 'True'
- 'False'
- name: name
description: The name of the destination list.
required: true
isArray: false
- name: destinations
description: Comma-separated list of destinations. A destination may be a URL, IPv4, CIDR or fully qualified domain name.
required: false
isArray: true
- name: destinations_comment
description: A comment about all the inserted destinations.
required: false
isArray: false
defaultValue: Added from XSOAR
outputs:
- type: Number
Expand Down Expand Up @@ -320,11 +290,9 @@ script:
- name: destination_list_id
description: The ID of the destination list. Destination lists can be fetched with the `umbrella-destination-lists-list` command.
required: true
isArray: false
- name: name
description: The name of the destination list.
required: true
isArray: false
outputs:
- type: Number
contextPath: Umbrella.DestinationLists.id
Expand Down Expand Up @@ -368,7 +336,6 @@ script:
- name: destination_list_id
description: The ID of the destination list. Destination lists can be fetched with the `umbrella-destination-lists-list` command.
required: true
isArray: false
- arguments:
- description: Organization ID.
name: orgId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def test_list_destinations_command(requests_mock, mock_client):
- A destination list ID

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

Then:
- Ensure that the CommandResults outputs_prefix is correct.
Expand Down Expand Up @@ -111,7 +111,7 @@ def test_list_destinations_command_fetch_destinations(requests_mock, mock_client
- A destination list ID

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

Then:
- Ensure that the CommandResults outputs_prefix is correct.
Expand Down Expand Up @@ -168,7 +168,7 @@ def test_add_destinations_command(requests_mock, mock_client):
- A destination list ID and destinations

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

Then:
- Ensure that the CommandResults raw_response is correct.
Expand Down Expand Up @@ -206,7 +206,7 @@ def test_delete_destination_command(requests_mock, mock_client):
- A destination list ID and destination IDs

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

Then:
- Ensure that the CommandResults readable_output is correct.
Expand Down Expand Up @@ -243,7 +243,7 @@ def test_list_destination_lists_command(requests_mock, mock_client):
- A destination list ID

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

Then:
- Ensure that the CommandResults outputs_prefix is correct.
Expand Down Expand Up @@ -280,7 +280,7 @@ def test_list_destination_lists_command_list_request(requests_mock, mock_client)
- Nothing

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

Then:
- Ensure that the CommandResults outputs_prefix is correct.
Expand Down Expand Up @@ -314,7 +314,7 @@ def test_create_destination_list_command(requests_mock, mock_client):
for a new destination list

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

Then:
- Ensure that the CommandResults outputs_prefix is correct.
Expand Down Expand Up @@ -356,7 +356,7 @@ def test_update_destination_list_command(requests_mock, mock_client):
- A destination list ID and a new name

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

Then:
- Ensure that the CommandResults outputs_prefix is correct.
Expand Down Expand Up @@ -418,3 +418,29 @@ def test_delete_destination_list_command(requests_mock, mock_client):

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'{CiscoUmbrellaCloudSecurityv2.BASE_URL}/auth/v2/token',
json=response
)

access_token = CiscoUmbrellaCloudSecurityv2.Client.get_access_token(mock_client)

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

6 changes: 6 additions & 0 deletions Packs/Cisco-umbrella-cloud-security/ReleaseNotes/2_0_9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

#### Integrations

##### Cisco Umbrella Cloud Security v2

- Improved implementation of retrieving the *Access Token* in the authentication process.
4 changes: 2 additions & 2 deletions Packs/Cisco-umbrella-cloud-security/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Cisco Umbrella cloud security",
"description": "Basic integration with Cisco Umbrella that allows you to add domains to destination lists (e.g. global block / allow)",
"support": "xsoar",
"currentVersion": "2.0.8",
"currentVersion": "2.0.9",
"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"email": "",
Expand All @@ -18,4 +18,4 @@
"marketplacev2"
],
"certification": "certified"
}
}
Loading