tpotce/collector/CollectorWEB/views.py

1057 lines
30 KiB
Python
Raw Normal View History

2024-06-05 07:52:53 +00:00
import json
import numpy as np
from django.contrib.auth.decorators import permission_required
from django.shortcuts import render, redirect
from django.conf import settings
from django.http import JsonResponse, HttpResponse, HttpResponseRedirect
from django.db import connection
import CollectorAPI.models
import CollectorAPI.views as api_views
import CollectorAPI.reports
from .forms import GenerateAdvReport
import csv
from ipwhois import IPWhois
import datetime
UNKNOWN_color = '#aaaaaa'
OTHER_color = '#6272fc'
BG_color = '#fc6265'
TARGET_color = '#fcbc62'
CITY_colors = [
"#ffa6a6",
"#e605ff",
"#ffdda6",
"#05f7ff",
"#f9ffa6",
"#ffa305",
"#acffa6",
"#ffa6f3",
"#a6f9ff",
"#dea6ff",
"#a6beff",
"#ffa6b6",
"#8aff05",
"#1e05ff",
"#ff051e"
]
class Echo:
"""An object that implements just the write method of the file-like
interface.
"""
def write(self, value):
"""Write the value by returning it, instead of storing in a buffer."""
return value
# Create your views here.
def convert_date(date_str):
if len(date_str) == 0 or date_str == "none":
return "none"
day, month, year = date_str.split('.')
if len(day) > 2:
raise Exception('Invalid date')
if len(month) > 2:
raise Exception('Invalid date')
if (len(year)) > 4:
raise Exception('Invalid date')
a = f'{year}-{month}-{day}'
return a
def index(request):
"""
View for /
:param request:
:return:
"""
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
query_servers = 'SELECT * FROM \"CollectorAPI_honeypotserver\" ORDER BY last_input DESC;'
with connection.cursor() as cursor:
cursor.execute(query_servers)
servers = cursor.fetchall()
context = {
'servers': servers,
}
return render(request, 'home.html', context)
def reports(request):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
context = {}
return render(request, 'report.html', context)
@permission_required('CollectorAPI.adv_reports')
def reports_adv(request):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = GenerateAdvReport(request.POST)
if form.is_valid():
from_date = form.cleaned_data['from_date']
to_date = form.cleaned_data['to_date']
affected_honeys = form.cleaned_data['affected_honeys']
attacker_countries = form.cleaned_data['attacker_countries']
output = CollectorAPI.reports.gen_report(from_date, to_date, affected_honeys, attacker_countries)
output = json.loads(output)
print(output)
filename = 'report'
response = HttpResponse(
content_type='text/csv',
headers={'Content-Disposition': 'attachment; filename="' + filename + '.csv"'},
)
writer = csv.writer(response)
for ip in output:
ip = [ip]
writer.writerow(ip)
return response
else:
form = GenerateAdvReport()
if 'r' in request.GET:
r = int(request.GET['r'])
try:
obj = CollectorAPI.models.HoneypotReportsStorage.objects.get(id=r)
except CollectorAPI.models.HoneypotReportsStorage.DoesNotExist:
return JsonResponse({'error': f'No such report'})
output = json.loads(obj.data)
filename = 'report'
response = HttpResponse(
content_type='text/csv',
headers={'Content-Disposition': 'attachment; filename="' + filename + '.csv"'},
)
writer = csv.writer(response)
for ip in output:
ip = [ip]
writer.writerow(ip)
return response
honeys = CollectorAPI.models.HoneyPotServer.objects.all()
honeys_clean = {}
for honey in honeys:
honeys_clean[honey.id] = honey.name
reports = CollectorAPI.models.HoneypotReportsStorage.objects.all().order_by('from_date')
clean_reports = []
for report in reports:
honey_to_servers = []
afected_shit = json.loads(report.affected_honeys)
for afected_shit_sub in afected_shit:
honey_to_servers.append(honeys_clean[int(afected_shit_sub)])
clean_reports.append({
'id': report.id,
'from_date': report.from_date,
'to_date': report.to_date,
'affected_honeys': honey_to_servers,
'countries': json.loads(report.countries)
})
return render(request, 'report_adv.html', {'form': form, 'reports': clean_reports, 'servers': honeys_clean})
def get_report_ips_csv(request):
'''
Function to export reports as CSV
:param request:
:return:
'''
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
days = 0
limit = 0
ISO = 'any'
no_count = True
country = True
city = True
if 'no_count' in request.GET:
no_count = False
country = False
city = False
if 'days' in request.GET:
days = int(request.GET['days'])
if 'limit' in request.GET:
limit = int(request.GET['limit'])
if 'iso' in request.GET:
ISO = request.GET['iso']
ips = api_views.gen_attack_ips(days, limit, ISO, no_count, country, city)
filename = 'attackers_for_days_' + str(days) + '_from_' + ISO
if no_count:
filename = filename + '_with_stats'
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(
content_type='text/csv',
headers={'Content-Disposition': 'attachment; filename="' + filename + '.csv"'},
)
writer = csv.writer(response)
for ip in ips:
if no_count:
try:
obj = IPWhois(ip[0])
res = obj.lookup_whois()
ip_print = ip + (res["nets"][0]['name'],)
except Exception as e:
print(e)
ip_print = ip + (e,)
ip = ip_print
writer.writerow(ip)
return response
def get_report_ips_json(request):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
days = 0
limit = 0
ISO = 'any'
no_count = True
if 'no_count' in request.GET:
no_count = False
if 'days' in request.GET:
days = int(request.GET['days'])
if 'limit' in request.GET:
limit = int(request.GET['limit'])
if 'iso' in request.GET:
ISO = request.GET['iso']
ips = api_views.gen_attack_ips(days, limit, ISO, no_count)
filename = 'attackers_for_days_' + str(days) + '_from_' + ISO
if no_count:
filename = filename + '_with_stats'
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(json.dumps(ips), content_type="application/json")
response['Content-Disposition'] = 'attachment; filename=' + filename + '.json'
return response
def get_report_agregated_per_server_csv(request):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
filter = '24h_all'
if 'filter' in request.GET:
filter = request.GET['filter']
target_targets = ['24h_all', '7d_all', '30d_all', '24h_bg', '7d_bg', '30d_bg']
if filter not in target_targets:
return JsonResponse({'error': f'I see you try to be a hacker!!!'})
data = CollectorAPI.models.HoneypotAgregatePerServer.objects.get(data_id=filter)
servers = CollectorAPI.models.HoneyPotServer.objects.all()
servers_output = []
json_data = json.dumps(data.data)
data_array = json.loads(json_data)
build_top = 0
print(data_array)
for server in servers:
if str(server.id) not in data_array:
continue
# check if we have top row with info
if build_top < 1:
json_int = json.dumps(data_array[str(server.id)]['data'])
data_int = json.loads(json_int)
top_row = ['name', 'ip']
for id, count in data_int.items():
if id == '01_comult':
top_row.append('Total')
else:
top_row.append(id)
build_top = 1
servers_output.append(top_row)
row = [server.name, server.ip]
json_int = json.dumps(data_array[str(server.id)]['data'])
data_int = json.loads(json_int)
for id, count in data_int.items():
row.append(count)
servers_output.append(row)
filename = 'per_server_' + str(filter)
response = HttpResponse(
content_type='text/csv',
headers={'Content-Disposition': 'attachment; filename="' + filename + '.csv"'},
)
writer = csv.writer(response)
for server in servers_output:
writer.writerow(server)
return response
@permission_required('CollectorAPI.graphs')
def graphs(request):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
return render(request, 'graphs.html')
@permission_required('CollectorAPI.graphs')
def attack_graph(request, start_date="none", end_date="none", min_attacks=0, global_ip="none", bg_only=0):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
bg_only = not not bg_only
try:
start_date = convert_date(start_date)
except Exception as e:
return JsonResponse({'error': f'Issue with start_date {e}'})
try:
end_date = convert_date(end_date)
except Exception as e:
return JsonResponse({'error': f'Issue with end_date {e}'})
query = None
if bg_only:
query = """
select
src_ip,
servers.name,
count(*) "value",
city_name
from "CollectorAPI_honeypotinfo" as info
"""
else:
query = """
select
src_ip,
servers.name,
count(*) "value",
"countryISO" = 'BG'
from "CollectorAPI_honeypotinfo" as info"""
query += """
inner join "CollectorAPI_honeypotserver" as servers on info.server_id_id = servers.id
"""
conditions = []
arguments = []
if global_ip != "none":
conditions.append("src_ip = %s")
arguments.append(global_ip)
if start_date != "none":
conditions.append("event_timestamp >= %s")
arguments.append(start_date)
if end_date != "none":
conditions.append("event_timestamp <= %s")
arguments.append(end_date)
if bg_only:
conditions.append('"countryISO" = %s')
arguments.append("BG")
if len(conditions) != 0:
query += """
where
""" + " and ".join(conditions)
if bg_only:
query += """
group by
src_ip,
servers.name,
city_name
"""
else:
query += """
group by
src_ip,
servers.name,
"countryISO" = 'BG'
"""
if min_attacks != 0:
query += " having count('*') > %s"
arguments.append(min_attacks)
query += """
order by value desc
"""
print(query)
with connection.cursor() as cursor:
cursor.execute(query, arguments)
rows = cursor.fetchall()
def loc_name(loc):
if loc is None:
return 'Unknown'
if type(loc) is bool:
if loc:
return "Bulgaria"
else:
return "Foreign"
return loc
links = []
rows = [[r[0] + f' ({loc_name(r[3])})', r[1], r[2], r[3]]
for r in rows]
for r in rows:
links.append({'source': r[0], 'target': r[1], 'value': r[2]})
ips = set()
ip2color = {}
if bg_only:
city2color = {}
available_colors = CITY_colors.copy()
for r in rows:
city = r[3] if r[3] is not None else "Unknown"
source = r[0]
target = r[1]
ips.add(source)
ips.add(target)
if target not in ip2color:
ip2color[target] = {
'color': TARGET_color
}
if source not in ip2color:
if city not in city2color:
if city == "Unknown":
city2color[city] = UNKNOWN_color
if len(available_colors) > 0:
city2color[city] = available_colors.pop()
else:
city2color[city] = BG_color
ip2color[source] = {
'color': city2color[city]
}
location2color = city2color
else:
for r in rows:
loc = r[3] if r[3] is not None else "Unknown"
ips.add(r[1])
ips.add(r[0])
if r[1] not in ip2color:
ip2color[r[1]] = {
'color': TARGET_color
}
if r[0] not in ip2color:
if loc == "Unknown":
ip2color[r[0]] = {
'color': UNKNOWN_color
}
elif r[3]:
ip2color[r[0]] = {
'color': BG_color
}
else:
ip2color[r[0]] = {
'color': OTHER_color
}
location2color = {
'Bulgaria': BG_color,
'Other': OTHER_color
}
vertices = [{'name': v, 'itemStyle': ip2color[v]} for v in ips]
print(ip2color)
return JsonResponse({'vertices': vertices,
'links': links,
'location2color': location2color})
@permission_required('CollectorAPI.graphs')
def attack_trend(request, start_date="none", end_date="none", resolution='day', global_ip="none", bg_only=0):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
try:
start_date = convert_date(start_date)
except Exception as e:
return JsonResponse({'error': f'Issue with start_date {e}'})
try:
end_date = convert_date(end_date)
except Exception as e:
return JsonResponse({'error': f'Issue with end_date {e}'})
if resolution not in ['hour', 'day', 'week']:
return JsonResponse({'error': 'Unknown resolution ' + resolution})
if resolution == 'hour':
time_step = 3600.0
elif resolution == 'day':
time_step = 3600.0*24
elif resolution == 'week':
time_step = 3600.0*24*7
else:
return JsonResponse({'error': 'Unknown resolution ' + resolution})
query = "select count(*) \"value\", date_trunc(%s, event_timestamp) timepoint from \"CollectorAPI_honeypotinfo\""
conditions = []
arguments = [resolution]
if start_date != "none":
conditions.append(" event_timestamp >= %s ")
arguments.append(start_date)
if end_date != "none":
conditions.append(" event_timestamp <= %s ")
arguments.append(end_date)
if global_ip != "none":
conditions.append(" src_ip = %s")
arguments.append(global_ip)
if bg_only:
conditions.append(" \"countryISO\" = 'BG'")
if len(conditions) != 0:
query += " where " + " and ".join(conditions)
query += " group by timepoint order by timepoint asc"
print(query)
with connection.cursor() as cursor:
cursor.execute(query, arguments)
rows = cursor.fetchall()
if len(rows) < 3:
return JsonResponse({'error': f'Insufficient data for regression analysis for start \
{start_date} end {end_date} and resolution {resolution}'})
data = np.zeros((len(rows), 2))
for i, r in enumerate(rows):
data[i, :] = [(r[1] - rows[0][1]).total_seconds()/time_step, r[0]]
n = data.shape[0]
# The growth model is y = a*x + b
# From this the formula for a will be a = \frac{\sum_i (x_i - \mu_x)(y_i - \mu_i)}{\sum_i (x - \mu_x)^2}
# Having a calculated, b = \mu_y - a \mu_x
a = np.sum(np.prod(data - np.mean(data, axis=0)[None], axis=1))/np.sum((data[:, 0] - np.mean(data[:, 0]))**2)
b = np.mean(data[:, 1]) - a*np.mean(data[:, 0])
# Since the parameters are calculated, the confidence interval of the slope should be calculated
# according to \sigma_a = \sqrt{\frac{\sum_i (y_i - a x_i - b)^2}{(n-2)\sum_i (x_i - \mu_x)^2}}
sigma_a = np.sqrt(np.sum((data[:, 1] - (a * data[:, 0] + b))**2) /
((n - 2) * np.sum((data[:, 0] - np.mean(data[:, 0]))**2))
)
return JsonResponse({'a': a, 'b': b,
'data': data.tolist(),
'max_x': np.max(data[:, 0]),
'first_attack': rows[0][1].strftime("%d %b %Y %H:%m:%S %Z"),
'sigma_a': sigma_a})
@permission_required('CollectorAPI.graphs')
def multi_target(request, ip):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
if len(ip) == 0:
return JsonResponse({'error': 'Invalid IP'})
query = """select
min(info.event_timestamp) + (max(info.event_timestamp) - min(info.event_timestamp)) / 2 "x",
count(*) "y",
info.type,
server.name
from
"CollectorAPI_honeypotinfo" as info
inner join "CollectorAPI_honeypotserver" as server
on info.server_id_id = server.id
where
info.src_ip = %s
group by
info.type, server.name, date_trunc('hour', info.event_timestamp)
order by
server.name, info.type, "x" """
with connection.cursor() as cursor:
cursor.execute(query, [ip])
rows = cursor.fetchall()
result = {}
attack_start = None
attack_end = None
max_attacks = None
for row in rows:
if attack_start is None:
attack_start = row[0]
else:
attack_start = min(row[0], attack_start)
if attack_end is None:
attack_end = row[0]
else:
attack_end = max(row[0], attack_end)
if max_attacks is None:
max_attacks = row[1]
else:
max_attacks = max(max_attacks, row[1])
if row[3] not in result:
result[row[3]] = {}
if row[2] not in result[row[3]]:
result[row[3]][row[2]] = []
result[row[3]][row[2]].append([row[0].strftime("%d %b %Y %H:%m:%S %Z"), row[1]])
return JsonResponse({'data': result,
'attack_start': attack_start.strftime("%d %b %Y %H:%m:%S %Z"),
'attack_end': attack_end.strftime("%d %b %Y %H:%m:%S %Z"),
'max_attacks': max_attacks})
@permission_required('CollectorAPI.graphs')
def multi_target_summary(request, ip):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
if len(ip) == 0:
return JsonResponse({'error': 'Invalid IP'})
query = """
select
date_trunc('day', event_timestamp) "day",
server.name "name",
count(*) "value",
info.type
from "CollectorAPI_honeypotinfo" as info
inner join "CollectorAPI_honeypotserver" as server
on info.server_id_id = server.id
where src_ip = %s
group by server.name, day, info.type;
"""
with connection.cursor() as cursor:
cursor.execute(query, [ip])
rows = cursor.fetchall()
max_attacks = None
data = {}
for row in rows:
if max_attacks is None:
max_attacks = row[2]
else:
max_attacks = max(max_attacks, row[2])
for row in rows:
if row[3] not in data:
data[row[3]] = []
data[row[3]].append([row[0].strftime("%d %b %Y"), row[1], float(row[2]) * 100.0 / float(max_attacks)])
return JsonResponse({
'data': data
})
@permission_required('CollectorAPI.tables')
def tables(request):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
return render(request, 'tables.html')
@permission_required('CollectorAPI.tables')
def table_daily(request, date):
psql_date = convert_date(date)
query_targets = """
select "name", "id" from "CollectorAPI_honeypotserver"
"""
query_per_ip = """
select count(*) "attacks", src_ip from "CollectorAPI_honeypotinfo"
where
"countryISO" = 'BG'
and event_timestamp >= %s
and event_timestamp <= (%s::date + interval '1d')
and server_id_id = %s
group by
src_ip
order by
attacks desc
"""
query_bg = """
select count(*) from "CollectorAPI_honeypotinfo"
where
"countryISO" = 'BG'
and event_timestamp >= %s
and event_timestamp <= (%s::date + interval '1d')
and server_id_id = %s
"""
query_all = """
select count(*) from "CollectorAPI_honeypotinfo"
where
event_timestamp >= %s
and event_timestamp <= (%s::date + interval '1d')
and server_id_id = %s
"""
with connection.cursor() as cursor:
cursor.execute(query_targets)
servers = cursor.fetchall()
table_data = {}
for name, s_id in servers:
with connection.cursor() as cursor:
cursor.execute(query_per_ip, [psql_date, psql_date, s_id])
top_ips = cursor.fetchall()
with connection.cursor() as cursor:
cursor.execute(query_bg, [psql_date, psql_date, s_id])
bg_attacks = cursor.fetchall()
with connection.cursor() as cursor:
cursor.execute(query_all, [psql_date, psql_date, s_id])
all_attacks = cursor.fetchall()
if len(top_ips) == 0:
continue
table_data[name] = {
'rest_top_ips': top_ips[1:],
'bg_attacks': bg_attacks[0][0],
'all_attacks': all_attacks[0][0],
'top_ip': top_ips[0][1],
'top_count': top_ips[0][0]
}
context = {'table_data': table_data,
'date': date,
'has_data': len(table_data) != 0}
return render(request, 'table_daily.html', context=context)
@permission_required('CollectorAPI.tables')
def table_simple(request, date):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
def process_rows(rows):
processed = {}
for row in rows:
if row[1] not in processed:
processed[row[1]] = {
'domestic': 0,
'total': 0
}
if row[2]:
processed[row[1]]['domestic'] = row[0]
processed[row[1]]['total'] += row[0]
return processed
psql_date = convert_date(date)
query24h = """
select count(*) "attacks", server.name, info."countryISO" = 'BG' as domestic from "CollectorAPI_honeypotinfo" as info
inner join "CollectorAPI_honeypotserver" as server
on info.server_id_id = server.id
where
event_timestamp <= (%s::date + interval '1d')
and event_timestamp >= %s::date
group by
server.name,
domestic
order by
server.name,
domestic,
attacks desc
"""
query7d = """
select count(*) "attacks", server.name, info."countryISO" = 'BG' as domestic from "CollectorAPI_honeypotinfo" as info
inner join "CollectorAPI_honeypotserver" as server
on info.server_id_id = server.id
where
event_timestamp <= (%s::date + interval '1d')
and event_timestamp >= (%s::date - interval '6d')
group by
server.name,
domestic
order by
server.name,
domestic,
attacks desc
"""
query30d = """
select count(*) "attacks", server.name, info."countryISO" = 'BG' as domestic from "CollectorAPI_honeypotinfo" as info
inner join "CollectorAPI_honeypotserver" as server
on info.server_id_id = server.id
where
event_timestamp <= (%s::date + interval '1d')
and event_timestamp >= (%s::date - interval '29d')
group by
server.name,
domestic
order by
server.name,
domestic,
attacks desc
"""
query24h_date = """
select %s::date, (%s::date + interval '1d');
"""
query7d_date = """
select (%s::date - interval '6d'), (%s::date + interval '1d');
"""
query30d_date = """
select (%s::date - interval '29d'), (%s::date + interval '1d');
"""
with connection.cursor() as cursor:
cursor.execute(query24h, [psql_date, psql_date])
summary24h = process_rows(cursor.fetchall())
with connection.cursor() as cursor:
cursor.execute(query7d, [psql_date, psql_date])
summary7d = process_rows(cursor.fetchall())
with connection.cursor() as cursor:
cursor.execute(query30d, [psql_date, psql_date])
summary30d = process_rows(cursor.fetchall())
with connection.cursor() as cursor:
cursor.execute(query24h_date, [psql_date, psql_date])
rows = cursor.fetchall()
date24h = {
'start': rows[0][0].strftime("%d %b %Y"),
'end': rows[0][1].strftime("%d %b %Y")
}
with connection.cursor() as cursor:
cursor.execute(query7d_date, [psql_date, psql_date])
rows = cursor.fetchall()
date7d = {
'start': rows[0][0].strftime("%d %b %Y"),
'end': rows[0][1].strftime("%d %b %Y")
}
with connection.cursor() as cursor:
cursor.execute(query30d_date, [psql_date, psql_date])
rows = cursor.fetchall()
date30d = {
'start': rows[0][0].strftime("%d %b %Y"),
'end': rows[0][1].strftime("%d %b %Y")
}
total = {
'summary24h': {
'domestic': 0,
'total': 0
},
'summary7d': {
'domestic': 0,
'total': 0
},
'summary30d': {
'domestic': 0,
'total': 0
}
}
all_targets = set(
list(summary24h.keys()) +
list(summary7d.keys()) +
list(summary30d.keys())
)
for k in summary24h:
all_targets.add(k)
for k in summary24h:
total['summary24h']['domestic'] += summary24h[k]['domestic']
total['summary24h']['total'] += summary24h[k]['total']
for k in summary7d:
total['summary7d']['domestic'] += summary7d[k]['domestic']
total['summary7d']['total'] += summary7d[k]['total']
for k in summary30d:
total['summary30d']['domestic'] += summary30d[k]['domestic']
total['summary30d']['total'] += summary30d[k]['total']
context = {'summary24h': summary24h,
'summary7d': summary7d,
'summary30d': summary30d,
'total': total,
'all_targets': list(all_targets),
'date24h': date24h,
'date7d': date7d,
'date30d': date30d}
return render(request, "table_simple.html", context=context)
@permission_required('CollectorAPI.tables')
def table_details(request, start, end, res):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
psql_start = convert_date(start)
psql_end = convert_date(end)
query = """
select
count(*) "attacks",
count(distinct(info.src_ip)) "ips",
info."countryISO" = 'BG' "domestic",
server.name,
date_trunc(%s, info.event_timestamp) "event_date"
from "CollectorAPI_honeypotinfo" as info
inner join "CollectorAPI_honeypotserver" as server
on info.server_id_id = server.id
where
info.event_timestamp >= %s
and info.event_timestamp <= %s
group by
domestic,
server.name,
event_date
"""
with connection.cursor() as cursor:
cursor.execute(query, [res, psql_start, psql_end])
rows = cursor.fetchall()
time_points = set()
targets = set()
data = {}
total_over_time = {}
total_over_targets = {}
total = {
'bg': {
'attacks': 0,
'ips': 0
},
'all': {
'attacks': 0,
'ips': 0
}
}
for row in rows:
time_point = row[4].strftime("%d %b %Y")
server = row[3]
domestic = not not row[2]
ips = row[1]
attacks = row[0]
time_points.add(row[4])
targets.add(server)
if time_point not in data:
data[time_point] = {}
if server not in data[time_point]:
data[time_point][server] = {
'bg': {
'attacks': 0,
'ips': 0
},
'all': {
'attacks': 0,
'ips': 0
}
}
if domestic:
data[time_point][server]['bg']['attacks'] = attacks
data[time_point][server]['bg']['ips'] = ips
data[time_point][server]['all']['attacks'] += attacks
data[time_point][server]['all']['ips'] += ips
if time_point not in total_over_targets:
total_over_targets[time_point] = {
'bg': {
'attacks': 0,
'ips': 0
},
'all': {
'attacks': 0,
'ips': 0
}
}
if domestic:
total_over_targets[time_point]['bg']['attacks'] += attacks
total_over_targets[time_point]['bg']['ips'] += ips
total_over_targets[time_point]['all']['attacks'] += attacks
total_over_targets[time_point]['all']['ips'] += ips
if server not in total_over_time:
total_over_time[server] = {
'bg': {
'attacks': 0,
'ips': 0
},
'all': {
'attacks': 0,
'ips': 0
}
}
if domestic:
total_over_time[server]['bg']['attacks'] += attacks
total_over_time[server]['bg']['ips'] += ips
total_over_time[server]['all']['attacks'] += attacks
total_over_time[server]['all']['ips'] += ips
if domestic:
total['bg']['attacks'] += attacks
total['bg']['ips'] += ips
total['all']['attacks'] += attacks
total['all']['ips'] += ips
context = {
'time_points': [d.strftime("%d %b %Y") for d in sorted(list(time_points))],
'targets': sorted(list(targets)),
'data': data,
'total_over_time': total_over_time,
'total_over_targets': total_over_targets,
'total': total
}
return render(request, "table_details.html", context=context)