From c5dfe8b773346e044f7f9c0e4a7bbcae2dc39543 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 3 Feb 2024 22:06:36 +0200 Subject: [PATCH] luci-app-cloudflared: add Tunnels status page The page allows to see if the tunnel has connections. This can be used for a basic troubleshooting without opening the Cloudflare dashboard. Signed-off-by: Sergey Ponomarev (cherry picked from commit b8a4328fcfa77621258d210dffc091353fcb1989) --- .../resources/view/cloudflared/tunnels.js | 86 +++++++++++++++++++ .../po/templates/cloudflared.pot | 27 +++++- .../luci/menu.d/luci-app-cloudflared.json | 10 ++- .../rpcd/acl.d/luci-app-cloudflared.json | 5 +- 4 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js diff --git a/applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js b/applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js new file mode 100644 index 0000000000..28acf4452f --- /dev/null +++ b/applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js @@ -0,0 +1,86 @@ +/* This is free software, licensed under the Apache License, Version 2.0 + * + * Copyright (C) 2024 Sergey Ponomarev + */ + +'use strict'; +'require view'; +'require fs'; + +function listTunnels() { + let command = '/usr/bin/cloudflared'; + let commandArgs = ['tunnel', 'list', '-o', 'json']; + return fs.exec(command, commandArgs).then(function (res) { + if (res.code === 0) { + return JSON.parse(res.stdout); + } else { + throw new Error(res.stdout + ' ' + res.stderr); + } + }); +} + + +return view.extend({ + handleSaveApply: null, + handleSave: null, + handleReset: null, + + load: function () { + return Promise.all([ + listTunnels() + ]); + }, + + render: function (data) { + var tunnels = data[0]; + + var tunnelsElList = []; + for (var tunnel of tunnels) { + var connectionsSection = []; + if (tunnel.connections.length > 0) { + var connectionsElList = []; + for (let connection of tunnel.connections) { + var dateOpenedAt = new Date(connection.opened_at).toLocaleString(); + connectionsElList.push( + E('tr', [ + E('td', connection.id), + E('td', connection.origin_ip), + E('td', dateOpenedAt), + E('td', connection.colo_name) + ]) + ); + } + + connectionsSection = [ + E('h5', _('Connections')), + E('table', {'class': 'table cbi-section-table'}, [ + E('thead', [ + E('tr', {'class': 'tr table-titles'}, [ + E('th', {'class': 'th'}, 'ID'), + E('th', {'class': 'th'}, _('Origin IP')), + E('th', {'class': 'th'}, _('Opened At')), + E('th', {'class': 'th'}, _('Data center')), + ]), + ]), + E('tbody', connectionsElList) + ]) + ]; + } else { + connectionsSection = [E('em', _('No connections'))]; + } + + var tunnelEl = E('div', [ + E('h4', tunnel.name), + E('span', 'ID '), + E('span', tunnel.id), + E('div', connectionsSection) + ] + ); + tunnelsElList.push(tunnelEl); + } + return E([], [ + E('h2', {'class': 'section-title'}, _('Tunnels')), + E('div', {'id': 'tunnels'}, tunnelsElList), + ]); + } +}); \ No newline at end of file diff --git a/applications/luci-app-cloudflared/po/templates/cloudflared.pot b/applications/luci-app-cloudflared/po/templates/cloudflared.pot index ce4f3c6f96..8f1d4d5428 100644 --- a/applications/luci-app-cloudflared/po/templates/cloudflared.pot +++ b/applications/luci-app-cloudflared/po/templates/cloudflared.pot @@ -35,12 +35,20 @@ msgstr "" msgid "Configuration" msgstr "" +#: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js:55 +msgid "Connections" +msgstr "" + #: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/config.js:54 msgid "" "Create and manage your network on the Cloudflare Zero Trust " "dashboard." msgstr "" +#: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js:62 +msgid "Data center" +msgstr "" + #: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/config.js:113 msgid "Debug" msgstr "" @@ -91,10 +99,14 @@ msgstr "" msgid "Log Direction:" msgstr "" -#: applications/luci-app-cloudflared/root/usr/share/luci/menu.d/luci-app-cloudflared.json:22 +#: applications/luci-app-cloudflared/root/usr/share/luci/menu.d/luci-app-cloudflared.json:30 msgid "Logs" msgstr "" +#: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js:69 +msgid "No connections" +msgstr "" + #: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/config.js:36 msgid "Not Running" msgstr "" @@ -103,6 +115,14 @@ msgstr "" msgid "Obtain a certificate here." msgstr "" +#: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js:61 +msgid "Opened At" +msgstr "" + +#: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js:60 +msgid "Origin IP" +msgstr "" + #: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/config.js:102 msgid "Region" msgstr "" @@ -138,6 +158,11 @@ msgstr "" msgid "Token" msgstr "" +#: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/tunnels.js:82 +#: applications/luci-app-cloudflared/root/usr/share/luci/menu.d/luci-app-cloudflared.json:22 +msgid "Tunnels" +msgstr "" + #: applications/luci-app-cloudflared/htdocs/luci-static/resources/view/cloudflared/log.js:33 msgid "Unable to read the interface info from /var/log/cloudflared.log." msgstr "" diff --git a/applications/luci-app-cloudflared/root/usr/share/luci/menu.d/luci-app-cloudflared.json b/applications/luci-app-cloudflared/root/usr/share/luci/menu.d/luci-app-cloudflared.json index 08c9a2d3b0..4177afa6be 100644 --- a/applications/luci-app-cloudflared/root/usr/share/luci/menu.d/luci-app-cloudflared.json +++ b/applications/luci-app-cloudflared/root/usr/share/luci/menu.d/luci-app-cloudflared.json @@ -18,9 +18,17 @@ "path": "cloudflared/config" } }, + "admin/vpn/cloudflared/tunnels": { + "title": "Tunnels", + "order": 20, + "action": { + "type": "view", + "path": "cloudflared/tunnels" + } + }, "admin/vpn/cloudflared/log": { "title": "Logs", - "order": 20, + "order": 30, "action": { "type": "view", "path": "cloudflared/log" diff --git a/applications/luci-app-cloudflared/root/usr/share/rpcd/acl.d/luci-app-cloudflared.json b/applications/luci-app-cloudflared/root/usr/share/rpcd/acl.d/luci-app-cloudflared.json index 82a9a89a21..3013b35dba 100644 --- a/applications/luci-app-cloudflared/root/usr/share/rpcd/acl.d/luci-app-cloudflared.json +++ b/applications/luci-app-cloudflared/root/usr/share/rpcd/acl.d/luci-app-cloudflared.json @@ -6,7 +6,10 @@ "ubus": { "service": [ "list" ] }, - "file": [ "/var/log/cloudflared.log" ] + "file": { + "/var/log/cloudflared.log": [ "read" ], + "/usr/bin/cloudflared *": [ "exec" ] + } }, "write": { "uci": [ "cloudflared" ], -- 2.30.2