mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-28 23:19:33 +00:00
278 lines
8 KiB
Python
Executable file
278 lines
8 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
"""
|
|
Interface PDF report creation script using the ntopng Python API
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
import getopt
|
|
import pandas as pd
|
|
from fpdf import FPDF
|
|
import plotly.figure_factory as ff
|
|
import plotly.graph_objects as go
|
|
|
|
sys.path.insert(0, '../')
|
|
|
|
from ntopng.ntopng import Ntopng
|
|
|
|
### NTOPNG API SETUP
|
|
username = "admin"
|
|
password = "admin"
|
|
ntopng_url = "http://localhost:3000"
|
|
iface_id = 0
|
|
auth_token = None
|
|
enable_debug = False
|
|
|
|
actual_ts = int(time.time())
|
|
yesterday = (actual_ts - 86400)
|
|
|
|
##################################
|
|
######### DATA COLLECTOR #########
|
|
##################################
|
|
|
|
try:
|
|
my_ntopng = Ntopng(username, password, auth_token, ntopng_url)
|
|
|
|
if(enable_debug):
|
|
my_ntopng.enable_debug()
|
|
except ValueError as e:
|
|
print(e)
|
|
os._exit(-1)
|
|
|
|
try:
|
|
my_interface = my_ntopng.get_interface(iface_id)
|
|
my_historical = my_ntopng.get_historical_interface(iface_id)
|
|
|
|
except ValueError as e:
|
|
print(e)
|
|
os._exit(-1)
|
|
|
|
def get_alerts_severity():
|
|
"""
|
|
Return a dataframe with alerts and severity
|
|
"""
|
|
|
|
alert_count_severity = my_historical.get_alerts_stats(yesterday, actual_ts)
|
|
alert_severity_df = pd.DataFrame(alert_count_severity[0]["value"])
|
|
alert_severity_df.drop(["key", "title"], axis= 1, inplace=True)
|
|
return alert_severity_df
|
|
|
|
def get_top_client_server():
|
|
"""
|
|
Return a dataframe with top clients and servers seen on the interface specified in the above script init data
|
|
"""
|
|
|
|
top_client_server = my_historical.get_flow_alerts_stats(yesterday, actual_ts)
|
|
top_client_server_df = pd.DataFrame(top_client_server[0]["value"])
|
|
top_client_server_df.drop(["key", "value"], axis= 1, inplace=True)
|
|
return top_client_server_df
|
|
|
|
def get_host_info(ip):
|
|
"""
|
|
Return a dataframe with alerts and severity
|
|
:param ip: ip of the desired host to get data of
|
|
"""
|
|
|
|
my_host = my_interface.get_host(ip)
|
|
|
|
return my_host
|
|
|
|
def get_upload_download():
|
|
"""
|
|
Return a list where => data[0] = uploaded MB, data[1] = downloaded MB for the interface specified in the above script init data
|
|
"""
|
|
|
|
up_down = my_historical.get_interface_timeseries("iface:traffic_rxtx", yesterday, actual_ts)
|
|
data = [(up_down["bytes_sent"].sum()/1000000), (up_down["bytes_rcvd"].sum()/1000000)]
|
|
|
|
return data
|
|
|
|
def get_interface_data():
|
|
"""
|
|
Return a dict with info about the interface specified in the above script init data
|
|
"""
|
|
|
|
host_data = my_interface.get_data()
|
|
|
|
host_info = {"flow_count": host_data["num_flows"], "local_hosts": host_data["num_local_hosts"], "hosts_count": host_data["num_hosts"], "local_hosts_anomalies": host_data["num_local_hosts_anomalies"], "alerted_flows": host_data["alerted_flows"], "num_flows": host_data["num_flows"],
|
|
"flows_warning": host_data["alerted_flows_warning"], "flows_error": host_data["alerted_flows_error"]}
|
|
|
|
return host_info
|
|
|
|
def get_interfaces():
|
|
"""
|
|
Return a df with a list of all the interfaces
|
|
"""
|
|
|
|
interfaces = my_ntopng.get_interfaces_list()
|
|
interfaces_df = pd.DataFrame(interfaces)
|
|
interfaces_df.drop("name", axis=1, inplace=True)
|
|
|
|
return interfaces_df
|
|
|
|
def get_interfaces_count():
|
|
"""
|
|
Return number of interfaces
|
|
"""
|
|
interfaces = my_ntopng.get_interfaces_list()
|
|
return len(interfaces)
|
|
##################################
|
|
############# UTILS ##############
|
|
##################################
|
|
|
|
def delete_file(fname):
|
|
"""
|
|
Deletes the table png from the current path
|
|
:param fname: name of png to delete
|
|
"""
|
|
current_dir = os.getcwd()
|
|
path = current_dir+"/"+fname
|
|
|
|
try:
|
|
os.path.exists(path)
|
|
os.remove(path)
|
|
|
|
except Exception as e:
|
|
print(f"FILE: {path} DOES NOT EXIST...")
|
|
os._exit(-1)
|
|
|
|
def df_to_table_png(df, fname):
|
|
"""
|
|
Return creates a png of the df specified with name
|
|
:param df: dataframe to save to png
|
|
:param fname: name of the file to save
|
|
"""
|
|
fig = ff.create_table(df, colorscale=[[0, "#f3a114"], [.5, "#d9d9d9"], [1, "#ffffff"]])
|
|
fig.update_layout(autosize=False, width=1100, height=350)
|
|
fig.write_image(str(fname), scale=2)
|
|
|
|
def plot_up_down():
|
|
"""
|
|
Plots a png of the timeseries
|
|
"""
|
|
up_down = my_historical.get_interface_timeseries("iface:traffic_rxtx", yesterday, actual_ts)
|
|
up_down.reset_index(inplace=True)
|
|
up_down['ts'] = up_down['index'].apply(lambda x: x.left)
|
|
up_down['ts'] = pd.to_datetime(up_down['ts'], unit='s')
|
|
|
|
layout = dict(plot_bgcolor='rgba(255,255,255, 0.3)')
|
|
fig = go.Figure(layout=layout)
|
|
fig.add_trace(go.Scatter(x=up_down["ts"], y=up_down["bytes_rcvd"],
|
|
mode='lines',
|
|
name='Downloaded bytes',
|
|
line_color='#f3a114'))
|
|
fig.add_trace(go.Scatter(x=up_down["ts"], y=up_down["bytes_sent"],
|
|
mode='lines',
|
|
name='Uploaded bytes',
|
|
line_color='#000000'))
|
|
#fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='black')
|
|
#fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='black')
|
|
|
|
fig.write_image("series.png", width=1280, height=720)
|
|
|
|
##################################
|
|
######## DATA COLLECTION #########
|
|
##################################
|
|
created_files = []
|
|
|
|
interfaces_count = get_interfaces_count()
|
|
data_sent_rcvd = get_upload_download()
|
|
interface_data = get_interface_data()
|
|
|
|
#interfaces table
|
|
#interfaces_df = get_interfaces()
|
|
#interfaces_df_fname = "interfaces_table.png"
|
|
#created_files.append(interfaces_df_fname)
|
|
#df_to_table_png(interfaces_df, interfaces_df_fname)
|
|
|
|
#alerts table
|
|
alerts_df = get_alerts_severity()
|
|
alerts_df.columns = ["Alert Type", "Score", "Alert occurrence %"]
|
|
|
|
alerts_df_fname = "alerts_table.png"
|
|
created_files.append(alerts_df_fname)
|
|
df_to_table_png(alerts_df, alerts_df_fname)
|
|
|
|
#client/server table
|
|
hosts_df = get_top_client_server()
|
|
hosts_df.columns = ["Host occurrence %", "Vlan", "IP", "Host Name"]
|
|
hosts_df = hosts_df[["Host Name", "IP", "Host occurrence %", "Vlan"]]
|
|
hosts_df
|
|
|
|
hosts_df_fname = "hosts_table.png"
|
|
created_files.append(hosts_df_fname)
|
|
df_to_table_png(hosts_df, hosts_df_fname)
|
|
|
|
## UPLOADED/DOWNLOADED IN MB
|
|
uploaded = data_sent_rcvd[0]
|
|
downloaded = data_sent_rcvd[1]
|
|
|
|
## INFO FOR SPECIFIED IFID
|
|
flows = interface_data["num_flows"]
|
|
host_num = interface_data["hosts_count"]
|
|
local_hosts_num = interface_data["local_hosts"]
|
|
flows_errors = interface_data["flows_error"]
|
|
flows_warnings = interface_data["flows_warning"]
|
|
|
|
##################################
|
|
########## PDF CREATION ##########
|
|
##################################
|
|
|
|
MARGIN = 10
|
|
pw = 25 - 2*MARGIN
|
|
ch = 50
|
|
pdf = FPDF()
|
|
pdf.add_page()
|
|
|
|
## LOGO
|
|
pdf.image("img/ntop.png", x=140, y=8, w=68.2, h=17.8)
|
|
|
|
## HOST PC SPECS AND STATS ##
|
|
pdf.set_font("Helvetica", "B", 14)
|
|
pdf.set_text_color(r= 0, g= 0, b = 0)
|
|
pdf.ln(9)
|
|
pdf.cell(w=0, h=10, txt="HOST INFO", ln=1)
|
|
pdf.set_font("Helvetica", "", 11)
|
|
pdf.cell(w=0, h=5, txt=f"Host: {ntopng_url}")
|
|
pdf.ln(5)
|
|
pdf.cell(w=0, h=5, txt=f"Timestamp: {time.strftime('%d-%m-%Y %H:%M:%S', time.localtime(actual_ts))}")
|
|
pdf.ln(5)
|
|
pdf.cell(w=0, h=5, txt=f"# Interfaces: {interfaces_count}")
|
|
pdf.ln(7)
|
|
|
|
## 24hr stats ##
|
|
pdf.set_font("Helvetica", "B", 14)
|
|
pdf.cell(w=0, h=10, txt="24h STATS")
|
|
pdf.ln(5)
|
|
pdf.set_font("Helvetica", "", 11)
|
|
pdf.cell(w=(pw/2), h=(ch/4), txt=f"Flows: {flows}")
|
|
pdf.ln(5)
|
|
pdf.cell(w=(pw/2), h=(ch/4), txt=f"Hosts count: {host_num}")
|
|
pdf.ln(5)
|
|
pdf.cell(w=(pw/2), h=(ch/4), txt=f"Local hosts count: {local_hosts_num}")
|
|
pdf.ln(5)
|
|
pdf.cell(w=(pw/2), h=(ch/4), txt=f"UP/DOWN MB: {uploaded:.3f}/{downloaded:.3f}")
|
|
pdf.ln(5)
|
|
pdf.cell(w=(pw/2), h=(ch/4), txt=f"Flows errors: {flows_errors}")
|
|
pdf.ln(5)
|
|
pdf.cell(w=(pw/2), h=(ch/4), txt=f"Flows warnings: {flows_warnings}")
|
|
pdf.ln(5)
|
|
|
|
# Alerts
|
|
pdf.image("alerts_table.png", x=10, y=75, w=190, h=65)
|
|
## Hosts
|
|
pdf.image("hosts_table.png", x=10, y=135, w=190, h=65)
|
|
# Series plot
|
|
plot_up_down()
|
|
pdf.image("series.png", x=10, y=210, w=190, h=85)
|
|
|
|
created_files.append("report.pdf")
|
|
created_files.append("series.png")
|
|
|
|
pdf.output(f"./report.pdf", "F")
|
|
|
|
|
|
for file in created_files:
|
|
delete_file(file)
|