Details
| ID | CiscoWSA |
|---|---|
| Provider | Cisco Systems |
| Category | Utilities |
| From Version | 6.0.0 |
| Docker Image | demisto/python3:3.10.10.48392 |
| Supported Modules | Agentix XSIAM |
README
Cisco WSA
This integration was integrated and tested with version vSeries-100 of Cisco-WSA
Configure CiscoWSA in Cortex
| Parameter | Required |
|---|---|
| BASE_URL | True |
| API_KEY | True |
| PORT | 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.
wsa-get-access-policies
Retrieving all access policies
Base Command
wsa-get-access-policies
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| wsa.AccessPolicies | string | Retrieving all access policies |
Command Example
#### Context Example
```json
{
"access_policies": [
{
"amw_reputation": {
"state": "use_global"
},
"avc": {
"state": "use_global"
},
"http_rewrite_profile": "use_global",
"membership": {
"identification_profiles": [
{
"profile2": {
"auth": "No Authentication"
}
}
],
"protocols": [
{
"id_profile": "profile2",
"value": [
"http",
"https",
"ftp"
]
}
]
},
"objects": {
"state": "use_global"
},
"policy_description": "",
"policy_expiry": "",
"policy_name": "policy2",
"policy_order": 1,
"policy_status": "enable",
"protocols_user_agents": {
"state": "use_global"
},
"url_filtering": {
"custom_cats": {
"use_global": [
"SocialURLCategorynader1"
]
},
"exception_referred_embedded_content": {
"state": "disable"
},
"state": "custom",
"update_cats_action": "use_global",
"yt_cats": {
"use_global": [
"Film & Animation",
"Autos & Vehicles",
"Music",
"Pets & Animals",
"Sports",
"Travel & Events",
"Gaming",
"People & Blogs",
"Comedy",
"Entertainment",
"News & Politics",
"Howto & Style",
"Education",
"Science & Technology",
"Nonprofits & Activism"
]
}
}
},
{
"amw_reputation": {
"state": "use_global"
},
"avc": {
"state": "use_global"
},
"http_rewrite_profile": "use_global",
"membership": {
"identification_profiles": [
{
"profile1": {
"auth": "No Authentication"
}
}
],
"protocols": [
{
"id_profile": "profile1",
"value": [
"http",
"https",
"ftp"
]
}
]
},
"objects": {
"state": "use_global"
},
"policy_description": "",
"policy_expiry": "",
"policy_name": "policy1",
"policy_order": 2,
"policy_status": "enable",
"protocols_user_agents": {
"state": "use_global"
},
"url_filtering": {
"custom_cats": {
"use_global": [
"SocialURLCategorynader1"
]
},
"exception_referred_embedded_content": {
"state": "disable"
},
"state": "custom",
"update_cats_action": "use_global",
"yt_cats": {
"use_global": [
"Film & Animation",
"Autos & Vehicles",
"Music",
"Pets & Animals",
"Sports",
"Travel & Events",
"Gaming",
"People & Blogs",
"Comedy",
"Entertainment",
"News & Politics",
"Howto & Style",
"Education",
"Science & Technology",
"Nonprofits & Activism"
]
}
}
},
{
"amw_reputation": {
"state": "use_global"
},
"avc": {
"state": "use_global"
},
"http_rewrite_profile": "use_global",
"membership": {
"identification_profiles": [
{
"profile2": {
"auth": "No Authentication"
}
}
],
"protocols": [
{
"id_profile": "profile2",
"value": [
"http",
"https",
"ftp"
]
}
]
},
"objects": {
"state": "use_global"
},
"policy_description": "",
"policy_expiry": "",
"policy_name": "nader2",
"policy_order": 3,
"policy_status": "enable",
"protocols_user_agents": {
"state": "use_global"
},
"url_filtering": {
"custom_cats": {
"use_global": [
"SocialURLCategorynader1"
]
},
"exception_referred_embedded_content": {
"state": "disable"
},
"state": "custom",
"update_cats_action": "use_global",
"yt_cats": {
"use_global": [
"Film & Animation",
"Autos & Vehicles",
"Music",
"Pets & Animals",
"Sports",
"Travel & Events",
"Gaming",
"People & Blogs",
"Comedy",
"Entertainment",
"News & Politics",
"Howto & Style",
"Education",
"Science & Technology",
"Nonprofits & Activism"
]
}
}
},
{
"amw_reputation": {
"state": "use_global"
},
"avc": {
"state": "use_global"
},
"http_rewrite_profile": "use_global",
"membership": {
"identification_profiles": [
{
"profile1": {
"auth": "No Authentication"
}
}
],
"protocols": [
{
"id_profile": "profile1",
"value": [
"http",
"https",
"ftp"
]
}
]
},
"objects": {
"state": "use_global"
},
"policy_description": "",
"policy_expiry": "",
"policy_name": "nader1",
"policy_order": 4,
"policy_status": "enable",
"protocols_user_agents": {
"state": "use_global"
},
"url_filtering": {
"custom_cats": {
"use_global": [
"SocialURLCategorynader1"
]
},
"exception_referred_embedded_content": {
"state": "disable"
},
"state": "custom",
"update_cats_action": "use_global",
"yt_cats": {
"use_global": [
"Film & Animation",
"Autos & Vehicles",
"Music",
"Pets & Animals",
"Sports",
"Travel & Events",
"Gaming",
"People & Blogs",
"Comedy",
"Entertainment",
"News & Politics",
"Howto & Style",
"Education",
"Science & Technology",
"Nonprofits & Activism"
]
}
}
},
{
"amw_reputation": {
"cisco_dvs_amw": {
"amw_scanning": {
"amw_scan_status": "disable",
"amw_scanners": {
"mcafee": "unavailable",
"sophos": "unavailable",
"webroot": "unavailable"
}
},
"other_categories": {},
"suspect_user_agent_scanning": "scan"
},
"web_reputation": {
"filtering": "unavailable"
}
},
"avc": {
"state": "unavailable"
},
"http_rewrite_profile": "None",
"membership": {
"identification_profiles": [
{
"_all_": {
"auth": "No Authentication"
}
}
]
},
"objects": {
"max_object_size_mb": {
"ftp": 0,
"http_or_https": 0
},
"object_type": {
"Archives": {
"monitor": [
"StuffIt",
"BinHex",
"LHARC",
"ARC",
"ARJ"
]
},
"Document Types": {
"monitor": [
"PostScript Document (PS)",
"OpenOffice Document",
"OASIS Open Document Format",
"Microsoft Office",
"XML Document",
"Portable Document Format (PDF)",
"FrameMaker Document (FM)",
"Rich Text Format (RTF)"
]
},
"Executable Code": {
"monitor": [
"UNIX Executable",
"Windows Executable",
"Java Applet"
]
},
"Inspectable Archives": {
"allow": [
"BZIP2",
"CPIO",
"7zip",
"RAR",
"LHA",
"ZIP Archive",
"GZIP",
"Compress Archive (Z)",
"TAR",
"Microsoft CAB"
]
},
"Installers": {
"monitor": [
"UNIX/LINUX Packages"
]
},
"Media": {
"monitor": [
"Photographic Images",
"Video",
"Audio"
]
},
"Miscellaneous": {
"monitor": [
"Calendar Data"
]
},
"P2P Metafiles": {
"monitor": [
"BitTorrent Links (.torrent)"
]
},
"Web Page Content": {
"monitor": [
"Images",
"Flash"
]
}
},
"state": "custom"
},
"policy_description": "Default settings",
"policy_expiry": "",
"policy_name": "global_policy",
"policy_status": "enable",
"protocols_user_agents": {
"allow_connect_ports": [
"8080",
"21",
"443",
"563",
"4431",
"6443",
"8443",
"20",
"6080"
],
"block_custom_user_agents": [],
"block_protocols": [],
"state": "custom"
},
"url_filtering": {
"custom_cats": {
"exclude": [
"SocialURLCategorynader1"
]
},
"exception_referred_embedded_content": {
"state": "disable"
},
"update_cats_action": "least restrictive",
"yt_cats": {
"monitor": [
"Film & Animation",
"Autos & Vehicles",
"Music",
"Pets & Animals",
"Sports",
"Travel & Events",
"Gaming",
"People & Blogs",
"Comedy",
"Entertainment",
"News & Politics",
"Howto & Style",
"Education",
"Science & Technology",
"Nonprofits & Activism"
]
}
}
}
]
}
Human Readable Output
Results
access_policies
wsa-get-domain-map
Retrieving the Domain Map Details
Base Command
wsa-get-domain-map
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| wsa.DomainMaps | string | Retrieving the Domain Map Details |
Command Example
#### Context Example
```json
{
"res_code": 400,
"res_message": "The feature key for https proxy has expired or is unavailable."
}
Human Readable Output
Results
res_code res_message 400 The feature key for https proxy has expired or is unavailable.
wsa-get-url-categories
Retrieving URL Categories
Base Command
wsa-get-url-categories
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| wsa.UrlCategories | string | Retrieving URL Categories |
Command Example
#### Context Example
```json
{
"custom": [
"SocialURLCategorynader1"
],
"predefined": null
}
Human Readable Output
Results
custom predefined SocialURLCategorynader1
wsa-get-identification-profiles
Modifying identification profiles
Base Command
wsa-get-identification-profiles
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| wsa.Profiles | string | Retrieving Identification Profiles |
Command Example
#### Context Example
```json
{
"identification_profiles": [
{
"description": "",
"identification_method": {},
"members": {
"protocols": [
"http",
"https",
"ftp"
]
},
"order": 1,
"profile_name": "profile2",
"status": "enable"
},
{
"description": "",
"identification_method": {},
"members": {
"protocols": [
"http",
"https",
"ftp"
]
},
"order": 2,
"profile_name": "profile1",
"status": "enable"
},
{
"description": "Default settings",
"identification_method": {},
"profile_name": "global_identification_profile",
"status": "enable"
}
]
}
Human Readable Output
Results
identification_profiles
wsa-modify-access-policies
Modifying an Access Policy
Base Command
wsa-modify-access-policies
Input
| Argument Name | Description | Required |
|---|---|---|
| policyname | Name of the policy. Unique identifier of the policy. | Required |
| profile_name | (profile_name, auth). Use “No Authentication” in case of no authentication required for the specific profile. Empty strings represents “global identification profile”. all represents “All identification profiles”. Please all inputs comma separated. | Required |
| auth | (profile_name,auth). Use “No Authentication” in case of no authentication required for the specific profile. Empty strings represents “global identification profile”. all represents “All identification profiles”. Please all inputs comma separated. | Required |
| policy_order | Index of this specific profile in the collection. Its starts from 1. Order of policy in collection of policies. Not applicable for global_policy. | Required |
| policy_status | Whether profile is enabled or disabled. Possible values: enable, disable. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| wsa.response | string | whether the result indicates if request is success or failure |
Command Example
!wsa-modify-access-policies policyname=policy1 profile_name=profile1 policy_order=2 policy_status=disable auth="No Authentication"
Context Example
{
"wsa": {
"response": "The modifying request has been processed successfully and all the given access policies are updated with the given payload"
}
}
Human Readable Output
Results
wsa
wsa-delete-access-policies
Deleting an Access Policy
Base Command
wsa-delete-access-policies
Input
| Argument Name | Description | Required |
|---|---|---|
| policy_name | Name of the policy. Unique identifier of the policy. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| wsa.response | unknown | whether the result indicates if request is success or failure |
Command Example
!wsa-delete-access-policies policy_name=policy2
Context Example
{
"wsa": {
"response": "The deleting request has been processed successfully and all the given access policies are updated with the given payload"
}
}
Human Readable Output
Results
wsa
Configuration parameters
url— Server URL (required)apikey— API Key (required)port— Portinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (6)
-
wsa-delete-access-policiesDeleting an Access Policy
-
wsa-get-access-policiesRetrieving all access policies
-
wsa-get-domain-mapRetrieving the Domain Map Details
-
wsa-get-identification-profilesModifying identification profiles
-
wsa-get-url-categoriesRetrieving URL Categories
-
wsa-modify-access-policiesModifying an Access Policy
import defusedxml.ElementTree as defused_ET from CommonServerPython import * from CommonServerUserPython import * ''' CONSTANTS ''' DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ' ''' CLIENT CLASS ''' class Client(BaseClient): def _httpp_request(self, method, url_suffix='', full_url=None, headers=None, auth=None, json_data=None, params={}, data=None, files=None, timeout=100, resp_type='json', ok_codes=None, return_empty_response=False, retries=0, status_list_to_retry=None, backoff_factor=5, raise_on_redirect=False, raise_on_status=False, error_handler=None, empty_valid_codes=None, **kwargs): try: # Replace params if supplied address = full_url if full_url else urljoin(self._base_url, url_suffix) headers = headers if headers else self._headers auth = auth if auth else self._auth if retries: self._implement_retry(retries, status_list_to_retry, backoff_factor, raise_on_redirect, raise_on_status) # Execute res = self._session.request( method, address, verify=self._verify, params=params, data=data, json=json_data, files=files, headers=headers, auth=auth, timeout=timeout, **kwargs) # Handle error responses gracefully if not self._is_status_code_valid(res, ok_codes): if error_handler: error_handler(res) else: err_msg = 'Error in API call [{}] - {}' \ .format(res.status_code, res.reason) try: # Try to parse json error response error_entry = res.json() err_msg += '\n{}'.format(json.dumps(error_entry)) raise DemistoException(err_msg, res=res) except ValueError: err_msg += '\n{}'.format(res.text) raise DemistoException(err_msg, res=res) if not empty_valid_codes: empty_valid_codes = [204] is_response_empty_and_successful = (res.status_code in empty_valid_codes) if is_response_empty_and_successful and return_empty_response: return res resp_type = resp_type.lower() try: if resp_type == 'json': return res.json() if resp_type == 'text': return res.text if resp_type == 'content': return res.content if resp_type == 'xml': defused_ET.parse(res.text) return res except ValueError: pass except requests.exceptions.RetryError: pass def get_access_policies(self) -> CommandResults: data = self._httpp_request( method='GET', url_suffix='/wsa/api/v3.0/web_security/access_policies') return data def get_domain_map(self) -> CommandResults: data = self._httpp_request( method='GET', url_suffix='/wsa/api/v2.0/configure/web_security/domain_map') return data def get_url_categories(self) -> CommandResults: data = self._httpp_request( method='GET', url_suffix='/wsa/api/v3.0/generic_resources/url_categories') return data def get_identification_profiles(self) -> CommandResults: data = self._httpp_request( method='GET', url_suffix='/wsa/api/v3.0/web_security/identification_profiles') return data def modify_access_policies(self, args) -> CommandResults: policy_name = args.get('policyname') profile_name = args.get('profile_name') policy_order = args.get('policy_order') policy_status = args.get('policy_status') auth = args.get('auth') accesspoliciesdata = {"access_policies": [{"policy_name": "{}".format(policy_name), "policy_status": "{}".format(policy_status), "policy_order": int(policy_order), "membership": {"identification_profiles": [{ "profile_name": "{}".format(profile_name), "auth": "{}".format(auth)}]}}]} response = self._httpp_request(method='PUT', url_suffix='/wsa/api/v3.0/web_security/access_policies?format=json', data=json.dumps(accesspoliciesdata)) try: if not response: outputs = {'wsa': { 'response': "The modifying request has been processed successfully and all " "the given access policies are updated with the given payload"}} return CommandResults( outputs=outputs) else: outputs = {'wsa': { 'response': response}} return CommandResults( outputs=outputs) except DemistoException: pass return CommandResults(outputs=outputs) def delete_access_policies(self, a_data) -> CommandResults: policy_namess = a_data.get('policy_name') access_data = {"policy_names": policy_namess} data = self._httpp_request(method='DELETE', url_suffix='/wsa/api/v3.0/web_security/access_policies', params=access_data) try: if not data: outputs = {'wsa': { 'response': "The deleting request has been processed successfully and all " "the given access policies are updated with the given payload"}} return CommandResults( outputs=outputs) else: outputs = {'wsa': { 'response': data}} return CommandResults( outputs=outputs) except DemistoException: pass return CommandResults(outputs=outputs) ''' HELPER FUNCTIONS ''' def initiateheaderrequest(api_key): headerrequest = {'Content-Type': 'application/json', "cache-control": "no-cache", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36", "Accept": "*/*", 'Authorization': 'Basic {}'.format(api_key), "accept-encoding": "gzip, deflate"} return headerrequest ''' COMMAND FUNCTIONS ''' def test_module(client: Client): try: client.get_access_policies() except DemistoException as exception: if 'Authorization Required' in str(exception) or 'Authentication failed' in str(exception): return_error(f'Authorization Error: please check your credentials.\n\nError:\n{exception}') if 'HTTPSConnectionPool' in str(exception): return_error(f'Connection Error: please check your server ip address.\n\nError: {exception}') raise return 'ok' def wsa_get_access_policies_command(client) -> CommandResults: results = client.get_access_policies() return CommandResults( outputs_key_field='', outputs=results) def wsa_get_domain_map_command(client) -> CommandResults: results = client.get_domain_map() return CommandResults( outputs_key_field='', outputs=results) def wsa_get_url_categories_command(client) -> CommandResults: results = client.get_url_categories() return CommandResults( outputs_key_field='', outputs=results) def wsa_get_identification_profiles_command(client) -> CommandResults: results = client.get_identification_profiles() return CommandResults( outputs_key_field='', outputs=results) def wsa_delete_access_policies_command(client, args): results = client.delete_access_policies(args) return results def wsa_modify_access_policies_command(client, args): results = client.modify_access_policies(args) return results ''' MAIN FUNCTION ''' def main() -> None: args = demisto.args() api_key = demisto.params()['apikey'] port = demisto.params()['port'] port = ":" + port base_url = demisto.params()['url'] + port verify_certificate = demisto.params()['insecure'] proxyy = demisto.params().get('proxy', False) handle_proxy() demisto.debug(f'Command being called is {demisto.command()}') try: header = initiateheaderrequest(api_key) client = Client( base_url=base_url, verify=verify_certificate, headers=header, proxy=proxyy) if demisto.command() == 'test-module': # This is the call made when pressing the integration Test button. return_results(test_module(client)) elif demisto.command() == 'wsa-get-access-policies': return_results(wsa_get_access_policies_command(client)) elif demisto.command() == 'wsa-get-domain-map': return_results(wsa_get_domain_map_command(client)) elif demisto.command() == 'wsa-get-identification-profiles': return_results(wsa_get_identification_profiles_command(client)) elif demisto.command() == 'wsa-get-url-categories': return_results(wsa_get_url_categories_command(client)) elif demisto.command() == 'wsa-delete-access-policies': return_results(wsa_delete_access_policies_command(client, args)) elif demisto.command() == 'wsa-modify-access-policies': return_results(wsa_modify_access_policies_command(client, args)) # Log exceptions and return errors except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f'Failed to execute {demisto.command()} command.\nError:\n{str(e)}') ''' ENTRY POINT ''' if __name__ in ('__main__', '__builtin__', 'builtins'): main()