Skip to content

Commit

Permalink
Fixing issue in the Palo Alto generator if there is an address family…
Browse files Browse the repository at this point in the history
… mismatch in ICMP/ICMPv6 rules for a Mixed address family filter

PiperOrigin-RevId: 728888559
  • Loading branch information
Capirca Team committed Feb 20, 2025
1 parent ea0d140 commit 8464aab
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 1 deletion.
14 changes: 14 additions & 0 deletions capirca/lib/paloaltofw.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,9 +586,23 @@ def _TranslatePolicy(self, pol, exp_info):
exclude_address_family.append(4)
elif filter_type == "mixed":
if "ip4-ip4" in flows and "ip6-ip6" not in flows:
if "icmpv6" in term.protocol:
logging.warning(
"WARNING: Term %s in policy %s>%s references ICMPv6,"
"but does not have IPv6 traffic flows, "
"term will not be rendered.", term.name, self.from_zone,
self.to_zone)
continue
exclude_address_family.append(6)
pass
elif "ip6-ip6" in flows and "ip4-ip4" not in flows:
if "icmp" in term.protocol:
logging.warning(
"WARNING: Term %s in policy %s>%s references ICMP protocol, "
"but does not have IPv4 traffic flows, "
"term will not be rendered.", term.name, self.from_zone,
self.to_zone)
continue
exclude_address_family.append(4)
pass
elif "ip4-ip4" in flows and "ip6-ip6" in flows:
Expand Down
87 changes: 86 additions & 1 deletion tests/lib/paloaltofw_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit test for Palo Alto Firewalls acl rendering module."""

from absl.testing import absltest
from unittest import mock

Expand Down Expand Up @@ -1814,5 +1813,91 @@ def testAddrObj(self):
addrs = {elem.text for elem in x}
self.assertEqual({"6000::/3"}, addrs, output)

def testMixedICMPFlow(self):
definitions = naming.Naming()
definitions._ParseLine('NET1 = 10.1.0.0/24', 'networks')
definitions._ParseLine('NET2 = 10.2.0.0/24', 'networks')
definitions._ParseLine('NET3 = 2001:db8:0:aa::/64', 'networks')
definitions._ParseLine(' 2001:db8:0:bb::/64', 'networks')
definitions._ParseLine('NET4 = 4000::/2', 'networks')

POL = """
header {
target:: paloalto from-zone trust to-zone untrust %s
}
term rule-1 {
%s
action:: accept
protocol::icmpv6
}"""

T = """
source-address:: NET1
destination-address:: NET2 NET3
"""
# This checks if the rule is properly dropped due to ICMPv6 being used with
# no IPv6 source address
pol = policy.ParsePolicy(POL % ('mixed', T), definitions)
paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
output = str(paloalto)
x = paloalto.config.findall(PATH_RULES + "/entry[@name='rule-1']/")
self.assertFalse(x, output)

T = """
source-address:: NET3
destination-address:: NET4
"""
pol = policy.ParsePolicy(POL % ('mixed', T), definitions)
paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
output = str(paloalto)
x = paloalto.config.findall(
PATH_RULES + "/entry[@name='rule-1']/application"
)
self.assertIsNotNone(x, output)
x = paloalto.config.findall(
PATH_RULES + "/entry[@name='rule-1']/application/member"
)
apps = {elem.text for elem in x}
self.assertIn('ipv6-icmp', apps)

POL = """
header {
target:: paloalto from-zone trust to-zone untrust %s
}
term rule-1 {
%s
action:: accept
protocol::icmp
}"""

T = """
source-address:: NET1
destination-address:: NET2 NET3
"""

pol = policy.ParsePolicy(POL % ('mixed', T), definitions)
paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
output = str(paloalto)
x = paloalto.config.findall(
PATH_RULES + "/entry[@name='rule-1']/application"
)
self.assertIsNotNone(x, output)
x = paloalto.config.findall(
PATH_RULES + "/entry[@name='rule-1']/application/member"
)
apps = {elem.text for elem in x}
self.assertIn('icmp', apps)
T = """
source-address:: NET3
destination-address:: NET4
"""
# This checks if the rule is properly dropped due to ICMP being used with
# no IPv4 source or destination address
pol = policy.ParsePolicy(POL % ('mixed', T), definitions)
paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
output = str(paloalto)
x = paloalto.config.findall(PATH_RULES + "/entry[@name='rule-1']/")
self.assertFalse(x, output)

if __name__ == '__main__':
absltest.main()

0 comments on commit 8464aab

Please sign in to comment.