-
Notifications
You must be signed in to change notification settings - Fork 209
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
Add Palo Alto Firewalls support #113
Conversation
Plus the following modifications: * Generic applications (known as services in PAN) and applications sets (layer 4) * PAN application (> layer 4) * Raises errors if policies/services names are too long * uses service_name and protocol in service name instead of port list * Used autopep8 (atom beautify) on paloaltofw.py
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed, please reply here (e.g.
|
aclgen.py
Outdated
@@ -54,6 +54,7 @@ | |||
from lib import speedway | |||
from lib import srxlo | |||
from lib import windows_advfirewall | |||
from lib import paloaltofw |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this to be in alphabetical order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lib/aclgenerator.py
Outdated
@@ -225,6 +225,7 @@ class ACLGenerator(object): | |||
'owner', | |||
'qos', | |||
'routing_instance', | |||
'pan-application' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot a comma?
Also is this strictly necessary? I don't believe it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I wasn't sure of its purpose when I originally added it.
lib/policy.py
Outdated
@@ -1600,6 +1617,7 @@ def __ne__(self, other): | |||
'protocol': 'PROTOCOL', | |||
'protocol-except': 'PROTOCOL_EXCEPT', | |||
'qos': 'QOS', | |||
'pan-application':'PAN_APPLICATION', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we put a space after the :?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lib/policy.py
Outdated
@@ -1612,7 +1630,7 @@ def __ne__(self, other): | |||
'timeout': 'TIMEOUT', | |||
'traffic-type': 'TRAFFIC_TYPE', | |||
'verbatim': 'VERBATIM', | |||
'vpn': 'VPN', | |||
# 'vpn': 'VPN', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this meant to be commented out? I don't see why this should be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed no. This is a workaround specific to our setup, as vpn is a zone name and not a special keyword.
Cf. #62
I removed the comment sign.
lib/policy.py
Outdated
@@ -2080,6 +2099,11 @@ def p_qos_spec(p): | |||
""" qos_spec : QOS ':' ':' STRING """ | |||
p[0] = VarType(VarType.QOS, p[4]) | |||
|
|||
def p_pan_application_spec(p): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two spaces should be separating this def, same thing for under it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lib/policy_simple.py
Outdated
@@ -249,6 +249,8 @@ class ProtocolExcept(Field): | |||
class Qos(Field): | |||
"""A rate-limit-icmp field.""" | |||
|
|||
class PANApplication(Field): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, please use two spaces between these classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lib/paloaltofw.py
Outdated
import aclgenerator | ||
import nacaddr | ||
|
||
import re |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks to be unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, removed.
I signed it! Corporation Mozilla. |
lib/paloaltofw.py
Outdated
|
||
|
||
class PaloAltoFW(aclgenerator.ACLGenerator): | ||
"""PaloAltoFW rendering class. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This docstring should only be one line. Arguments should not be documented here and the description below is kind of redundant. It inherits from the aclgenerator class so it should be obvious it renders a syntax output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated, I think it has been copied from the JuniperSRX docstring, which is very similar.
@@ -0,0 +1,48 @@ | |||
################ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we see an example of pan_application being used inside of here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added, as well as the expected output in the test folder.
Palo alto comes with a wide array of existing "Applications", that's why I made it a simple variable that the user can define.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can someone make custom applications or is there a set list of things? If it is a set list should this have checking to make sure someone is not applying incorrect services?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's also possible to make custom applications.
lib/paloaltofw.py
Outdated
term_dup_check = set() | ||
new_terms = [] | ||
for term in terms: | ||
term.name = self.FixTermLength(term.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big deal but is there a max term length? If so we should probably override it because it is likely different from 62 limit in aclgenerator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand.
The final rule length is limited to 31 chars. I added an exception for that on line 208 (PaloAltoFWTooLongName)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a variable named _TERM_MAX_LENGTH. If there is a max length FixTermLength should be called and _TERM_MAX_LENGTH should be set. This will raise an error if the term name is to long. If there is no limit then FixTermLength is irrelevant. Make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently the final name (limited at 31 chars) also contains the source and destination zone name (eg. internal_2_external-term-name. So only checking the term length is not possible (and ends up being quite short).
In order to save rule length, I'm considering the idea of requiring the terms to be unique (similar to the srx lib for example), and then either:
1/ Trimming the sources zone names to 3 char (eg. int_2_ext-term-name), then the prefix is always a fixed length.
or
2/ Not applying any prefix, and letting the user manually set a prefix (eg, src/dst zones) in the term if the user wants it.
I think I like 2/ better as it lets the user have more freedom.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 gives more freedom but there should be checks to make sure a invalid ACL is not rendered. Please make sure that is not possible via raising an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a check to raise "PaloAltoFWDuplicateTermError" in case a term is duplicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As well as use _TERM_MAX_LENGTH instead of custom check.
lib/paloaltofw.py
Outdated
self.modify_options(terms) | ||
|
||
def modify_options(self, PAFWterm): | ||
# for PAFWterm in terms: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the loop has been moved to line 346 (for term in new_terms:)
I removed the line mentioned here.
lib/paloaltofw.py
Outdated
self.service_map[(ports, protocol)] = {'name': final_service_name} | ||
|
||
|
||
class Rule(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused why this exists, it seems to replace the function of Term. Why was Term not able to be used instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why the original Author went that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we explore why this was chosen and if this could be rolled up into a term? I don't understand why this is being used this way and I don't like having code integrated that no one understands. I will expect a docstring for Rule explaining what it is and why it is used instead of the term object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to need help to figure that one out.
…name is duplicated
rules.append(self.INDENT * 9 + "<action>" + Term.ACTIONS.get( | ||
str(options["action"])) + "</action>") | ||
|
||
if fz == tz == "any": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems weird. There are loops above over the from zone and to zone which is a list. From my bit of testing I don't see that this would ever have more than one from-zone or to-zone per rule in rules. So why are these added as a list? The way the logic is setup fz could theoretically be set to an empty list if someone fed in a modified policy object that had the options set to ['from-zone', '', 'to-zone', ''] this would cause a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ankenyr
Not sure why it's originally set up that way, but it can be related to the fact that PAN allows rules to have several source/destination zones.
Right now line 149
self.options["from_zone"] = [from_zone]
sets it to an array containing only 1 element.
But we could for example imagine it (in the future) being a list from the .pol file header, line 292
self.from_zone = filter_options[1].split(',')
(or something similar).
About the possibility of fz or tz being empty, I believe we can add a check after line 150:
if not from_zone or not to_zone:
raise PaloAltoFWOptionError("Source or destination zone is empty.")
2nd option would be to default both to "any" if they are not set instead of raising an error.
But I think it makes more sens to have the user explicitly define "any" if he wants "any".
CLA signed with my personal email as well. |
CLAs look good, thanks! |
… duplicated + update .pol and filter expected
Commit 48a5f71 default the "service" field to "application-default" if "service" is not set, but "application" is. This is to follow PaloAlto recommendations and improve security. If "any" is used, the "application" filter can in some cases not be respected. Here is PaloAlto suport take on it:
|
This is looking good enough that I think you should start making tests for the PR. |
Great! Tests added! |
lib/policy.py
Outdated
@@ -1026,6 +1040,7 @@ def AddObject(self, obj): | |||
# qos? | |||
elif obj.var_type is VarType.QOS: | |||
self.qos = obj.value | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra space added, please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed!
lib/policy.py
Outdated
@@ -1334,6 +1349,7 @@ class VarType(object): | |||
HOP_LIMIT = 47 | |||
LOG_NAME = 48 | |||
FLEXIBLE_MATCH_RANGE = 49 | |||
PAN_APPLICATION = 50 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change this to 54? I have some internal stuff I will be pushing out soon and it will conflict.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed!
#113 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=147091309
This PR includes the content of the PR #52
Plus the following modifications:
If this gets accepted, we also need to make sure the original author of PR #52 gets the credits as he did the largest part of the work.