最近两周在做思科交换机IOS 12/15的安全加固,加起来一共120台左右,同样是计划使用Prime或者Python脚本批量部署。也想过用Ansible试一把,限制于没有现成的环境,其他team生产环境涉及重要业务太多,也就没有尝试,接下来也会在自己的机器上建立个虚机,自己简单的玩一下,后期更新吧。
部署的思路如下:
1、整理需要部署的条目
2、转换成对应的命令行命令
3、整理需要部署的设备列表
4、测试
5、根据测试结果进行更改,部署所有设备
经过简单比较,还是选择了自己写Python脚本,通过脚本执行。虽然Prime也有CLI的命令模板,可以像脚本一样把一堆的CLI命令推给指定设备或设备组,而且也是采用SSH到设备上执行的方式。相比于Python脚本的缺点:不能输出每台设备每一条命令的执行反馈,只有一个总的设备是否执行完成的结果,不知道没有成功的设备是执行了部分命令还是根本就没有执行;不能进行条件判断,根据条件判断是否执行某些命令(很重要),而Python脚本的话就可以按照自己的思路根据执行反馈来判断是否进行某些命令的执行。
执行的脚本也和之前WLC一样,SSH设备列表,分别执行需要执行的命令。设备列表和命令分别放在文件里,Python循环读取。
强调一下,测试很重要,包括命令的可执行性,以及命令的执行结果是否符合预期。
测试时发现的小Trick, 差点把自己关在SSH门外。部署的项目里面有两条要求在Line VTY下面添加可以SSH设备的ACL。使用标准ACL允许一堆IP,然后vty下面调用就行了。结果发现ACL有命中允许策略,但是SSH无法登录。原因是部分设备管理口划分了单独的VRF vty接口下的ACL要加参数vrf-also,这样从管理vrf过来的流量就也可以通过了。
在VTY ACL添加的时候首先判断设备是否存在这个ACL,如果存在的话就在VTY下添加‘access-class VTY_ACL in vrf-also’,如果希望做的更细致一点的话还可以判断ACL的条目是否存在希望的IP.
源码需添加注释,后期更新链接。
添加ACL后再次登录设备,如果成功表示没有问题,保存配置即可。
源码:
import time
import paramiko
#全局变量,用于存放需要部署到SW的命令
commands = []
#用于登录设备参数
port =22
timeout =30
user ="username"
password ="password"
def Deploy_Commands(device_ip):
# 连接ssh
sshClient = paramiko.SSHClient()
sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#添加异常处理,如SSH时产生异常,直接打印异常
try:
#ssh设备
sshClient.connect(hostname=device_ip, port=port, username=user, password=password)
shell = sshClient.invoke_shell()
#执行文件中的命令
for iin commands:
shell.sendall(i)
#防止命令输入过快产生错误,每输入一条命令后暂停0.1秒
time.sleep(0.1)
#输出命令反馈
data = shell.recv(2048).decode()
print(data, end="\n")
#命令执行完毕后关闭ssh连接
sshClient.close()
except Exception as e:
print(e)
def Check_ACL(device_ip):
# 连接ssh
sshClient = paramiko.SSHClient()
sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
sshClient.connect(hostname=device_ip, port=port, username=user, password=password)
shell = sshClient.invoke_shell()
#查看ACL是否存在
shell.sendall('show ip access-lists | include VTY_ACL\n')
#由于设备性能原因以及网络延迟,需要等待返回信息,设置等待时间3秒
time.sleep(3)
data = shell.recv(2048).decode()
print(data, end="\n")
ACL_LINE ='Standard IP access list VTY_ACL'
#输出反馈如果包含字符串'Standard IP access list VTY_ACL'就添加vty acl
if ACL_LINEin data:
print('已经添加了ACL')
shell.sendall('conf t')
time.sleep(0.1)
shell.sendall('line vty 0 15')
time.sleep(0.1)
shell.sendall('access-class VTY_ACL in vrf-also')
time.sleep(0.1)
data = shell.recv(2048).decode()
print(data, end="\n")
sshClient.close()
else:
print('没有ACL')
except Exception as e:
print(e)
def SSH_WR(device_ip):
# 连接ssh
sshClient = paramiko.SSHClient()
sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
sshClient.connect(hostname=device_ip, port=port, username=user, password=password)
shell = sshClient.invoke_shell()
shell.sendall('wr\n')
#存盘时间较长设置时间为10秒
time.sleep(10)
data = shell.recv(2048).decode()
print(data, end="\n")
print('成功保存配置')
except Exception as e:
print(e)
if __name__ =='__main__':
#从文件读取需要部署的命令到全局变量
with open("D:\\python\\pythonlist\\Cisco_IOS12_15_Command.txt")as WLC_command:
for linesin WLC_command.readlines():
command = lines.split('\n')[0]+'\n'
commands.append(command)
#打印一下要执行的命令
print('要执行的命令:',commands)
#从文件读取设备IP列表,逐个进行添加
with open("D:\\python\\pythonlist\\Cisco_IOS12_15_IP_List.txt")as WLC_ip:
for linesin WLC_ip.readlines():
#每一行根据空格将数据分割到List里面
y = lines.split(' ')
device_ip = y[0]
device_name = y[1]
#每一行末尾会有回车符,将回车符去掉
device_module = y[2].split('\n')[0]
#打印将要开始部署的设备信息:IP 设备名 设备型号
print(device_ip,device_name,device_module)
#执行文件中的命令
Deploy_Commands(device_ip)
#确定执行成功设备配置里面存在ACL VTY_ACL再把line vty的ACL添加上
Check_ACL(device_ip)
#加上ACL后再次SSH上去保存配置,如果不能登录可以通过重启设备恢复
SSH_WR(device_ip)