Trigger’s ACL parser.
This library contains various modules that allow for parsing, manipulation, and management of network access control lists (ACLs). It will parse a complete ACL and return an ACL object that can be easily translated to any supported vendor syntax.
Longest match of all the strings that are keys of ‘d’.
Parse a complete ACL and return an ACL object. This should be the only external interface to the parser.
>>> from trigger.acl import parse
>>> aclobj = parse("access-list 123 permit tcp any host 10.20.30.40 eq 80")
>>> aclobj.terms
[<Term: None>]
Parameters: | input_data – An ACL policy as a string or file-like object. |
---|
Wrap your grammar token in this to call your helper function with a list of each parsed subtag, instead of the raw text. This is useful for performing modifiers.
Parameters: | prod – The parser product. |
---|
An abstract access-list object intended to be created by the parse() function.
Assign names to all unnamed terms.
Output the ACL data in the specified format.
Output the ACL in IOS traditional format.
Parameters: | replace – If set the ACL is preceded by a no access-list line. |
---|
Output the ACL in Brocade-flavored IOS format.
The difference between this and “traditional” IOS are:
- Stripping of comments
- Appending of ip rebind-acl or ip rebind-receive-acl line
Parameters: |
|
---|
Output the ACL in IOS named format.
Parameters: | replace – If set the ACL is preceded by a no access-list line. |
---|
Output the ACL in IOS XR format.
Parameters: | replace – If set the ACL is preceded by a no ipv4 access-list line. |
---|
Output the ACL in JunOS format.
Parameters: |
|
---|
Strips all comments from ACL header and all terms.
Container for inline comments.
Output the Comment to IOS traditional format.
Output the Comment to IOS named format.
Output the Comment to IOS XR format.
Output the Comment to JunOS format.
Container class for Term.match object used for membership tests on access checks.
Convert a list of addresses to IOS-style stupid strings.
Parameters: | addrs – List of IP address objects. |
---|
Convert a list of tuples back to ranges, then to strings.
Parameters: | ports – A list of port tuples, e.g. [(0,65535), (1,2)]. |
---|
Convert a 2-tuple into a hyphenated string, e.g. a range of ports. If not a tuple, tries to treat it as IPs or failing that, casts it to a string.
Parameters: | pair – The 2-tuple to convert. |
---|
Return a string of IOS ACL bodies.
Return a list that can form the from { ... } clause of the term.
Container class for policer policy definitions. This is a dummy class for now, that just passes it through as a string.
Container for Policer objects. Juniper only.
A protocol object used for access membership tests in Term objects. Acts like an integer, but stringify into a name if possible.
A type which stores ordered sets, with efficient handling of ranges. It can also store non-incrementable terms as an sorted set without collapsing into ranges.
This is currently used to just store match conditions (e.g. protocols, ports), but could be fleshed out into a general-purpose class. One thing to think about is how/whether to handle a list of tuples as distinct from a list of ranges. Should we just store them as xrange objects? Should the object appear as discrete elements by default, for example in len(), with the collapsed view as a method, or should we keep it as it is now? All the current uses of this class are in this file and have unit tests, so when we decided what the semantics of the generalized module ought to be, we can make it so without worry.
Return a list with all ranges converted to discrete elements.
IOS extended ACL “remark” lines automatically become comments when converting to other formats of ACL.
Output the Remark to IOS named format.
An individual term from which an ACL is made
Output the term to the specified format
Parameters: | format – The desired output format. |
---|
Output term to IOS traditional format.
Parameters: |
|
---|
Output term to IOS named format.
Output term to IOS XR format.
Convert the term to JunOS format.
Add or replace a modifier, or set the primary action. This method exists for the convenience of parsers.
Container class for Term objects within an ACL object.
Class based on IPy.IP, but with extensions for Trigger.
Currently, only the only extension is the ability to negate a network block. Only used internally within the parser, as it’s not complete (doesn’t interact well with IPy.IP objects). Does not handle IPv6 yet.
This module controls when ACLs get auto-applied to network devices, in addition to what is specified in acls.db.
This is primarily used by AclsDB to populate the implicit ACL-to-device mappings.
No changes should be made to this module. You must specify the path to the autoacl logic inside of settings.py as AUTOACL_FILE. This will be exported as autoacl so that the module path for the autoacl() function will still be trigger.autoacl.autoacl().
This trickery allows us to keep the business-logic for how ACLs are mapped to devices out of the Trigger packaging.
If you do not specify a location for AUTOACL_FILE or the module cannot be loaded, then a default autoacl() function ill be used.
Given a NetDevice object, returns a set of implicit (auto) ACLs. We require a device object so that we don’t have circular dependencies between netdevices and autoacl.
This function MUST return a set() of acl names or you will break the ACL associations. An empty set is fine, but it must be a set!
Parameters: |
|
---|
>>> dev = nd.find('test1-abc')
>>> dev.vendor
<Vendor: Juniper>
>>> autoacl(dev)
set(['juniper-router-protect', 'juniper-router.policer'])
NOTE: If the default function is returned it does nothing with the arguments and always returns an empty set.
Redis-based replacement of the legacy acls.db file. This is used for interfacing with the explicit and automatic ACL-to-device mappings.
>>> from trigger.netdevices import NetDevices
>>> from trigger.acl.db import AclsDB
>>> nd = NetDevices()
>>> dev = nd.find('test1-abc')
>>> a = AclsDB()
>>> a.get_acl_set(dev)
set(['juniper-router.policer', 'juniper-router-protect', 'abc123'])
>>> a.get_acl_set(dev, 'explicit')
set(['abc123'])
>>> a.get_acl_set(dev, 'implicit')
set(['juniper-router.policer', 'juniper-router-protect'])
>>> a.get_acl_dict(dev)
{'all': set(['abc123', 'juniper-router-protect', 'juniper-router.policer']),
'explicit': set(['abc123']),
'implicit': set(['juniper-router-protect', 'juniper-router.policer'])}
Return a sorted list of the names of devices that have at least one of the wanted ACLs, and the ACLs that matched on each. Without ‘exact’, match ACL name by startswith.
To get a list of devices, matching the ACLs specified:
>>> adb.get_matching_acls(['abc123'])
[('fw1-xyz.net.aol.com', ['abc123']), ('test1-abc.net.aol.com', ['abc123'])]
To get a list of ACLS matching the devices specified using an explicit match (default) by setting match_device=True:
>>> adb.get_matching_acls(['test1-abc'], match_device=True)
[]
>>> adb.get_matching_acls(['test1-abc.net.aol.com'], match_device=True)
[('test1-abc.net.aol.com', ['abc123', 'juniper-router-protect',
'juniper-router.policer'])]
To get a list of ACLS matching the devices specified using a partial match. Not how it returns all devices starting with ‘test1-mtc’:
>>> adb.get_matching_acls(['test1-abc'], match_device=True, exact=False)
[('test1-abc.net.aol.com', ['abc123', 'juniper-router-protect',
'juniper-router.policer'])]
Returns a dict keyed by acl names whose containing a set of NetDevices objects to which each acl is applied.
@nd can be your own NetDevices object if one is not supplied already
>>> all_acls = get_all_acls()
>>> all_acls['abc123']
set([<NetDevice: test1-abc.net.aol.com>, <NetDevice: fw1-xyz.net.aol.com>])
Returns a set of acls with an applied count over settings.AUTOLOAD_BULK_THRESH.
Given a NetDevices instance, Adds bulk_acls attribute to NetDevice objects.
Container for ACL operations.
add/remove operations are for explicit associations only.
Add explicit acl to device
>>> dev = nd.find('test1-mtc')
>>> a.add_acl(dev, 'acb123')
'added acl abc123 to test1-mtc.net.aol.com'
Returns a dict of acl mappings for a @device, which is expected to be a NetDevice object.
>>> a.get_acl_dict(dev)
{'all': set(['115j', 'protectRE', 'protectRE.policer', 'test-bluej',
'testgreenj', 'testops_blockmj']),
'explicit': set(['test-bluej', 'testgreenj', 'testops_blockmj']),
'implicit': set(['115j', 'protectRE', 'protectRE.policer'])}
Return an acl set matching @acl_set for a given device. Match can be one of [‘all’, ‘explicit’, ‘implicit’]. Defaults to ‘all’.
>>> a.get_acl_set(dev)
set(['testops_blockmj', 'testgreenj', '115j', 'protectRE',
'protectRE.policer', 'test-bluej'])
>>> a.get_acl_set(dev, 'explicit')
set(['testops_blockmj', 'test-bluej', 'testgreenj'])
>>> a.get_acl_set(dev, 'implicit')
set(['protectRE', 'protectRE.policer', '115j'])
Remove explicit acl from device.
>>> a.remove_acl(dev, 'acb123')
'removed acl abc123 from test1-mtc.net.aol.com'
Parse and manipulate network access control lists.
This library doesn’t completely follow the border of the valid/invalid ACL set, which is determined by multiple vendors and not completely documented by any of them. We could asymptotically approach that with an enormous amount of testing, although it would require a ‘flavor’ flag (vendor, router model, software version) for full support. The realistic goal is to catch all the errors that we see in practice, and to accept all the ACLs that we use in practice, rather than to try to reject every invalid ACL and accept every valid ACL.
>>> from trigger.acl import parse
>>> aclobj = parse("access-list 123 permit tcp any host 10.20.30.40 eq 80")
>>> aclobj.terms
[<Term: None>]
Longest match of all the strings that are keys of ‘d’.
Parse a complete ACL and return an ACL object. This should be the only external interface to the parser.
>>> from trigger.acl import parse
>>> aclobj = parse("access-list 123 permit tcp any host 10.20.30.40 eq 80")
>>> aclobj.terms
[<Term: None>]
Parameters: | input_data – An ACL policy as a string or file-like object. |
---|
Wrap your grammar token in this to call your helper function with a list of each parsed subtag, instead of the raw text. This is useful for performing modifiers.
Parameters: | prod – The parser product. |
---|
An abstract access-list object intended to be created by the parse() function.
Assign names to all unnamed terms.
Output the ACL data in the specified format.
Output the ACL in IOS traditional format.
Parameters: | replace – If set the ACL is preceded by a no access-list line. |
---|
Output the ACL in Brocade-flavored IOS format.
The difference between this and “traditional” IOS are:
- Stripping of comments
- Appending of ip rebind-acl or ip rebind-receive-acl line
Parameters: |
|
---|
Output the ACL in IOS named format.
Parameters: | replace – If set the ACL is preceded by a no access-list line. |
---|
Output the ACL in IOS XR format.
Parameters: | replace – If set the ACL is preceded by a no ipv4 access-list line. |
---|
Output the ACL in JunOS format.
Parameters: |
|
---|
Strips all comments from ACL header and all terms.
Container for inline comments.
Output the Comment to IOS traditional format.
Output the Comment to IOS named format.
Output the Comment to IOS XR format.
Output the Comment to JunOS format.
Container class for Term.match object used for membership tests on access checks.
Convert a list of addresses to IOS-style stupid strings.
Parameters: | addrs – List of IP address objects. |
---|
Convert a list of tuples back to ranges, then to strings.
Parameters: | ports – A list of port tuples, e.g. [(0,65535), (1,2)]. |
---|
Convert a 2-tuple into a hyphenated string, e.g. a range of ports. If not a tuple, tries to treat it as IPs or failing that, casts it to a string.
Parameters: | pair – The 2-tuple to convert. |
---|
Return a string of IOS ACL bodies.
Return a list that can form the from { ... } clause of the term.
Container class for policer policy definitions. This is a dummy class for now, that just passes it through as a string.
Container for Policer objects. Juniper only.
A protocol object used for access membership tests in Term objects. Acts like an integer, but stringify into a name if possible.
A type which stores ordered sets, with efficient handling of ranges. It can also store non-incrementable terms as an sorted set without collapsing into ranges.
This is currently used to just store match conditions (e.g. protocols, ports), but could be fleshed out into a general-purpose class. One thing to think about is how/whether to handle a list of tuples as distinct from a list of ranges. Should we just store them as xrange objects? Should the object appear as discrete elements by default, for example in len(), with the collapsed view as a method, or should we keep it as it is now? All the current uses of this class are in this file and have unit tests, so when we decided what the semantics of the generalized module ought to be, we can make it so without worry.
Return a list with all ranges converted to discrete elements.
IOS extended ACL “remark” lines automatically become comments when converting to other formats of ACL.
Output the Remark to IOS named format.
An individual term from which an ACL is made
Output the term to the specified format
Parameters: | format – The desired output format. |
---|
Output term to IOS traditional format.
Parameters: |
|
---|
Output term to IOS named format.
Output term to IOS XR format.
Convert the term to JunOS format.
Add or replace a modifier, or set the primary action. This method exists for the convenience of parsers.
Container class for Term objects within an ACL object.
Class based on IPy.IP, but with extensions for Trigger.
Currently, only the only extension is the ability to negate a network block. Only used internally within the parser, as it’s not complete (doesn’t interact well with IPy.IP objects). Does not handle IPv6 yet.
Database interface for automated ACL queue. Used primarily by load_acl and acl` commands for manipulating the work queue.
>>> from trigger.acl.queue import Queue
>>> q = Queue()
>>> q.list()
(('dc1-abc.net.aol.com', 'datacenter-protect'), ('dc2-abc.net.aol.com',
'datacenter-protect'))
Interacts with firewalls database to insert/remove items into the queue.
Parameters: | verbose (Boolean) – Toggle verbosity |
---|
Mark a device and its ACLs as complete using current timestamp.
(Integrated queue only.)
Parameters: |
|
---|
Create a task in the specified queue.
Parameters: | queue – Name of the queue whose object you want |
---|
Delete an ACL from the firewall database queue.
Attempts to delete from integrated queue. If ACL test fails or if routers are not specified, the item is deleted from manual queue.
Parameters: |
|
---|
Given a queue name, return its DB model.
Parameters: | queue – Name of the queue whose object you want |
---|
Insert an ACL and associated devices into the ACL load queue.
Attempts to insert into integrated queue. If ACL test fails, then item is inserted into manual queue.
Parameters: |
|
---|
List items in the specified queue, defauls to integrated queue.
Parameters: |
|
---|
Integrated queue only.
Mark an ACL and associated devices as “removed” (loaded=0). Intended for use when performing manual actions on the load queue when troubleshooting or addressing errors with automated loads. This leaves the items in the database but removes them from the active queue.
Parameters: |
|
---|
Print something if verbose instance variable is set.
Parameters: | msg – The string to print |
---|
Various tools for use in scripts or other modules. Heavy lifting from tools that have matured over time have been moved into this module.
Constructs & returns a Term object from constituent parts.
Breaks a new_term up into separate constituent parts so that they can be compared in a check_access test.
Returns a list of terms that should be inserted.
Determine whether access is permitted by a given ACL (list of terms).
Tests a new term against a list of terms. Return True if access in new term is permitted, or False if not.
Optionally displays the terms that apply and what edits are needed.
Parameters: |
|
---|
Interface to generating or modifying access-lists. Intended for use in creating command-line utilities using the ACL API.
Formerly “process –ones”.
Processes work dict and determines tuple of (prefix, site) for each device. Stores tuple as a dict key in prefix_hits. If prefix_hits[(prefix, site)] is greater than max_hits, remove all further matching devices from work dict.
By default if a device has no acls flagged as bulk_acls, it is not removed from the work dict.
You may override max_hits to increase the num. of devices on which to load a bulk acl. You may pass force_bulk=True to treat all loads as bulk loads.
Returns a dict of acls with an applied count over settings.AUTOLOAD_BULK_THRESH
Given an ACL object and a list of ticket numbers return a list of matching comments.
Write a temporary file to disk from an Trigger acl.ACL object & return the filename
Return a unified diff between two files
Save a diff to the ACL worklog
Return a new ACL object with the new_term added in the proper place based on the aclobj. Intended to recursively append to an interim ACL object based on a list of Term objects.
It’s safe to assume that this function is incomplete pending better documentation and examples.
Parameters: |
|
---|
Example:
import copy
# terms_to_be_added is a list of Term objects that is to be added in
# the "right place" into new_acl based on the contents of aclobj
original_acl = parse(open('acl.original'))
new_acl = copy.deepcopy(original_acl) # Dupe the original
for term in terms_to_be_added:
new_acl = generate_new_acl(term, new_acl)
Given a list of Term objects call insert_term_into_acl() to determine what needs to be added in based on the contents of old_file. Returns a new ACL object.