From afcbabb7cbdcf6b6067dfe1920cc11c433392f90 Mon Sep 17 00:00:00 2001 From: Gerd Saurer Date: Sat, 28 Dec 2024 17:53:09 +0100 Subject: [PATCH 1/4] Adding json API endpoints for easier integration with other platforms. --- openvpn_monitor/app.py | 63 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/openvpn_monitor/app.py b/openvpn_monitor/app.py index 212b347..4f2a42b 100644 --- a/openvpn_monitor/app.py +++ b/openvpn_monitor/app.py @@ -20,8 +20,9 @@ import os import secrets import sys +import json from datetime import datetime -from flask import Flask, request, render_template +from flask import Flask, request, render_template, jsonify from flask_wtf import CSRFProtect from humanize import naturalsize from pprint import pformat @@ -187,8 +188,66 @@ def handle_root(): port=port, client_id=client_id, ) - return render_template('base.html', vpns=vpns) + return render_template('base.html', vpns=vpns) + + @app.route('/api/status') + def handle_api_vpnStatus(): + vpn_data = VPNDataCollector(loaded_vpns, geoip_db.gi) + vpns = vpn_data.vpns.items() + pretty_vpns = pformat((dict(vpns))) + logging.debug(f'=== begin vpns\n{pretty_vpns}\n=== end vpns') + + jsonVPN = [] + totalVPNs = 0 + totalClients = 0 + totalBytesIn = 0 + totalBytesOut = 0 + for vpnId, vpnInfo in vpns: + jsonVPN.append( {"Id": vpnId, + "Name": vpnInfo["name"], + "Status": vpnInfo["state"]["connected"], + "Uptime": vpnInfo["state"]["up_since"], + "BytesIn": vpnInfo["stats"]["bytesin"], + "BytesOut": vpnInfo["stats"]["bytesout"], + "Clients": vpnInfo["stats"]["nclients"], + }) + totalVPNs += 1 + totalClients += vpnInfo["stats"]["nclients"] + totalBytesIn += vpnInfo["stats"]["bytesin"] + totalBytesOut += vpnInfo["stats"]["bytesout"] + + statusInfo = {"Total": { + "VPNs": totalVPNs, + "Clients": totalClients, + "BytesIn": totalBytesIn, + "BytesOut": totalBytesOut + }, + 'VPNs': jsonVPN} + return jsonify(statusInfo) + + + @app.route('/api/clients') + def handle_api_vpnClients(): + vpn_data = VPNDataCollector(loaded_vpns, geoip_db.gi) + vpns = vpn_data.vpns.items() + pretty_vpns = pformat((dict(vpns))) + logging.debug(f'=== begin vpns\n{pretty_vpns}\n=== end vpns') + connectionsVPN = [] + for vpnId, vpnInfo in vpns: + for ip, sessionInf in vpnInfo["sessions"].items(): + connectionsVPN.append({"LocalIp": ip, + "VPNId": vpnId, + "Username": sessionInf["username"], + "ConnectedSince": sessionInf["connected_since"], + "LastPing": sessionInf["last_ping"], + "BytesIn": sessionInf["bytes_recv"], + "BytesOut": sessionInf["bytes_sent"], + "LastSeen": sessionInf["last_seen"]} + ) + return jsonify(connectionsVPN) + + return app From 6cbcbb38f7d0e22dc345308f653f3868fdc231c8 Mon Sep 17 00:00:00 2001 From: Gerd Saurer Date: Sat, 28 Dec 2024 18:04:36 +0100 Subject: [PATCH 2/4] Added missing RemoteIP to the API --- openvpn_monitor/app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openvpn_monitor/app.py b/openvpn_monitor/app.py index 4f2a42b..baed10a 100644 --- a/openvpn_monitor/app.py +++ b/openvpn_monitor/app.py @@ -236,8 +236,9 @@ def handle_api_vpnClients(): connectionsVPN = [] for vpnId, vpnInfo in vpns: for ip, sessionInf in vpnInfo["sessions"].items(): - connectionsVPN.append({"LocalIp": ip, + connectionsVPN.append({"LocalIP": ip, "VPNId": vpnId, + "RemoteIP": sessionInf["remote_ip"], "Username": sessionInf["username"], "ConnectedSince": sessionInf["connected_since"], "LastPing": sessionInf["last_ping"], From 88302298ba0d5263ae81fbf7ef2884bec3ce7bdf Mon Sep 17 00:00:00 2001 From: Gerd Saurer Date: Sat, 28 Dec 2024 18:11:16 +0100 Subject: [PATCH 3/4] fixing formating issue with the IPAddress in json --- openvpn_monitor/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvpn_monitor/app.py b/openvpn_monitor/app.py index baed10a..4094795 100644 --- a/openvpn_monitor/app.py +++ b/openvpn_monitor/app.py @@ -238,10 +238,10 @@ def handle_api_vpnClients(): for ip, sessionInf in vpnInfo["sessions"].items(): connectionsVPN.append({"LocalIP": ip, "VPNId": vpnId, - "RemoteIP": sessionInf["remote_ip"], + "RemoteIP": format(sessionInf["remote_ip"]), "Username": sessionInf["username"], "ConnectedSince": sessionInf["connected_since"], - "LastPing": sessionInf["last_ping"], + "LastSeen": sessionInf["last_seen"], "BytesIn": sessionInf["bytes_recv"], "BytesOut": sessionInf["bytes_sent"], "LastSeen": sessionInf["last_seen"]} From 228c0a4d23964c51470e6e54e3766811eb6d8145 Mon Sep 17 00:00:00 2001 From: Gerd Saurer Date: Sat, 28 Dec 2024 22:23:39 +0100 Subject: [PATCH 4/4] adding datetime formatting to API --- openvpn_monitor/app.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openvpn_monitor/app.py b/openvpn_monitor/app.py index 4094795..83433c7 100644 --- a/openvpn_monitor/app.py +++ b/openvpn_monitor/app.py @@ -57,6 +57,7 @@ def openvpn_monitor_wsgi(): settings = config.settings loaded_vpns = config.vpns geoip_db = GeoipDBLoader(settings) + datetime_format = settings.get('datetime_format', '%d/%m/%Y %H:%M:%S%z') @app.template_filter() def get_formatted_time_now(datetime_format): @@ -206,7 +207,7 @@ def handle_api_vpnStatus(): jsonVPN.append( {"Id": vpnId, "Name": vpnInfo["name"], "Status": vpnInfo["state"]["connected"], - "Uptime": vpnInfo["state"]["up_since"], + "Uptime": vpnInfo["state"]["up_since"].strftime(datetime_format), "BytesIn": vpnInfo["stats"]["bytesin"], "BytesOut": vpnInfo["stats"]["bytesout"], "Clients": vpnInfo["stats"]["nclients"], @@ -240,11 +241,10 @@ def handle_api_vpnClients(): "VPNId": vpnId, "RemoteIP": format(sessionInf["remote_ip"]), "Username": sessionInf["username"], - "ConnectedSince": sessionInf["connected_since"], - "LastSeen": sessionInf["last_seen"], + "ConnectedSince": sessionInf["connected_since"].strftime(datetime_format), + "LastSeen": sessionInf["last_seen"].strftime(datetime_format), "BytesIn": sessionInf["bytes_recv"], - "BytesOut": sessionInf["bytes_sent"], - "LastSeen": sessionInf["last_seen"]} + "BytesOut": sessionInf["bytes_sent"]} ) return jsonify(connectionsVPN)