Skip to content

pan-os-list-applications #24521

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

Merged
merged 16 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 9 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
88 changes: 68 additions & 20 deletions Packs/PAN-OS/Integrations/Panorama/Panorama.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,20 @@
}

RULE_FILTERS = ('nat-type', 'action')


APPILICATION_FILTERS = ('risk', 'category', 'subcategory', 'technology')
CHARACTERISTICS_LIST=('virus-ident',
'file-type-ident',
'evasive-behavior',
'consume-big-bandwidth',
'used-by-malware',
'able-to-transfer-file',
'has-known-vulnerability',
'tunnel-other-application',
'prone-to-misuse',
'pervasive-use',
'data-ident',
'file-forward',
'is-saas')
class PAN_OS_Not_Found(Exception):
""" PAN-OS Error. """

Expand Down Expand Up @@ -692,13 +704,15 @@ def get_pan_os_major_version() -> int:
return major_version


def build_xpath_filter(rule_name: str = None, filters: dict = None) -> str:
def build_xpath_filter(name_match: str = None, name_contains: str = None, filters: dict = None) -> str:
xpath_prefix = ''
if rule_name:
xpath_prefix = f"@name='{rule_name}'"
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 RULE_FILTERS:
if key in RULE_FILTERS or key in APPILICATION_FILTERS:
if xpath_prefix:
xpath_prefix += 'and'
xpath_prefix += f"({key}='{value}')"
Expand All @@ -707,6 +721,11 @@ def build_xpath_filter(rule_name: str = None, filters: dict = None) -> str:
if xpath_prefix:
xpath_prefix += 'and'
xpath_prefix += f"(tag/member='{tag}')"
if key == 'characteristics':
for characteristic in value:
if xpath_prefix:
xpath_prefix += 'and'
xpath_prefix += f"({characteristic}='yes')"
return xpath_prefix


Expand All @@ -719,7 +738,6 @@ def filter_rules_by_status(disabled: str, rules: list) -> list:

''' FUNCTIONS'''


def panorama_test(fetch_params):
"""
test module
Expand Down Expand Up @@ -3483,7 +3501,7 @@ def panorama_list_rules(xpath: str, name: str = None, filters: dict = None, quer

if query:
params["xpath"] = f'{params["xpath"]}[{query}]'
elif xpath_filter := build_xpath_filter(name, filters):
elif xpath_filter := build_xpath_filter(name, None ,filters):
params["xpath"] = f'{params["xpath"]}[{xpath_filter}]'

result = http_request(
Expand Down Expand Up @@ -4122,41 +4140,69 @@ def prettify_applications_arr(applications_arr: Union[List[dict], dict]):
applications_arr = [applications_arr]
for i in range(len(applications_arr)):
application = applications_arr[i]
application_characteristics_list=[]
for key,value in application.items():
if key in CHARACTERISTICS_LIST and value=='yes':
application_characteristics_list.append(str(key))
pretty_application_arr.append({
'Category': application.get('category'),
'SubCategory': application.get('subcategory'),
'Risk': application.get('risk'),
'Technology': application.get('technology'),
'Name': application.get('@name'),
'Description': application.get('description'),
'Characteristics': application_characteristics_list,
'Id': application.get('@id'),
})
return pretty_application_arr


@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')
if name_match and name_contain:
raise Exception('Please specify name_match or 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 @@ -4166,21 +4212,23 @@ 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)
headers = ['Id', 'Name', 'Risk', 'Category', 'SubCategory', 'Technology', 'Description']
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', 'Characteristics']

return_results({
'Type': entryTypes['note'],
'ContentsFormat': formats['json'],
'Contents': applications_arr,
'ReadableContentsFormat': formats['markdown'],
'HumanReadable': tableToMarkdown('Applications', t=applications_arr_output, headers=headers),
'HumanReadable': tableToMarkdown('Applications', t=applications_arr_output, headers=headers, removeNull=True),
'EntryContext': {
"Panorama.Applications(val.Name == obj.Name)": applications_arr_output
}
Expand Down Expand Up @@ -11707,7 +11755,7 @@ def build_nat_xpath(name: Optional[str], pre_post: str, element: Optional[str] =

if query:
_xpath = f"{_xpath}/rules/entry[{query}]"
elif xpath_filter := build_xpath_filter(name, filters):
elif xpath_filter := build_xpath_filter(name, None ,filters):
_xpath = f"{_xpath}/rules/entry[{xpath_filter}]"

if element:
Expand Down Expand Up @@ -12480,7 +12528,7 @@ def build_pbf_xpath(name, pre_post, element_to_change=None, filters: dict = None

if query:
_xpath = f"{_xpath}/rules/entry[{query}]"
elif xpath_filter := build_xpath_filter(name, filters):
elif xpath_filter := build_xpath_filter(name, None,filters):
_xpath = f"{_xpath}/rules/entry[{xpath_filter}]"

if element_to_change:
Expand Down Expand Up @@ -13539,7 +13587,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
55 changes: 55 additions & 0 deletions Packs/PAN-OS/Integrations/Panorama/Panorama.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5284,9 +5284,64 @@ script:
- description: The device group for which to return applications.
name: device-group
required: false
- description: When specified, the results returned in the list are limited to applications whose names match the specified string.
name: name_match
required: false
isArray: false
- description: When specified, the results returned in the list are limited to applications whose names contain 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 of characteristics. 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:
- contextPath: Panorama.Applications.Characteristics
description: The application characteristics.
type: string
- contextPath: Panorama.Applications.Name
description: The application name.
type: string
Expand Down
8 changes: 4 additions & 4 deletions Packs/PAN-OS/Integrations/Panorama/Panorama_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,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 @@ -6383,8 +6383,8 @@ def test_second_fetch_with_two_incidents_with_different_log_types_and_different_
assert last_id_dict.get('Y_log_type', '') == '000000002'


@pytest.mark.parametrize('name, filters, expected_result', mock_rules.get_mock_rules)
def test_build_xpath_filter(name, filters, expected_result):
@pytest.mark.parametrize('name_match, name_contain,, filters, expected_result', mock_rules.get_mock_rules)
def test_build_xpath_filter(name_match, name_contain, filters, expected_result):
from Panorama import build_xpath_filter
mock_result = build_xpath_filter(name, filters)
mock_result = build_xpath_filter(name_match, name_contain, filters)
assert mock_result == expected_result
30 changes: 20 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,31 @@ 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, the results returned in the list are limited to applications whose names match the specified string. | Optional |
| name_contain | When specified, the results returned in the list are limited to applications whose names contain 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 of characteristics. 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. |
| Panorama.Applications.Characteristics | string | The application characteristics. |


#### Command Example
Expand Down
3 changes: 3 additions & 0 deletions Packs/PAN-OS/Integrations/Panorama/test_data/mock_rules.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
case_with_name = (
'test',
None,
{'tags': ['test', 'tag'], 'disabled': 'yes', 'nat-type': 'ipv4'},
"@name='test'and(tag/member='test')and(tag/member='tag')and(nat-type='ipv4')"
)
case_without_name = (
'',
None,
{'tags': ['test', 'tag'], 'disabled': 'yes', 'nat-type': 'ipv4'},
"(tag/member='test')and(tag/member='tag')and(nat-type='ipv4')"
)
case_empty = (
'',
None,
{},
''
)
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 the following filters in the ***pan-os-list-applications*** command: *characteristics*, *technology*, *sub_category*, *category*, *risk*, *name_contain*, *name_match*.
- Added support for the *limit* argument in the ***pan-os-list-applications*** command.
- Updated the Docker image to: *demisto/pan-os-python:1.0.0.48063*.
Loading