Skip to content

Commit

Permalink
[CIAC-6775] [PAN-OS] Add audit-comment argument (#32790)
Browse files Browse the repository at this point in the history
* new get-audit-comment command

* audit-comment arg && ip-wildcard

* tests

* tests

* docs

* RN

* fix tests and update docker

* fix tests

* bump version

* cr

* cr

* Update Packs/PAN-OS/Integrations/Panorama/Panorama.yml

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>

* Update Packs/PAN-OS/ReleaseNotes/2_1_23.md

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>

* fix

---------

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>
  • Loading branch information
YairGlik and ShirleyDenkberg committed Apr 3, 2024
1 parent a627428 commit 2718196
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 56 deletions.
169 changes: 129 additions & 40 deletions Packs/PAN-OS/Integrations/Panorama/Panorama.py
Expand Up @@ -214,6 +214,12 @@
'file-forward',
'is-saas')

RULE_TYPES_MAP = {
"Security Rule": "security",
"NAT Rule": "nat",
"PBF Rule": "pbf"
}


class PAN_OS_Not_Found(Exception):
""" PAN-OS Error. """
Expand Down Expand Up @@ -688,9 +694,9 @@ def prepare_security_rule_params(api_action: str = None, rulename: str = None, s
raise Exception('Please provide the pre_post argument when configuring '
'a security rule in Panorama instance.')
else:
params['xpath'] = f"{XPATH_SECURITY_RULES}{PRE_POST}/security/rules/entry[@name='{rulename}']"
params['xpath'] = f"{XPATH_RULEBASE}{PRE_POST}/security/rules/entry[@name='{rulename}']"
else:
params['xpath'] = f"{XPATH_SECURITY_RULES}[@name='{rulename}']"
params['xpath'] = f"{XPATH_RULEBASE}[@name='{rulename}']"

return params

Expand Down Expand Up @@ -1542,6 +1548,8 @@ def prettify_addresses_arr(addresses_arr: list) -> List:
pretty_address['IP_Netmask'] = address['ip-netmask']
if 'ip-range' in address:
pretty_address['IP_Range'] = address['ip-range']
if 'ip-wildcard' in address:
pretty_address['IP_Wildcard'] = address['ip-wildcard']
if 'fqdn' in address:
pretty_address['FQDN'] = address['fqdn']
if 'tag' in address and address['tag'] is not None and 'member' in address['tag']:
Expand Down Expand Up @@ -1588,7 +1596,8 @@ def panorama_list_addresses_command(args: dict):
'Contents': addresses_arr,
'ReadableContentsFormat': formats['markdown'],
'HumanReadable': tableToMarkdown('Addresses:', addresses_output,
['Name', 'IP_Netmask', 'IP_Range', 'FQDN', 'Tags'], removeNull=True),
['Name', 'IP_Netmask', 'IP_Range', 'IP_Wildcard', 'FQDN', 'Tags'],
removeNull=True),
'EntryContext': {
"Panorama.Addresses(val.Name == obj.Name)": addresses_output
}
Expand Down Expand Up @@ -3865,6 +3874,10 @@ def panorama_create_rule_command(args: dict):
log_forwarding=log_forwarding, tags=tags, category=categories,
from_=source_zone, to=destination_zone, profile_setting=profile_setting,
where=where, dst=dst)

if args.get('audit_comment'):
params['audit-comment'] = args.get('audit_comment')

result = http_request(
URL,
'POST',
Expand Down Expand Up @@ -4005,19 +4018,30 @@ def panorama_edit_rule_items(rulename: str, element_to_change: str, element_valu


def build_audit_comment_params(
name: str, audit_comment: str, pre_post: str, policy_type='security'
name: str, pre_post: str, audit_comment: str = '', policy_type='security', xml_type='set'
) -> dict:
"""
Builds up the params needed to update the audit comment of a policy rule.
"""
_xpath = f"{XPATH_RULEBASE}{pre_post}/{policy_type}/rules/entry[@name='{name}']"
return {
'type': 'op',
'cmd': f"<set><audit-comment><xpath>{_xpath}</xpath><comment>{audit_comment}</comment></audit-comment></set>",
'cmd': build_audit_comment_cmd(_xpath, audit_comment, xml_type),
'key': API_KEY
}


def build_audit_comment_cmd(xpath, audit_comment, xml_type='set') -> str:
"""
Builds up the needed `cmd` param to get or update the audit comment of a policy rule.
"""
if xml_type == 'set':
return f"<set><audit-comment><xpath>{xpath}</xpath><comment>{audit_comment}</comment></audit-comment></set>"
elif xml_type == 'show':
return f"<show><config><list><audit-comments><xpath>{xpath}</xpath></audit-comments></list></config></show>"
return ""


@logger
def panorama_edit_rule_command(args: dict):
"""
Expand Down Expand Up @@ -4046,7 +4070,7 @@ def panorama_edit_rule_command(args: dict):
new_audit_comment = args.get('element_value') or ''
# to update audit-comment of a security rule, it is required to build a 'cmd' parameter
params = build_audit_comment_params(
rulename, new_audit_comment, pre_post='rulebase' if VSYS else pre_post
rulename, pre_post='rulebase' if VSYS else pre_post, audit_comment=new_audit_comment
)
else:
params = {
Expand Down Expand Up @@ -12327,6 +12351,9 @@ def _set_up_original_packet_objects_body_request():
'key': API_KEY
}

if args.get('audit_comment'):
params['audit-comment'] = args.get('audit_comment')

return http_request(URL, 'POST', params=params)


Expand Down Expand Up @@ -12370,22 +12397,28 @@ def pan_os_edit_nat_rule(
):
xpath = build_nat_xpath(name=rule_name, pre_post='rulebase' if VSYS else pre_post, element=element_to_change)

params = {
'xpath': xpath,
'element': dict_to_xml(build_body_request_to_edit_pan_os_object(
behavior=behavior,
object_name=object_name,
element_value=element_value,
is_listable=is_listable,
xpath=xpath,
should_contain_entries=True,
is_commit_required=False
if element_to_change == 'audit-comment':
# to update audit-comment of a nat rule, it is required to build a 'cmd' parameter
params = build_audit_comment_params(
rule_name, pre_post='rulebase' if VSYS else pre_post, audit_comment=element_value, policy_type='nat'
)
),
'action': 'edit',
'type': 'config',
'key': API_KEY
}
else:
params = {
'xpath': xpath,
'element': dict_to_xml(build_body_request_to_edit_pan_os_object(
behavior=behavior,
object_name=object_name,
element_value=element_value,
is_listable=is_listable,
xpath=xpath,
should_contain_entries=True,
is_commit_required=False
)
),
'action': 'edit',
'type': 'config',
'key': API_KEY
}

return http_request(URL, 'POST', params=params)

Expand Down Expand Up @@ -12451,7 +12484,8 @@ def pan_os_edit_nat_rule_command(args):
'dynamic-destination-translation/distribution', 'distribution', False
),
'destination_translation_port': ('destination-translation/translated-port', 'translated-port', False),
'destination_translation_ip': ('destination-translation/translated-address', 'translated-address', False)
'destination_translation_ip': ('destination-translation/translated-address', 'translated-address', False),
'audit-comment': ('audit-comment', '', False)
}

element_to_change, object_name, is_listable = elements_to_change_mapping_pan_os_paths.get(
Expand Down Expand Up @@ -13038,6 +13072,9 @@ def _setup_general_rule_body_request():
'key': API_KEY
}

if args.get('audit_comment'):
params['audit-comment'] = args.get('audit_comment')

return http_request(URL, 'POST', params=params)


Expand All @@ -13058,23 +13095,29 @@ def pan_os_edit_pbf_rule(
name=rule_name, pre_post='rulebase' if VSYS else pre_post, element_to_change=element_to_change
)

params = {
'xpath': xpath,
'element': dict_to_xml(build_body_request_to_edit_pan_os_object(
behavior=behavior,
object_name=object_name,
element_value=element_value,
is_listable=is_listable,
xpath=xpath,
is_entry=True if object_name == 'nexthop-address-list' else False,
is_empty_tag=True if object_name == 'action' else False
),
contains_xml_chars=True
),
'action': 'edit',
'type': 'config',
'key': API_KEY
}
if element_to_change == 'audit-comment':
# to update audit-comment of a pbf rule, it is required to build a 'cmd' parameter
params = build_audit_comment_params(
rule_name, pre_post='rulebase' if VSYS else pre_post, audit_comment=element_value, policy_type='pbf'
)
else:
params = {
'xpath': xpath,
'element': dict_to_xml(build_body_request_to_edit_pan_os_object(
behavior=behavior,
object_name=object_name,
element_value=element_value,
is_listable=is_listable,
xpath=xpath,
is_entry=True if object_name == 'nexthop-address-list' else False,
is_empty_tag=True if object_name == 'action' else False
),
contains_xml_chars=True
),
'action': 'edit',
'type': 'config',
'key': API_KEY
}

return http_request(URL, 'POST', params=params)

Expand Down Expand Up @@ -13110,7 +13153,8 @@ def pan_os_edit_pbf_rule_command(args):
'description': ('description', 'description', False),
'negate_source': ('negate-source', 'negate-source', False),
'negate_destination': ('negate-destination', 'negate-destination', False),
'disabled': ('disabled', 'disabled', False)
'disabled': ('disabled', 'disabled', False),
'audit-comment': ('audit-comment', '', False)
}

if DEVICE_GROUP and not pre_post: # panorama instances must have the pre_post argument!
Expand Down Expand Up @@ -13660,6 +13704,49 @@ def pan_os_delete_tag_command(args: dict) -> CommandResults:
)


def pan_os_get_audit_comment_command(args: dict) -> CommandResults:
"""
executes the command pan-os-get-audit-comment to get the audit comment for a given policy rule.

Args:
args (dict): The command arguments.

Returns:
CommandResults: The command results with raw response, outputs and readable outputs.
"""
if DEVICE_GROUP and not PRE_POST:
raise DemistoException(f'The pre_post argument must be provided for panorama instance')

rule_name = args.get("rule_name") or ""
rule_type = args.get("rule_type") or ""
params = build_audit_comment_params(
name=rule_name,
pre_post='rulebase' if VSYS else f'{PRE_POST.lower()}-rulebase',
policy_type=RULE_TYPES_MAP[rule_type],
xml_type='show',
)

raw_response = http_request(URL, 'GET', params=params)
comment = (raw_response["response"]["result"] or {}).get("entry", {}).get("comment", "") or ""
outputs = {
"rule_name": rule_name,
"rule_type": rule_type,
"comment": comment
}

return CommandResults(
raw_response=raw_response,
outputs=outputs,
readable_output=tableToMarkdown(
f'Audit Comment for Rule: {rule_name}',
outputs,
headerTransform=string_to_table_header,
),
outputs_prefix='Panorama.AuditComment',
outputs_key_field=['rule_name', 'rule_type']
)


""" Fetch Incidents """


Expand Down Expand Up @@ -14805,6 +14892,8 @@ def main(): # pragma: no cover
return_results(list_device_groups_names())
elif command == 'pan-os-export-tech-support-file':
return_results(export_tsf_command(args))
elif command == 'pan-os-get-audit-comment':
return_results(pan_os_get_audit_comment_command(args))
else:
raise NotImplementedError(f'Command {command} is not implemented.')
except Exception as err:
Expand Down
42 changes: 41 additions & 1 deletion Packs/PAN-OS/Integrations/Panorama/Panorama.yml
Expand Up @@ -5148,6 +5148,8 @@ script:
- bottom
- description: The destination rule relative to the rule that you are moving. This field is only relevant if you specify "before" or "after" in the "where" argument.
name: dst
- description: An audit comment for the rule.
name: audit_comment
description: Creates a policy rule.
execution: true
name: pan-os-create-rule
Expand Down Expand Up @@ -8674,6 +8676,8 @@ script:
predefined:
- forward
- reverse
- description: An audit comment for the rule.
name: audit_comment
description: Creates a new NAT rule in a Panorama/firewall instance.
name: pan-os-create-nat-rule
- arguments:
Expand Down Expand Up @@ -8735,6 +8739,7 @@ script:
- destination_translation_dynamic_ip
- destination_translation_dynamic_distribution_method
- disabled
- audit-comment
- description: The value of the element to change. Can be a list for certain elements.
isArray: true
name: element_value
Expand Down Expand Up @@ -9113,6 +9118,8 @@ script:
- description: The nexthop addresses list for the symmetric return.
isArray: true
name: nexthop_address_list
- description: An audit comment for the rule.
name: audit_comment
description: Creates a new policy-based-forwarding (PBF) rule in a Panorama/firewall instance.
name: pan-os-create-pbf-rule
- arguments:
Expand Down Expand Up @@ -9148,6 +9155,7 @@ script:
- action_forward_discard
- action_forward_no_pbf
- disabled
- audit-comment
- description: The value of the element to change. Can be a list for some of the elements. When element_to_change == 'action_forward_egress_interface', the action of the rule will be changed to 'forward' automatically.
isArray: true
name: element_value
Expand Down Expand Up @@ -9364,7 +9372,39 @@ script:
description: The job ID to use when polling.
description: Exports a tech support file (TSF).
polling: true
dockerimage: demisto/pan-os-python:1.0.0.87401
- arguments:
- description: The rule name to apply.
name: rule_name
required: true
- auto: PREDEFINED
description: The rule type.
name: rule_type
required: true
predefined:
- Security Rule
- NAT Rule
- PBF Rule
- auto: PREDEFINED
description: The pre-rule or post-rule (Panorama instances only).
name: pre_post
predefined:
- Pre
- Post
- description: The device group that the rule is part of.
name: device-group
description: Gets the audit comment of a rule.
name: pan-os-get-audit-comment
outputs:
- contextPath: Panorama.AuditComment.comment
description: The audit comment ot the rule.
type: String
- contextPath: Panorama.AuditComment.rule_name
description: The rule name.
type: String
- contextPath: Panorama.AuditComment.rule_type
description: The rule type.
type: String
dockerimage: demisto/pan-os-python:1.0.0.88899
isfetch: true
runonce: false
script: ''
Expand Down

0 comments on commit 2718196

Please sign in to comment.