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

pan-os-list-applications #24521

Merged
merged 16 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
64 changes: 56 additions & 8 deletions Packs/PAN-OS/Integrations/Panorama/Panorama.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@
'ransomware'
}

APPILICATION_FILTERS = ('risk', 'category', 'subcategory', 'technology')
class PAN_OS_Not_Found(Exception):
""" PAN-OS Error. """

Expand Down Expand Up @@ -690,6 +691,30 @@ def get_pan_os_major_version() -> int:

''' FUNCTIONS'''

def build_xpath_filter(name_match: str = None, name_contains: str = None, filters: dict = None) -> str:
"""Builds xpath according to the filters.

Returns:
xpath str
"""
xpath_prefix = ''
if name_match:
xpath_prefix = f"@name='{name_match}'"
if name_contains:
xpath_prefix = f"contains(@name,'{name_contains}')"
if filters:
for key, value in filters.items():
if key in APPILICATION_FILTERS:
if xpath_prefix:
xpath_prefix += 'and'
xpath_prefix += f"({key}='{value}')"
if key == 'characteristics':
for characteristic in value:
if xpath_prefix:
xpath_prefix += 'and'
xpath_prefix += f"({characteristic}='yes')"
return xpath_prefix


def panorama_test(fetch_params):
"""
Expand Down Expand Up @@ -4081,6 +4106,7 @@ def prettify_applications_arr(applications_arr: Union[List[dict], dict]):
for i in range(len(applications_arr)):
application = applications_arr[i]
pretty_application_arr.append({
'Category': application.get('category'),
'SubCategory': application.get('subcategory'),
'Risk': application.get('risk'),
'Technology': application.get('technology'),
Expand All @@ -4092,29 +4118,49 @@ def prettify_applications_arr(applications_arr: Union[List[dict], dict]):


@logger
def panorama_list_applications(predefined: bool) -> Union[List[dict], dict]:
def panorama_list_applications(args:Dict[str, str], predefined: bool) -> Union[List[dict], dict]:
major_version = get_pan_os_major_version()
params = {
'type': 'config',
'action': 'get',
'key': API_KEY
}
filters = assign_params(
name_match=args.get('name_match'),
risk=args.get('risk'),
category=args.get('category'),
subcategory=args.get('sub_category'),
technology=args.get('technology'),
characteristics=argToList(args.get('characteristics')),
)
name_match = args.get('name_match')
name_contain = args.get('name_contain')
xpath_filter = build_xpath_filter(name_match,name_contain,filters)
demisto.debug("xpath_filter", xpath_filter)
if predefined: # if predefined = true, no need for device group.
if major_version < 9:
raise Exception('Listing predefined applications is only available for PAN-OS 9.X and above versions.')
else:
params['xpath'] = '/config/predefined/application'
if xpath_filter:
params['xpath'] = f'/config/predefined/application/entry[{xpath_filter}]'
else:
params['xpath'] = '/config/predefined/application'
else:
# if device-group was provided it will be set in initialize_instance function.
params['xpath'] = XPATH_OBJECTS + "application/entry"

if xpath_filter:
params['xpath'] = XPATH_OBJECTS + f"application/entry[{xpath_filter}]"
else:
params['xpath'] = XPATH_OBJECTS + "application/entry"
demisto.debug(params['xpath'])
result = http_request(
URL,
'POST',
body=params
)
applications_api_response = result['response']['result']
if predefined:
if filters or name_match or name_contain:
applications = applications_api_response.get('entry') or []
elif predefined:
applications = applications_api_response.get('application', {}).get('entry') or []
else:
applications = applications_api_response.get('entry') or []
Expand All @@ -4124,13 +4170,15 @@ def panorama_list_applications(predefined: bool) -> Union[List[dict], dict]:
return applications


def panorama_list_applications_command(predefined: Optional[str] = None):
def panorama_list_applications_command(args:Dict[str, str] ,predefined: Optional[str] = None):
"""
List all applications
"""
predefined = predefined == 'true'
applications_arr = panorama_list_applications(predefined)
applications_arr = panorama_list_applications(args,predefined)
applications_arr_output = prettify_applications_arr(applications_arr)
limit = arg_to_number(args.get('limit')) or DEFAULT_LIMIT_PAGE_SIZE
applications_arr_output=applications_arr_output[:limit]
headers = ['Id', 'Name', 'Risk', 'Category', 'SubCategory', 'Technology', 'Description']

return_results({
Expand Down Expand Up @@ -13464,7 +13512,7 @@ def main(): # pragma: no cover

# Application
elif command == 'panorama-list-applications' or command == 'pan-os-list-applications':
panorama_list_applications_command(args.get('predefined'))
panorama_list_applications_command(args,args.get('predefined'))

# Test security policy match
elif command == 'panorama-security-policy-match' or command == 'pan-os-security-policy-match':
Expand Down
52 changes: 52 additions & 0 deletions Packs/PAN-OS/Integrations/Panorama/Panorama.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5284,6 +5284,58 @@ script:
- description: The device group for which to return applications.
name: device-group
required: false
- description: When specified, returned in the list are limited to applications whose name match the specified string.
name: name_match
required: false
isArray: false
- description: When specified, returned in the list are limited to applications whose name contains the specified string.
name: name_contain
required: false
isArray: false
- description: The application risk (1 to 5).
auto: PREDEFINED
name: risk
required: false
isArray: false
predefined:
- '1'
- '2'
- '3'
- '4'
- '5'
- description: The application category.
auto: PREDEFINED
name: category
required: false
isArray: false
predefined:
- 'collaboration'
- 'business-systems'
- 'networking'
- 'media'
- description: The application sub-category.
name: sub_category
required: false
isArray: false
- description: The application technology.
auto: PREDEFINED
name: technology
required: false
isArray: false
predefined:
- 'browser-based'
- 'client-server'
- 'network-protocol'
- 'peer-to-peer'
- description: "A comma-separated list, possible values are: 'virus-ident', 'evasive-behavior', 'file-type-ident', 'consume-big-bandwidth', 'used-by-malware', 'able-to-transfer-file', 'has-known-vulnerability', 'tunnel-other-application', 'prone-to-misuse', 'pervasive-use', 'file-forward', 'is-saas'."
name: characteristics
required: false
isArray: false
- defaultValue: '50'
description: The maximum number of results to retrieve.
isArray: false
name: limit
required: false
description: Returns a list of applications.
name: pan-os-list-applications
outputs:
Expand Down
54 changes: 53 additions & 1 deletion Packs/PAN-OS/Integrations/Panorama/Panorama_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ def test_panorama_list_applications_command(mocker, panorama_version):
mocker.patch('Panorama.get_pan_os_major_version', return_value=panorama_version)

res = mocker.patch('demistomock.results')
panorama_list_applications_command(predefined='false')
panorama_list_applications_command({}, predefined='false')

assert res.call_args.args[0]['Contents'] == {
'@name': 'test-playbook-app', '@loc': 'Lab-Devices', 'subcategory': 'infrastructure',
Expand Down Expand Up @@ -6380,3 +6380,55 @@ def test_second_fetch_with_two_incidents_with_different_log_types_and_different_
assert last_id_dict.get('X_log_type', '') == '000000002'
assert last_fetch_dict.get('Y_log_type', '') == '2022-01-01 13:00:00'
assert last_id_dict.get('Y_log_type', '') == '000000002'


case_only_name = (
Copy link
Contributor

Choose a reason for hiding this comment

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

What will happen if you give both name and name_match?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If there is an application that meets the requirements the API returns it else we get a warning entry for an empty list (this is a known issue related to pan-os response parsing)

'name',
None,
{},
"@name='name'"
)

case_only_name_match: tuple = (
None,
'name_match',
{},
"contains(@name,'name_match')"
)

case_with_characteristics = (
'name',
None,
{'category': 'some_category',
'characteristics': ['file-type-ident', 'consume-big-bandwidth', 'used-by-malware'],
'risk': '5',
'sub_category': 'some_sub_category',
'technology': 'browser-based'
},
"@name='name'and(category='some_category')and(file-type-ident='yes')and(consume-big-bandwidth='yes')"
"and(used-by-malware='yes')and(risk='5')and(technology='browser-based')"
)
case_empty: tuple = (
'',
'',
{},
''
)
get_mock_rules = [case_only_name, case_only_name_match, case_with_characteristics, case_empty]


@pytest.mark.parametrize('name_match, name_contains, filters, expected_result', get_mock_rules)
def test_build_xpath_filter(name_match, name_contains, filters, expected_result):
"""
Given
- Filters: str and dict.

When -
running the pan-os-list-applictions command.

Then
- make sure the str xpath is correct.
"""
from Panorama import build_xpath_filter
mock_result = build_xpath_filter(name_match, name_contains, filters)
assert mock_result == expected_result
29 changes: 19 additions & 10 deletions Packs/PAN-OS/Integrations/Panorama/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2561,21 +2561,30 @@ Returns a list of applications.
#### Input

| **Argument Name** | **Description** | **Required** |
|-------------------| --- | --- |
| predefined | Whether to list predefined applications or not. | Optional |
| device-group | The device group for which to return applications. | Optional |
| --- | --- | --- |
| predefined | Whether to list predefined applications. Possible values are: true, false. Default is false. | Optional |
| device-group | The device group for which to return applications. | Optional |
| name_match | When specified, returned in the list are limited to applications whose name match the specified string. | Optional |
| name_contain | When specified, returned in the list are limited to applications whose name contains the specified string. | Optional |
| risk | The application risk (1 to 5). Possible values are: 1, 2, 3, 4, 5. | Optional |
| category | The application category. Possible values are: collaboration, business-systems, networking, media. | Optional |
| sub_category | The application sub-category. | Optional |
| technology | The application technology. Possible values are: browser-based, client-server, network-protocol, peer-to-peer. | Optional |
| characteristics | A comma-separated list, possible values are: 'virus-ident', 'evasive-behavior', 'file-type-ident', 'consume-big-bandwidth', 'used-by-malware', 'able-to-transfer-file', 'has-known-vulnerability', 'tunnel-other-application', 'prone-to-misuse', 'pervasive-use', 'file-forward', 'is-saas'. | Optional |
| limit | The maximum number of results to retrieve. Default is 50. | Optional |


#### Context Output

| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Panorama.Applications.Name | string | Application name. |
| Panorama.Applications.Id | number | Application ID. |
| Panorama.Applications.Category | string | Application category. |
| Panorama.Applications.SubCategory | string | Application sub-category. |
| Panorama.Applications.Technology | string | Application technology. |
| Panorama.Applications.Risk | number | Application risk \(1 to 5\). |
| Panorama.Applications.Description | string | Application description. |
| Panorama.Applications.Name | string | The application name. |
| Panorama.Applications.Id | number | The application ID. |
| Panorama.Applications.Category | string | The application category. |
| Panorama.Applications.SubCategory | string | The application sub-category. |
| Panorama.Applications.Technology | string | The application technology. |
| Panorama.Applications.Risk | number | The application risk \(1 to 5\). |
| Panorama.Applications.Description | string | The application description. |


#### Command Example
Expand Down
6 changes: 6 additions & 0 deletions Packs/PAN-OS/ReleaseNotes/1_16_9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

#### Integrations
##### Palo Alto Networks PAN-OS
- Added support for filters *characteristics*, *technology*, *sub_category*, *category*, *risk*, *name_contain*, *name_match* arguments in the ***pan-os-list-applications*** command.
- Added support for *limit* argument in the ***pan-os-list-applications*** command.
- Updated the Docker image to: *demisto/pan-os-python:1.0.0.47142*.
2 changes: 1 addition & 1 deletion Packs/PAN-OS/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "PAN-OS by Palo Alto Networks",
"description": "Manage Palo Alto Networks Firewall and Panorama. For more information see Panorama documentation.",
"support": "xsoar",
"currentVersion": "1.16.7",
"currentVersion": "1.16.9",
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the bump in the version?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In order to avoid conflicts with #24298 (i think it ready for merge)

"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"email": "",
Expand Down