def testIOSNonCanonical(self): """Test parsing of IOS match terms in non-output formats.""" x = 'access-list 100 permit tcp any any eq ftp-data' y = 'access-list 100 permit tcp any any eq 20' self.assertEqual(acl.parse(x).output_ios(), [y]) x = 'access-list 100 permit ip any 192.0.2.99 0.0.0.0' y = 'access-list 100 permit ip any host 192.0.2.99' self.assertEqual(acl.parse(x).output_ios(), [y])
def testIOSACL(self): """Test parsing of IOS numbered ACLs.""" text = '\n'.join(['access-list 100 permit ' + x for x in ios_matches]) self.assertEqual('\n'.join(acl.parse(text).output_ios()), text) # Non-canonical forms: x = 'access-list 100 permit icmp any any log echo' y = 'access-list 100 permit icmp any any echo log' a = acl.parse(x) self.assertEqual(a.output_ios(), [y]) self.assertEqual(a.format, 'ios')
def testFirewallReplace(self): """Test JunOS ACL with "firewall { replace:" around it.""" acl.parse(''' firewall { replace: filter blah { term foo { then { accept; } } } }''')
def testJunOSExamples(self): """Test examples from JunOS documentation.""" examples = file(EXAMPLES_FILE).read().expandtabs().split('\n\n') # Skip the last two because they use the unimplemented "except" # feature in address matches. for i in range(0, 14, 2): if examples[i + 1].find('policer'): continue x = examples[i + 1].split('\n') y = acl.parse(examples[i]).output_junos() self.assertEqual(x, y) self.assertEqual(y.format, 'junos') z = acl.parse('\n'.join(y)).output_junos() self.assertEqual(y, z)
def testJunOSExamples(self): """Test examples from JunOS documentation.""" examples = file(EXAMPLES_FILE).read().expandtabs().split('\n\n') # Skip the last two because they use the unimplemented "except" # feature in address matches. for i in range(0, 14, 2): if examples[i+1].find('policer'): continue x = examples[i+1].split('\n') y = acl.parse(examples[i]).output_junos() self.assertEqual(x, y) self.assertEqual(y.format, 'junos') z = acl.parse('\n'.join(y)).output_junos() self.assertEqual(y, z)
def testPolicer(self): '''test policer stuff.''' x = \ '''firewall { replace: policer test { if-exceeding { bandwidth-limit 32000; burst-size-limit 32000; } then { discard; } } policer test2 { if-exceeding { bandwidth-limit 32000; burst-size-limit 32000; } then { discard; } } }''' a = acl.parse(x) self.assertEqual(a.output(replace=True), x.split('\n'))
def testIOSNamedACL(self): """Test parsing of IOS named ACLs.""" x = 'ip access-list extended foo\n' x += '\n'.join([' permit ' + x for x in ios_matches]) a = acl.parse(x) self.assertEqual(a.output_ios_named(), x.split('\n')) self.assertEqual(a.format, 'ios_named')
def _create_packet_dict(self, cmd_out): import warnings with warnings.catch_warnings(record=True): warnings.simplefilter("always") from trigger.acl import parse import netaddr import json import uuid # pd is list of dictionary of packets pd = [] lines = cmd_out.split('\n') for index, line in enumerate(lines): line = to_bytes(line, errors='surrogate_or_strict') pd_it = {} try: p = parse(line) except Exception: continue if p.terms: match = p.terms[0].match for key in match: if key == 'source-address': for m in match["source-address"]: v = netaddr.IPNetwork(str(m)) # Return the host in middle of subnet size_subnet = v.size host_index = int(size_subnet / 2) pd_it["src"] = str(v[host_index]) if key == 'destination-address': for m in match["destination-address"]: v = netaddr.IPNetwork(str(m)) # Return the host in middle of subnet size_subnet = v.size host_index = int(size_subnet / 2) pd_it["dst"] = str(v[host_index]) if key == 'protocol': for m in match['protocol']: pd_it["proto"] = str(m) if key == 'destination-port': for m in match["destination-port"]: pd_it['dst_port'] = str(m) if key == 'source-port': for m in match["source-port"]: pd_it['src_port'] = str(m) action = p.terms[0].action for act in action: pd_it["action"] = act if pd_it is not None: if "dst" not in pd_it: pd_it["dst"] = "any" if "src" not in pd_it: pd_it["src"] = "any" pd_it["service_line_index"] = str(index) pd.append(pd_it) return json.dumps(pd, indent=4)
def testIOSACLNegation(self): """Test handling of "no access-list" command.""" x = [ 'access-list 100 permit udp any any', 'no access-list 100', 'access-list 100 permit tcp any any' ] self.assertEqual(acl.parse('\n'.join(x)).output_ios(), x[-1:])
def testIOSNamedACLRemarks(self): """Test parsing of 'remark' lines in IOS named ACLs.""" x = '''\ ip access-list extended foo permit nos any any remark Need more NOS! permit nos any any''' self.assertEqual(acl.parse(x).output_ios_named(), x.split('\n'))
def testDoubleQuotes(self): '''Test JunOS double-quoted names (regression).''' x = '''\ filter test { term "awkward term name" { then { accept; count "awkward term name"; } } }''' a = acl.parse(x) self.assertEqual(a.terms[0].name, 'awkward term name') self.assertEqual('\n'.join(a.output_junos()), x)
def testTCPFlags(self): """Test tcp-established and is-fragment.""" x = '''\ filter x { term y { from { is-fragment; tcp-established; } then { accept; } } }''' self.assertEqual(x, '\n'.join(acl.parse(x).output_junos()))
def force_parse(line, quiet=False, attempt=0): try: return parse(line) except trigger.exceptions.ParseError as error: attempt += 1 if attempt > 1: if not quiet: print('Could not force parse: "{}"'.format(obj.text)) return None else: new_line = re.sub('access-list\s(\w+)\s(extended\s)*', 'access-list 1 ', line) if not quiet: print('Force parsing: "{}" into "{}"'.format(line, new_line)) return force_parse(new_line, quiet, attempt)
def testRanges(self): '''Test JunOS ICMP and protocol ranges (regression).''' x = ''' filter 115j { term ICMP { from { protocol tcp-17; icmp-type [ echo-reply 10-11 ]; } then { accept; count ICMP; } } }''' a = acl.parse(x)
def testCommentStress(self): #'''Test pathological JunOS comments.''' '''Test pathological JunOS comments. We want this to error in order to pass. NO MULTI-LINE COMMENTS!! ''' x = ''' filter 100 { /* one */ /* two */ term/* */y { from /*{*/ /******/ { protocol tcp; /* */ destination-port 80/**/; /* tcp-established; */ } /* /* /* */ } }''' self.assertRaises(exceptions.ParserSyntaxError, lambda: acl.parse(x))
def testInactiveTerm(self): """Test terms flagged as inactive.""" x = '''\ filter 100 { term t1 { then { reject; } } inactive: term t2 { then { accept; } } term t3 { then { accept; } } }''' y = acl.parse(x) self.assertEqual(y.output_junos(), x.split('\n')) self.assertRaises(exceptions.VendorSupportLacking, y.output_ios)
def testShorthandIPv4(self): """Test incomplete IP blocks like "10/8" (vs. "10.0.0.0/8").""" x = '''filter x { term y { from { address { 10/8; } } } }''' y = acl.parse(x) self.assertEqual(y.terms[0].match['address'][0].strNormal(), '10.0.0.0/8')
def testInterfaceSpecific(self): """Test support of Juniper 'interface-specific statement""" x = '''filter x { interface-specific; term y { then accept; } }''' y = acl.parse(x) self.assertTrue(y.interface_specific) self.assertEqual(y.output_junos()[1], ' interface-specific;')
def testICMPIOSNames(self): """Test stringification of ICMP types and codes into IOS format.""" x = 'access-list 100 permit icmp 172.16.0.0 0.15.255.255 any 8' y = 'access-list 100 permit icmp 172.16.0.0 0.15.255.255 any echo' self.assertEqual(acl.parse(x).output_ios(), [y]) self.assertEqual(acl.parse(y).output_ios(), [y])
def testIOSBadACL(self): """Test handling of a bad ACL.""" text = 'access-list 145 permit tcp any any;\naccess-list 145 deny ip any any' self.assertRaises(exceptions.ParseError, lambda: acl.parse(text))
def testIOSACLNegation(self): """Test handling of "no access-list" command.""" x = ['access-list 100 permit udp any any', 'no access-list 100', 'access-list 100 permit tcp any any'] self.assertEqual(acl.parse('\n'.join(x)).output_ios(), x[-1:])
def testNextTerm(self): '''Test "next term" action (regression).''' x = 'filter f { term t { then { next term; } } }' a = acl.parse(x)
def testModifierWithoutAction(self): """Test modifier without action.""" x = '''filter x { term y { then { count z; } } }''' y = acl.parse(x) self.assertEqual(y.terms[0].action, ('accept',))
def testModifierWithoutAction(self): """Test modifier without action.""" x = '''filter x { term y { then { count z; } } }''' y = acl.parse(x) self.assertEqual(y.terms[0].action, ('accept', ))
def testIOSACLDecoration(self): """Test IOS ACLs with comments, blank lines, and "end".""" x = '\n! comment\n\naccess-list 100 permit udp any any log ! ok\nend\n' y = ['! ok', '! comment', 'access-list 100 permit udp any any log'] a = acl.parse(x) self.assertEqual(a.output_ios(), y)
def testIOSLongComments(self): """Test long comments in IOS ACLs.""" # Regression: naïve comment handling caused this to exceed the # maximum recursion depth. acl.parse('!'*200 + '\naccess-list 100 deny ip any any')
def testIOSLongComments(self): """Test long comments in IOS ACLs.""" # Regression: naïve comment handling caused this to exceed the # maximum recursion depth. acl.parse('!' * 200 + '\naccess-list 100 deny ip any any')
def testParseFile(self): """Make sure we can apply trigger.acl.parse() to file objects.""" a = acl.parse(StringIO('access-list 100 deny ip any any')) self.assertEqual(a.name, '100')
PARSIT = ''' filter fire1 { term 1 { from { source-address { 192.168.5.0/24 except; 192.168.6.0/24; } } then { count reject-pref1-1; log; reject; } } term 2 { then { count reject-pref1-2; log; accept; } } } ''' y = acl.parse(PARSIT) print y.terms[0].match print '\n'.join(acl.parse(PARSIT).output_junos()) # following should fail #print '\n'.join(acl.parse(PARSIT).output_ios())