1

我有代码可以在'line vty'上找到'access-class'的名称

之后,我能够找到 ACL,但随后我想检查 ACL 的每一行以验证“拒绝”和“允许”语句是否具有“日志”关键字。如果没有“log”语句,则打印 OPEN 报告,如果条目上有“log”语句,则打印 NOT A FINDING 报告。

这就是我不知道如何解析 ACL 语句的地方,我是否可以使用 CiscoConfParse 或更标准的 python 来完成这项工作?

#Importing the necessary modules.
import sys
from sys import argv
#Importing the necessary modules. 
from ciscoconfparse import CiscoConfParse
import sys
import argparse

def check_VTY_ACL_NET1637():
## Search for LINE VTY access-list name then check if that ACL has    log keyword
#
    for VTY_ACL in parse.find_children_w_parents('line vty', 'access-class'):
        #print(VTY_ACL[14])
        VTY_ACL = VTY_ACL.lstrip('access-class ')
        #print (VTY_ACL)
        VTY_ACL_2 = VTY_ACL.rstrip(' in')
        #print(VTY_ACL_R)
        #has_ACL_in = VTY_ACL.find_lines(r'access-class')
        #print(has_ACL_in)
        #for IP_ACL_LIST in parse.find_objects_w_child(VTY_ACL_R, 'log'):
        #for IP_ACL_LIST in parse.find_lines(VTY_ACL_R):
        for IP_ACL_LIST in parse.find_parents_w_child(VTY_ACL_2, ''):
            #print(IP_ACL_LIST)
            #IP_ACL_ACE = parse.has_line_with(' log')
            IP_ACL_ACE = parse.find_children_w_parents(IP_ACL_LIST, '')
            #print(IP_ACL_ACE)
            has_log_keyword = parse.has_line_with(r' log')
            #print(has_log_keyword)
            #
            #has_log_keyword = has_log_keyword.split()
            for log in IP_ACL_ACE:
                #print (log)
                #has_not_log_keyword = parse.has_line_with(r'. log')
                #print(has_not_log_keyword)
                keyword_log = 'log'
                keyword_permit = 'permit'
                keyword_deny = 'deny'
                log = log.split()
                print (log)
                if (not keyword_log):
                   print('OPEN LINE VTY')
                else:
                   print("Not a Finding: 'NET-VLAN-023'" )


# Main starting of script
def start():
script, input_file = argv
global parse
parse = CiscoConfParse (input_file)
print("Opening config file: %r\n" % input_file)
check_VTY_ACL_NET1637()

def main():
args = sys.argv[1:]
if len(args) == 1:
    start()
#else:
    #usage()

if __name__ == "__main__":
main()

这是我在 VTY 上与 ACL 一起使用的示例配置文件

Current configuration : 25432 bytes
!
ip access-list extended SSH2-IN
 remark ///\\\///\\\///\\\///\\\///\\\///\\\///
 remark ///\\\***DEC 8 2015***///\\\
 remark SomeSite //VoSIP //
 remark ******************************************
 permit ip 10.227.2.128 0.0.0.63 any
 permit tcp 43.81.133.0 0.0.0.255 any eq 22 log
 deny   ip any any
!
line vty 0 4
 access-class SSH2-IN in
line vty 5 15
access-class SSH2-IN in
!
end
4

2 回答 2

1

我为此写了一个概念证明:

#!/usr/bin/env python

import re
from ciscoconfparse import CiscoConfParse

def main():
    cisco_file = 'cisco_ipsec.txt'
    cisco_cfg = CiscoConfParse(cisco_file)
    vty_acl = cisco_cfg.find_objects(r'access-class')

    # Find the ACL name
    acl_name = ''
    for entry in vty_acl:
        if 'line vty' in entry.parent.text:
            match = re.search(r'access-class (.*) in', entry.text)
            if not acl_name:
                acl_name = match.group(1)
            else:
                new_acl_name = match.group(1)
                if new_acl_name != acl_name:
                    raise ValueError("ACL names do not match")

    if not acl_name:
        raise ValueError("ACL not found under line vty")

    the_acl = r"ip access-list extended {}".format(acl_name)
    acl_object = cisco_cfg.find_objects(the_acl)[0]

    # Parse the ACL lines looking for 'log' keyword    
    log_lines = []
    no_log_lines = []
    for line in acl_object.all_children:
        if 'permit' in line.text or 'deny' in line.text:
            if 'log' in line.text:
                log_lines.append(line.text)
            else:
                no_log_lines.append(line.text)

    print "\nLines with log"
    print '#' * 50
    for line in log_lines:
        print line
    print '#' * 50

    print "\nLines without log"
    print '#' * 50
    for line in no_log_lines:
        print line
    print '#' * 50
    print


if __name__ == "__main__":
    main()

在一般层面上,我首先找到 ACL 名称。然后,我遍历 ACL 的每一行以查找 permit 或 deny,然后是 log 关键字。从这里我创建了两个列表:“log_lines”和“no_log_lines”。最后,我打印这两个屏幕。

仅供参考,在发布上述代码以删除注释代码时会有所帮助。它只会让你正在做的事情变得混乱。

于 2016-06-01T16:19:25.050 回答
1
from ciscoconfparse import CiscoConfParse

input_file = 'some_site.conf'
parse = CiscoConfParse(input_file)

## Build a list of vty ACLs here (and flag if a vty doesn't have one)
vty_acl_names = set([])
for vtyobj in parse.find_objects(r'^line\svty'):

    vty_acl_name = vtyobj.re_match_iter_typed('access-class\s+(\S+)\s+in', 
        result_type=str, default="")

    if not vty_acl_name:
        print "FAIL: '{0}' doesn't have an ACL".format(vtyobj.text)
    else:
        vty_acl_names.add(vty_acl_name)

## Check ACL log compliance here (and ensure the ACL is even in the config)
for vty_acl_name in vty_acl_names:
    try:
        aclobj = parse.find_objects(r'ip\s+access-list\s+extended\s+{0}'.format(vty_acl_name))[0]
    except IndexError:
        print "FAIL: ACL {0} is applied to a vty, but it's missing from the config!".format(vty_acl_name)
    ## NOTE: this only works if you are using extended ACLs on the VTY
    for ace in aclobj.children:

        if 'remark' in ace.text:
            continue
        if 'log' in ace.text:
            print "NOT A FINDING - ACL {0}, ACE: {1}".format(vty_acl_name, ace.text)
        else:
            print "OPEN (no log) - ACL {0}, ACE: {1}".format(vty_acl_name, ace.text)

当我在你的配置上运行它时,我得到这个输出:

(py27_default) mpenning@MPENNING-BRIX C:\Users\mpenning
> python garrybaker.py
FAIL: 'line vty 5 15' doesn't have an ACL
OPEN (no log) - ACL SSH2-IN, ACE:  permit ip 10.227.2.128 0.0.0.63 any
NOT A FINDING - ACL SSH2-IN, ACE:  permit tcp 43.81.133.0 0.0.0.255 any eq 22 log
OPEN (no log) - ACL SSH2-IN, ACE:  deny   ip any any

(py27_default) mpenning@MPENNING-BRIX C:\Users\mpenning
>

我冒昧地添加了您的要求...我标记了没有 ACL 的 vty 行。

现在,您可能会问“为什么它说 'line vty 5 15' 没有 ACL,因为我把它放在了配置中?这是因为我使用re_match_iter_typed()了 ,它只搜索父行的子行......当你输入这样的配置,CiscoConfParse 不会在 5 15 上将访问类与父 vty 行关联,因为访问类行的缩进不超过line vty 5 15

line vty 0 4
 access-class SSH2-IN in
line vty 5 15
access-class SSH2-IN in
!

缩进对 CiscoConfParse 很重要……你必须知道你的输入……如果你不能依赖人们缩进他们的配置,那么使用 Kirk 回答中的方法:-)

于 2016-06-02T08:43:08.833 回答