Permalink
Browse files

Improve temporary web page with graph and coloration

  • Loading branch information...
root
root committed Jul 30, 2018
1 parent fdf1601 commit 2ed2c588a473b0e2c46523250ee9bf412094b6ed
@@ -3,6 +3,7 @@ venv
config.yml
assets/logs.txt
assets/sqlite.db
assets/sqlite.db-journal
assets/unbound.conf
assets/cache/*.txt
feeds/uppersafe.py
Binary file not shown.
@@ -141,6 +141,7 @@ exemptions:
- "*?.imageshack.us"
- "*?.imgur.com"
- "*?.instagram.com"
- "*?.jsfiddle.net"
- "*?.line.me"
- "*?.linkedin.com"
- "*?.live.com"
@@ -8,7 +8,7 @@
from .. import conf, db, app
from flask import g, session, request, abort, redirect, make_response, render_template
from datetime import datetime
import time, json
import json

@app.route("/api", methods=["GET"])
def controller_api_root():
@@ -18,25 +18,56 @@ def controller_api_root():
def controller_api_auth():
return make_response(json.dumps({"message": "Not implemented yet"}))

@app.route("/api/events", methods=["GET"])
def controller_api_events():
@app.route("/api/events/<string:timeframe>", methods=["GET"])
def controller_api_events(timeframe):
data = []
utcnow = datetime.utcnow()
period = {
"5m": [int(time.time()) - 300, int(time.time())],
"60m": [int(time.time()) - 3600, int(time.time())],
"4h": [int(time.time()) - 14400, int(time.time())],
"24h": [int(time.time()) - 86400, int(time.time())],
"7d": [int(time.time()) - 604800, int(time.time())],
"30d": [int(time.time()) - 2592000, int(time.time())]
"5m": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, utcnow.minute, 0).timestamp()) - 300,
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, utcnow.minute, 0).timestamp()) - 1
],
"15m": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, utcnow.minute, 0).timestamp()) - 900,
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, utcnow.minute, 0).timestamp()) - 1
],
"60m": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, utcnow.minute, 0).timestamp()) - 3600,
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, utcnow.minute, 0).timestamp()) - 1
],
"4h": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, 0, 0).timestamp()) - 14400,
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, 0, 0).timestamp()) - 1
],
"12h": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, 0, 0).timestamp()) - 43200,
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, 0, 0).timestamp()) - 1
],
"24h": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, 0, 0).timestamp()) - 86400,
int(datetime(utcnow.year, utcnow.month, utcnow.day, utcnow.hour, 0, 0).timestamp()) - 1
],
"7d": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, 0, 0, 0).timestamp()) - 604800,
int(datetime(utcnow.year, utcnow.month, utcnow.day, 0, 0, 0).timestamp()) - 1
],
"15d": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, 0, 0, 0).timestamp()) - 1296000,
int(datetime(utcnow.year, utcnow.month, utcnow.day, 0, 0, 0).timestamp()) - 1
],
"30d": [
int(datetime(utcnow.year, utcnow.month, utcnow.day, 0, 0, 0).timestamp()) - 2592000,
int(datetime(utcnow.year, utcnow.month, utcnow.day, 0, 0, 0).timestamp()) - 1
]
}
if "range" in request.values and request.values.get("range") in period:
minimum, maximum = period[request.values.get("range")]
if timeframe in period:
minimum, maximum = period[timeframe]
query = g.db.session.query(g.db.models.events)
query = query.order_by(g.db.models.events.id.desc())
query = query.filter(g.db.models.events.creation >= minimum)
query = query.filter(g.db.models.events.creation <= maximum)
if "only" in request.values and request.values.get("only"):
query = query.filter(g.db.models.events.port.in_(request.values.get("only").split(",")))
if "matchonly" in request.values and request.values.get("matchonly"):
query = query.filter(g.db.models.events.port.in_(request.values.get("matchonly").split(",")))
for row in query.yield_per(g.db.chunk):
data.append({
"source": row.source,
@@ -8,7 +8,7 @@
from .. import conf, db, app
from flask import g, session, request, abort, redirect, make_response, render_template
from datetime import datetime
import time, json
import json

@app.route("/app", methods=["GET"])
def controller_app_root():
@@ -20,4 +20,4 @@ def controller_app_auth():

@app.route("/app/dashboard", methods=["GET", "POST"])
def controller_app_dashboard():
return render_template("default.html")
return render_template("dashboard.html")
@@ -8,7 +8,7 @@
from .. import conf, db, app
from flask import g, session, request, abort, redirect, make_response, render_template
from datetime import datetime
import time, json
import json

@app.before_request
def handler_before_request():
@@ -0,0 +1,250 @@
<!DOCTYPE html>
<html itemscope itemtype="http://schema.org/WebPage" lang="en-US">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"/>
<meta name="description" content="UPPERSAFE Open Source Firewall"/>
<meta name="keywords" content=""/>
<meta name="author" content="Nicolas THIBAUT"/>
<title>OSFW</title>
<link rel="canonical" href=""/>
<link rel="icon" href="/static/images/favicon.ico"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/css/bootstrap.min.css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<style type="text/css">
.main {
margin: 56px 0 0 0;
}
.page {
padding: 15px 15px 15px 15px;
}
.sidebar {
position: fixed;
overflow: scroll;
height: calc(100vh - 56px);
padding: 15px 15px 15px 15px;
background: #EEEEEE;
}
.template {
display: none;
}
</style>
</head>
<body>
<nav class="navbar navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">OSFW - Dashboard</a>
<a class="btn btn-dark" href="#"><span class="fa fa-power-off"></span></a>
</nav>
<div class="main container-fluid">
<div class="row">
<div class="col-2 sidebar">
<form>
<div class="form-group">
<label for="">Timeframe</label>
<select class="form-control" name="timeframe">
<option value="5m">Last 5 minutes</option>
<option value="15m" selected="selected">Last 15 minutes</option>
<option value="60m">Last 60 minutes</option>
<option value="4h">Last 4 hours</option>
<option value="12h">Last 12 hours</option>
<option value="24h">Last 24 hours</option>
<option value="7d">Last 7 days</option>
<option value="15d">Last 15 days</option>
<option value="30d">Last 30 days</option>
</select>
</div>
<div class="form-group">
<label for="">Port filters</label>
<input class="form-control" type="text" name="matchonly"/>
</div>
<div class="form-group">
<button class="btn btn-block btn-outline-primary refresh" type="submit">Update</button>
</div>
</form>
</div>
<div class="col-10 ml-auto page">
<div class="sheet">
<canvas class="chart"></canvas>
</div>
<table class="table table-sm table-hover">
<thead>
<tr>
<th>Datetime UTC</th>
<th>Source</th>
<th>Destination</th>
<th class="text-right">Port</th>
</tr>
</thead>
<tbody>
<tr class="template">
<td class="data datetime"><code class="text-primary"></code></td>
<td class="data source"><code class="text-dark"></code></td>
<td class="data destination"><code class="text-dark"></code></td>
<td class="data port text-right"><span class="badge badge-secondary"></span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
$(function () {
var graph = null;
var colorhash = function (nbr) {
var r = Math.max((nbr >> 8) & 0xFF, 1) * Math.max(nbr & 0xFF, 1) * 16 % 150 + 50;
var g = r % 100 * 32 % 150 + 50;
var b = g % 100 * 64 % 150 + 50;
return ("rgba(" + r + ", " + g + ", " + b + ", 1.00)");
}
var refresh = function (event) {
var that = this;
var btntext = $(that).text();
var btnicon = $("<i></i>").attr("class", "fa fa-refresh fa-spin");
var timeframe = $("[name=timeframe]").val();
var matchonly = $("[name=matchonly]").val();
$(that).html(btnicon);
$.ajax({
"url": "/api/events/" + timeframe + "?matchonly=" + matchonly,
"method": "GET",
"success": function (data) {
var json = JSON.parse(data);
var datetime = moment.utc();
var template = $(".template");
var chartctx = $(".chart").get(0).getContext("2d");
var size = parseInt(timeframe);
var unit = timeframe.slice(-1);
var output = {};
while (size != 0) {
datetime.subtract(1, {"m": "minutes", "h": "hours", "d": "days"}[unit]);
output[datetime.format({"m": "YYYY-MM-DD HH:mm:00", "h": "YYYY-MM-DD HH:00:00", "d": "YYYY-MM-DD 00:00:00"}[unit])] = 0;
size = size - 1;
}
template.parent().find(".item").remove();
json.forEach(function (element, index) {
var item = template.clone().attr("class", "item");
output[moment.utc(element.datetime).format({"m": "YYYY-MM-DD HH:mm:00", "h": "YYYY-MM-DD HH:00:00", "d": "YYYY-MM-DD 00:00:00"}[unit])]++;
item.find(".data.datetime").children().text(element.datetime);
item.find(".data.source").children().text(element.source);
item.find(".data.destination").children().text(element.destination);
item.find(".data.port").children().text(element.port).css({"background-color": colorhash(element.port)});
template.parent().append(item);
});
if (graph) {
graph.destroy();
}
graph = new Chart.Line(chartctx, {
"data": {
"labels": Object.keys(output).reverse().map(function (x) {return (moment.utc(x).format({"m": "HH:mm", "h": "HH:mm", "d": "MM/DD"}[unit]));}),
"datasets": [
{
"label": "Events",
"lineTension": 0,
"borderWidth": 2,
"pointBorderWidth": 2,
"pointRadius": 4,
"pointHitRadius": 4,
"pointBorderWidth": 2,
"backgroundColor": "rgba(32, 128, 192, 0.25)",
"pointBackgroundColor": "rgba(32, 128, 192, 1.00)",
"pointHoverBackgroundColor": "rgba(255, 255, 255, 1.00)",
"borderColor": "rgba(32, 128, 192, 1.00)",
"pointBorderColor": "rgba(255, 255, 255, 1.00)",
"pointHoverBorderColor": "rgba(32, 128, 192, 1.00)",
"data": Object.values(output).reverse()
}
]
},
"options": {
"legend": {
"display": false
},
"layout": {
"padding": {
"top": 40,
"right": 40,
"bottom": 0,
"left": 0
}
},
"hover": {
"mode": "index",
"intersect": false,
"animationDuration": 0
},
"tooltips": {
"mode": "index",
"intersect": false,
"caretSize": 8,
"xPadding": 8,
"yPadding": 8,
"bodySpacing": 8,
"position": "nearest",
"backgroundColor": "#000000"
},
"scales": {
"xAxes": [
{
"ticks": {
"display": true,
"fontColor": "#000000",
"beginAtZero": false
},
"gridLines": {
"display": true,
"color": "#EEEEEE",
"zeroLineColor": "#EEEEEE"
},
"scaleLabel": {
"display": true,
"fontColor": "#AAAAAA",
"labelString": "Timeframe"
}
}
],
"yAxes": [
{
"ticks": {
"display": true,
"fontColor": "#000000",
"beginAtZero": true
},
"gridLines": {
"display": true,
"color": "#EEEEEE",
"zeroLineColor": "#EEEEEE"
},
"scaleLabel": {
"display": true,
"fontColor": "#AAAAAA",
"labelString": "Number of events"
}
}
]
}
}
});
$(that).text(btntext);
},
"error": function () {
$(that).text(btntext);
}
});
event.preventDefault();
}
$(".refresh").on("click", refresh).click();
});
</script>
</body>
</html>
Oops, something went wrong.

0 comments on commit 2ed2c58

Please sign in to comment.