Addresses the three non-blocking notes from #292: - README's plugin_api requirement was stale (22) vs the manifest's real minimum (17, the onExit lifecycle addition) — corrected, and pinned the noctalia version floor to beta.7 (the first tagged release plugin_api actually reaches 17 in). - apply()'s privilege path ran the whole discovery+mutate script through `priv sh -c '...'`, which the documented sudoers rule (NOPASSWD: /usr/bin/nmcli) never covers — sudo -n always failed. Now the privilege prefix is applied to each of the two mutating nmcli calls individually, never to a wrapping shell. - Regenerated thumbnail.webp. Co-authored-by: nightwatch75 <nightwatch75@users.noreply.github.com>
This commit is contained in:
co-authored by
nightwatch75
parent
b9d21951ec
commit
f222cdee2b
@@ -75,8 +75,8 @@ neighbouring provider (what scroll sends).
|
||||
|
||||
## Requirements
|
||||
|
||||
- noctalia v5.0.0-beta.6 or newer for the core plugin; the gesture remapping
|
||||
and lookup tester need a newer build still (`plugin_api = 22`)
|
||||
- noctalia v5.0.0-beta.7 or newer (`plugin_api = 17`, for the `onExit`
|
||||
lifecycle cleanup in `service.luau`)
|
||||
- NetworkManager (`networkmanager`, provides `nmcli`) with an active connection
|
||||
- Permission to modify system connections (see *Privileges* below)
|
||||
- `dig` (bind-tools/dnsutils) or `nslookup`, optional — only the lookup
|
||||
@@ -87,13 +87,19 @@ neighbouring provider (what scroll sends).
|
||||
*Privilege command* is **empty by default**: NetworkManager's polkit policy
|
||||
usually lets active local sessions modify system connections without a
|
||||
password. If you get a "not authorized" error, set it to `pkexec` (shows
|
||||
noctalia's own polkit prompt) or `sudo -n` with a matching sudoers rule:
|
||||
noctalia's own polkit prompt) or `sudo -n` with a matching sudoers rule.
|
||||
The privilege command is applied to the `nmcli con mod` and `nmcli device
|
||||
reapply` calls individually — never to a wrapping shell — so the sudoers
|
||||
rule only ever needs to name `nmcli` itself:
|
||||
|
||||
```
|
||||
# /etc/sudoers.d/nmcli-dns
|
||||
youruser ALL=(root) NOPASSWD: /usr/bin/nmcli
|
||||
```
|
||||
|
||||
With `pkexec`, this means an apply may show its polkit prompt twice (once
|
||||
per elevated `nmcli` call) instead of once.
|
||||
|
||||
Or grant it via a polkit rule and keep the setting empty:
|
||||
|
||||
```js
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
-- binding that opens its own settings, and that default is exactly what's
|
||||
-- wanted here.
|
||||
|
||||
local STATE_KEY = "dns_state"
|
||||
local STATE_KEY = "dns_state" -- published by service.luau
|
||||
|
||||
local GLYPH_UNKNOWN = "globe"
|
||||
|
||||
local snapshot = nil -- last state published by the service
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
-- "apply_request" entries this panel emits. Picking a provider applies it
|
||||
-- immediately (one nmcli change, no reactivation).
|
||||
|
||||
local STATE_KEY = "dns_state"
|
||||
local REQUEST_KEY = "apply_request"
|
||||
local STATE_KEY = "dns_state" -- published by service.luau
|
||||
local REQUEST_KEY = "apply_request" -- consumed by service.luau
|
||||
|
||||
local RESOLVE_TIMEOUT_MS = 4000
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
id = "nightwatch75/dns-switcher"
|
||||
name = "DNS Switcher"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
plugin_api = 17
|
||||
author = "nightwatch75"
|
||||
license = "MIT"
|
||||
|
||||
+20
-18
@@ -14,10 +14,13 @@
|
||||
-- reapply pushes the change onto the live connection without reactivating
|
||||
-- it, so the network never drops. The privilege command is empty by default:
|
||||
-- NetworkManager's polkit policy lets active local sessions modify system
|
||||
-- connections on most desktop distros.
|
||||
-- connections on most desktop distros. When set, it is prefixed onto each
|
||||
-- of those two nmcli calls individually (never onto a wrapping shell), so a
|
||||
-- sudoers NOPASSWD rule naming the nmcli binary itself is enough — see
|
||||
-- apply() below and the README's Privileges section.
|
||||
|
||||
local STATE_KEY = "dns_state"
|
||||
local REQUEST_KEY = "apply_request"
|
||||
local STATE_KEY = "dns_state" -- published here, read by widget + panel
|
||||
local REQUEST_KEY = "apply_request" -- sent by widget/panel, consumed here
|
||||
|
||||
local BUILTIN = {
|
||||
{ id = "google", label = "Google", ip = "8.8.8.8 8.8.4.4", glyph = "brand-google" },
|
||||
@@ -52,10 +55,6 @@ local function trim(value)
|
||||
return (value:gsub("^%s+", ""):gsub("%s+$", ""))
|
||||
end
|
||||
|
||||
local function shellQuote(value)
|
||||
return "'" .. value:gsub("'", "'\\''") .. "'"
|
||||
end
|
||||
|
||||
local function pollSeconds()
|
||||
return math.max(2, tonumber(cfg("poll_seconds")) or 10)
|
||||
end
|
||||
@@ -302,23 +301,26 @@ local function apply(provider)
|
||||
else
|
||||
mods = 'ipv4.dns "' .. safeIp .. '" ipv4.ignore-auto-dns yes'
|
||||
end
|
||||
local inner = 'ACT=$(LC_ALL=C nmcli -t -f TYPE,DEVICE,UUID connection show --active 2>/dev/null); '
|
||||
.. [[LINE=$(printf '%s\n' "$ACT" | grep -E '^(802-11-wireless|802-3-ethernet):' | head -n 1); ]]
|
||||
.. [=[[ -n "$LINE" ] || LINE=$(printf '%s\n' "$ACT" | grep -v '^loopback:' | head -n 1); ]=]
|
||||
.. [=[[ -n "$LINE" ] || exit 9; ]=]
|
||||
.. 'DEV=$(printf \'%s\' "$LINE" | cut -d: -f2); '
|
||||
.. 'UUID=$(printf \'%s\' "$LINE" | cut -d: -f3); '
|
||||
.. 'nmcli con mod "$UUID" ' .. mods .. ' && nmcli device reapply "$DEV"'
|
||||
|
||||
local priv = cfg("privilege_command")
|
||||
if type(priv) ~= "string" then
|
||||
priv = ""
|
||||
end
|
||||
priv = trim(priv)
|
||||
local cmd = inner
|
||||
if priv ~= "" then
|
||||
cmd = priv .. " sh -c " .. shellQuote(inner)
|
||||
end
|
||||
-- Prefixed onto each nmcli invocation individually, never onto a
|
||||
-- wrapping `sh -c`: the README's sudoers example authorizes the nmcli
|
||||
-- binary itself (NOPASSWD: /usr/bin/nmcli), which never covers a shell
|
||||
-- run under sudo. Discovering the device/uuid stays unprivileged either
|
||||
-- way (it's a plain read), so only the two mutating calls need it.
|
||||
local privPrefix = priv ~= "" and (priv .. " ") or ""
|
||||
|
||||
local cmd = 'ACT=$(LC_ALL=C nmcli -t -f TYPE,DEVICE,UUID connection show --active 2>/dev/null); '
|
||||
.. [[LINE=$(printf '%s\n' "$ACT" | grep -E '^(802-11-wireless|802-3-ethernet):' | head -n 1); ]]
|
||||
.. [=[[ -n "$LINE" ] || LINE=$(printf '%s\n' "$ACT" | grep -v '^loopback:' | head -n 1); ]=]
|
||||
.. [=[[ -n "$LINE" ] || exit 9; ]=]
|
||||
.. 'DEV=$(printf \'%s\' "$LINE" | cut -d: -f2); '
|
||||
.. 'UUID=$(printf \'%s\' "$LINE" | cut -d: -f3); '
|
||||
.. privPrefix .. 'nmcli con mod "$UUID" ' .. mods .. ' && ' .. privPrefix .. 'nmcli device reapply "$DEV"'
|
||||
|
||||
changing = true
|
||||
publish()
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 79 KiB |
Reference in New Issue
Block a user