深信服获取防火墙策略Python脚本
通过API接口,调用防火墙策略,并最终转化为Excel输出
import requests
import json
import os
import warnings
import pandas as pd
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from datetime import datetime
# 禁用 SSL 警告
warnings.simplefilter('ignore', InsecureRequestWarning)
# 统一时间戳生成
timestamp = datetime.now().strftime('%m%d_%H%M')
print(f"当前时间戳: {timestamp}") # 打印时间
# 获取token后,调用appcontrols/policys接口
def get_policys(host, token):
url = f"https://{host}/api/v1/namespaces/@namespace/appcontrols/policys"
# 设置请求头,携带token作为Cookie
headers = {
"Accept": "*/*", # 接受任何类型的响应
"Accept-Encoding": "gzip, deflate, br", # 支持的压缩格式
"Connection": "keep-alive", # 保持连接
"Content-Type": "application/json", # 请求数据格式为JSON
"User-Agent": "PostmanRuntime-ApipostRuntime/1.1.0", # 模拟 Postman 请求
"Cookie": f"token={token}" # 把token放入Cookie中
}
all_items = [] # 用来存储所有页的数据
page = 1
while True:
params = {
"_start": (page - 1) * 100, # 起始位置
"_length": 100, # 每页条数
}
try:
# 发送GET请求,获取策略列表
response = requests.get(url, headers=headers, params=params, verify=False)
if response.status_code == 200:
resp_data = response.json()
if resp_data["code"] == 0:
# 获取当前页的策略数据
items = resp_data.get("data", {}).get("items", [])
all_items.extend(items) # 将当前页的数据添加到all_items中
# 保存当前页的数据到文件
filename = f"{timestamp}_AF_ACL_Page_{page}.json"
with open(filename, 'w', encoding='utf-8') as f:
json.dump(resp_data, f, ensure_ascii=False, indent=4)
print(f"第 {page} 页数据已保存到 '{filename}'")
# 检查是否还有下一页
if len(items) < 100: # 如果当前页的数据量少于100,说明没有更多数据了
break
page += 1 # 继续请求下一页
else:
print(f"获取策略失败,错误信息: {resp_data['message']}") # 打印错误信息
break
else:
print(f"请求失败,状态码: {response.status_code}, 错误信息: {response.text}") # 打印HTTP错误
break
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}") # 捕获请求异常并打印
break
# 将所有数据合并并保存到一个文件
if all_items:
all_data = {"data": {"items": all_items}}
all_filename = f"{timestamp}_AF_ACL_All.json"
with open(all_filename, 'w', encoding='utf-8') as f:
json.dump(all_data, f, ensure_ascii=False, indent=4)
return all_items, all_filename # 返回合并数据和文件名
# 登录函数,获取token
def login(host, username, password):
url = f"https://{host}/api/v1/namespaces/@namespace/login" # 使用@namespace固定命名空间
# 登录所需的用户名和密码
payload = {
"name": username,
"password": password
}
# 构建请求头
headers = {
"Accept": "*/*", # 接受任何类型的响应
"Accept-Encoding": "gzip, deflate, br", # 支持的压缩格式
"Connection": "keep-alive", # 保持连接
"Content-Type": "application/json", # 请求数据格式为JSON
}
try:
# 发送POST请求以获取token
response = requests.post(url, json=payload, headers=headers, verify=False)
if response.status_code == 200:
resp_data = response.json()
if resp_data["code"] == 0:
token = resp_data["data"]["loginResult"]["token"]
print("获取到的token:", token) # 打印获取到的token
return token
else:
print("登录失败,错误信息:", resp_data["message"]) # 打印错误信息
else:
print(f"请求失败,状态码: {response.status_code}, 错误信息: {response.text}") # 打印HTTP错误
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}") # 捕获请求异常并打印
# 获取网络对象列表,支持分页
def get_ipgroups(host, token):
url = f"https://{host}/api/v1/namespaces/@namespace/ipgroups" # 修改为正确的访问路径
# 设置请求头,携带token作为Cookie
headers = {
"Accept": "*/*", # 接受任何类型的响应
"Accept-Encoding": "gzip, deflate, br", # 支持的压缩格式
"Connection": "keep-alive", # 保持连接
"Content-Type": "application/json", # 请求数据格式为JSON
"User-Agent": "PostmanRuntime-ApipostRuntime/1.1.0", # 模拟 Postman 请求
"Cookie": f"token={token}" # 把token放入Cookie中
}
all_ipgroups = [] # 用来存储所有页的数据
page = 1
while True:
params = {
"_start": (page - 1) * 100, # 起始位置
"_length": 100, # 每页条数
}
try:
# 发送GET请求,获取网络对象列表
response = requests.get(url, headers=headers, params=params, verify=False)
if response.status_code == 200:
resp_data = response.json()
if resp_data["code"] == 0:
ipgroups = resp_data.get("data", {}).get("items", [])
if ipgroups:
all_ipgroups.extend(ipgroups) # 将当前页的数据添加到 all_ipgroups 中
# 保存当前页的数据到文件
ipgroups_filename = f"{timestamp}_IPGroups_Page_{page}.json"
with open(ipgroups_filename, 'w', encoding='utf-8') as f:
json.dump(resp_data, f, ensure_ascii=False, indent=4)
print(f"第 {page} 页网络对象数据已保存到 '{ipgroups_filename}'")
else:
print(f"第 {page} 页没有获取到网络对象数据。")
break
# 判断是否有更多页
total_pages = resp_data["data"].get("totalPages", 1)
if page < total_pages:
page += 1 # 继续请求下一页
else:
print("所有网络对象数据已获取完毕。")
break
else:
print(f"获取网络对象失败,错误信息: {resp_data['message']}")
break
else:
print(f"请求失败,状态码: {response.status_code}, 错误信息: {response.text}")
break
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
break
# 如果有数据,将所有数据合并并保存到一个文件
if all_ipgroups:
all_data = {"data": {"items": all_ipgroups}}
all_filename = f"{timestamp}_IPGroups_All.json"
with open(all_filename, 'w', encoding='utf-8') as f:
json.dump(all_data, f, ensure_ascii=False, indent=4)
print(f"所有网络对象数据已保存到 '{all_filename}'")
return all_ipgroups, all_filename
def update_dst_ipgroups_with_domains(all_data, ipgroup_to_info):
"""
根据 IP 组的域名或 IP 范围更新 all_data 中的 dstIpGroups 字段。
"""
try:
# 遍历 all_data 中的每个策略数据,更新 dstIpGroups
for item in all_data.get("data", {}).get("items", []):
if 'dst' in item and 'dstAddrs' in item['dst']:
dst_ipgroups = item['dst']['dstAddrs'].get('dstIpGroups', [])
# 更新 dstIpGroups,拼接域名或 IP 范围
updated_dst_ipgroups = []
for ipgroup in dst_ipgroups:
if ipgroup in ipgroup_to_info:
# 构建没有转义字符的格式,手动拼接
info_str = ",".join([f"\"{domain}\"" for domain in ipgroup_to_info[ipgroup]])
updated_dst_ipgroups.append(f"{ipgroup}[{info_str}]")
else:
updated_dst_ipgroups.append(ipgroup)
# 更新 dstIpGroups 字段
item['dst']['dstAddrs']['dstIpGroups'] = updated_dst_ipgroups
return all_data
except Exception as e:
print(f"处理过程中出错: {e}")
return all_data
def generate_ipgroup_to_info(ipgroups_filename):
"""
读取 IP 组数据文件,并构建 IP 组到域名的映射。
"""
ipgroup_to_info = {}
try:
# 读取 IP 组文件
with open(ipgroups_filename, 'r', encoding='utf-8') as f:
ipgroups_data = json.load(f)
# 构建 IP 组到域名或 IP 范围的映射
for ipgroup in ipgroups_data.get('data', {}).get('items', []):
if ipgroup['businessType'] == "DOMAINS":
ipgroup_to_info[ipgroup['name']] = ipgroup.get('domains', [])
elif ipgroup['businessType'] == "IP":
# 你可以扩展 IP 组到 IP 地址的处理
ipgroup_to_info[ipgroup['name']] = [
f"{ip_range['start']}{' - ' + ip_range['end'] if 'end' in ip_range else ''}"
for ip_range in ipgroup.get('ipRanges', [])
]
except Exception as e:
print(f"读取 IP 组数据时出错: {e}")
return ipgroup_to_info
# 新增导出 Excel 文件功能
def export_to_excel(json_file):
# 读取 JSON 文件
with open(json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
# 提取需要的字段 (你可以根据实际需要调整字段)
items = data['data']['items']
rows = []
for item in items:
row = {
'UUID': item.get('uuid', ''),
'Name': item.get('name', ''),
'Description': item.get('description', ''),
'Group': item.get('group', ''),
'Source Zones': ', '.join(item.get('src', {}).get('srcZones', [])),
'Source IP Groups': ', '.join(item.get('src', {}).get('srcAddrs', {}).get('srcIpGroups', [])),
'Destination Zones': ', '.join(item.get('dst', {}).get('dstZones', [])),
'Destination IP Groups': ', '.join(item.get('dst', {}).get('dstAddrs', {}).get('dstIpGroups', [])),
'Services': ', '.join(item.get('services', [])), # 使用 .get() 防止 KeyError
'Action': item.get('action', ''),
'Schedule': item.get('schedule', ''),
'Log Enable': item.get('advanceOption', {}).get('logEnable', ''),
'Last Hit Time': item.get('lastHitTime', ''),
'Hits': item.get('hits', ''),
}
rows.append(row)
# 转换为 DataFrame
df = pd.DataFrame(rows)
excel_filename = f"AF_Final_{timestamp}.xlsx"
# 导出为 Excel
df.to_excel(excel_filename, index=False, engine='openpyxl')
print(f"数据已导出为 Excel 文件: {excel_filename}")
import os
# 新增模块:清理当前目录中 {timestamp}_ 开头的文件
def clean_files_with_timestamp_prefix(timestamp):
# 获取当前目录路径
current_directory = os.getcwd()
# 遍历目录下的所有文件
files_to_remove = [file for file in os.listdir(current_directory) if file.startswith(f"{timestamp}_")]
if not files_to_remove:
print(f"没有找到以 '{timestamp}_' 开头的文件。")
return
# 删除这些文件
for file in files_to_remove:
file_path = os.path.join(current_directory, file)
try:
os.remove(file_path)
print(f"文件 '{file}' 已删除。")
except Exception as e:
print(f"删除文件 '{file}' 时发生错误: {e}")
# 主程序中的菜单更新
def main():
token = None
all_filename = None # 初始化保存文件名变量
all_data = None # 新增变量保存所有数据
ipgroup_to_info = {} # 动态生成的字典
while True:
print("\n请选择操作:")
print("1. 登录并获取 token")
print("2. 拉取策略列表")
print("3. 批量获取网络对象")
print("4. 导入 IP 字段")
print("5. 导出为 Excel")
print("9. 清理其余") # 新增清理文件选项
print("0. 退出")
choice = input("请输入数字:")
if choice == "1":
host = input("请输入主机地址 (默认 10.0.0.1): ") or "10.0.0.1"
username = input("请输入用户名 (默认 admin): ") or "admin"
password = input("请输入密码 (默认 ******): ") or "admin"
# 登录并获取token
token = login(host, username, password)
elif choice == "2":
if token:
# 调用接口获取策略列表
all_items, all_filename = get_policys(host, token)
print(f"所有策略数据已保存到 '{all_filename}'")
# 载入all_data
with open(all_filename, 'r', encoding='utf-8') as f:
all_data = json.load(f)
else:
print("请先获取token。")
elif choice == "3":
if token:
ipgroups, ipgroups_filename = get_ipgroups(host, token)
if ipgroups:
print(f"所有网络对象数据已保存到 '{ipgroups_filename}'")
# 动态生成ipgroup_to_info字典
ipgroup_to_info = generate_ipgroup_to_info(ipgroups_filename)
print("ipgroup_to_info字典已生成。")
else:
print("请先获取token。")
elif choice == "4":
if all_data and ipgroup_to_info:
# 更新dstIpGroups字段
all_data = update_dst_ipgroups_with_domains(all_data, ipgroup_to_info)
updated_filename = f"{timestamp}_AF-应用控制策略.json"
with open(updated_filename, 'w', encoding='utf-8') as f:
json.dump(all_data, f, ensure_ascii=False, indent=4)
print(f"dstIpGroups字段已更新,结果已保存到 '{updated_filename}'")
else:
print("请先执行(2.拉取策略数据)和(3.批量获取网络对象数据)。")
elif choice == "5":
if all_filename:
# 将 JSON 文件导出为 Excel
export_to_excel(updated_filename)
else:
print("请先执行(2.拉取策略数据)。")
elif choice == "9":
# 执行清理文件操作
clean_files_with_timestamp_prefix(timestamp)
elif choice == "0":
print("退出程序")
break
else:
print("无效输入,请重新选择。")
if __name__ == "__main__":
main()
根据你的设备信息,修改主机地址、用户名、密码,即可执行效果:
请选择操作:
1. 登录并获取 token
2. 拉取策略列表
3. 批量获取网络对象
4. 更新 dstIpGroups 字段
5. 导出为 Excel
0. 退出
请输入数字:1
请输入主机地址 (默认 10.0.0.1):
请输入用户名 (默认 admin):
请输入密码 (默认 ******):
获取到的token: 6KILKDU5GLS1***************JP8V70GPSRNEZK***R2V
请选择操作:
1. 登录并获取 token
2. 拉取策略列表
3. 批量获取网络对象
4. 更新 dstIpGroups 字段
5. 导出为 Excel
0. 退出
请输入数字:2
第 1 页数据已保存到 '1229_1939_data_page_1.json'
第 2 页数据已保存到 '1229_1939_data_page_2.json'
所有策略数据已保存到 '1229_1939_all_data.json'
请选择操作:
1. 登录并获取 token
2. 拉取策略列表
3. 批量获取网络对象
4. 更新 dstIpGroups 字段
5. 导出为 Excel
0. 退出
请输入数字:3
第 1 页网络对象数据已保存到 '1229_1939_ipgroups_page_1.json'
第 2 页网络对象数据已保存到 '1229_1939_ipgroups_page_2.json'
第 3 页网络对象数据已保存到 '1229_1939_ipgroups_page_3.json'
第 4 页网络对象数据已保存到 '1229_1939_ipgroups_page_4.json'
所有网络对象数据已获取完毕。
所有网络对象数据已保存到 '1229_1939_all_ipgroups_data.json'
所有网络对象数据已保存到 '1229_1939_all_ipgroups_data.json'
ipgroup_to_info字典已生成。
请选择操作:
1. 登录并获取 token
2. 拉取策略列表
3. 批量获取网络对象
4. 更新 dstIpGroups 字段
5. 导出为 Excel
0. 退出
请输入数字:4
dstIpGroups字段已更新,结果已保存到 '1229_1939_AF-Final.json'
请选择操作:
1. 登录并获取 token
2. 拉取策略列表
3. 批量获取网络对象
4. 更新 dstIpGroups 字段
5. 导出为 Excel
0. 退出
请输入数字:5
数据已导出为 Excel 文件: AF_Final_1229_1939.xlsx
请选择操作:
1. 登录并获取 token
2. 拉取策略列表
3. 批量获取网络对象
4. 更新 dstIpGroups 字段
5. 导出为 Excel
0. 退出
请输入数字:0
退出程序
进程已结束,退出代码为 0


浙公网安备 33010602011771号