mcdbus/docs/examples/50-mcdbus.rules
Ryan Malloy 5fa1eb36ef Hamilton remediation: validation, ToolError, elicitation, permission docs
Three-pillar fix from Hamilton review:

Code quality — validate_signature() for D-Bus spec compliance,
MCDBUS_TIMEOUT env var, replace 13 error-as-success returns with
ToolError, monotonic clock deadline on tree walks, sanitize D-Bus
error messages, fix resource connection leak via module-level
BusManager, hasattr guards in conftest.

Elicitation — ctx.elicit() confirmation for system bus call_method
and all set_property calls, graceful degradation when client lacks
elicitation support, MCDBUS_REQUIRE_ELICITATION for hard-fail mode.

Permission docs — four-layer guide (systemd sandboxing, dbus-broker
policy, polkit rules, xdg-dbus-proxy) with ready-to-deploy example
configs validated against xmllint, bash -n, and systemd-analyze.
2026-03-06 11:54:31 -07:00

89 lines
2.9 KiB
Plaintext

// polkit rules for mcdbus
//
// Drop into /etc/polkit-1/rules.d/50-mcdbus.rules and restart polkit:
// sudo systemctl restart polkit.service
//
// Users in the "mcdbus" group get read-only access to common system
// services. Everything else falls through to system defaults (which
// typically require admin authentication or deny).
//
// Create the group:
// sudo groupadd mcdbus
// sudo usermod -aG mcdbus youruser
//
// Test with:
// pkcheck --action-id org.freedesktop.systemd1.manage-units \
// --process $$ --allow-user-interaction
//
// List all actions:
// pkaction | grep -E 'systemd|NetworkManager|UPower|udisks'
polkit.addRule(function(action, subject) {
// Only apply to users in the mcdbus group
if (!subject.isInGroup("mcdbus")) {
return polkit.Result.NOT_HANDLED;
}
// Read-only systemd operations
// ListUnits, GetUnit, GetUnitProperties -- these do not change state.
var systemdReadActions = [
"org.freedesktop.systemd1.manage-units",
"org.freedesktop.systemd1.reload-daemon"
];
// NetworkManager: allow reading connection and device info
var nmReadActions = [
"org.freedesktop.NetworkManager.network-control",
"org.freedesktop.NetworkManager.settings.modify.system"
];
// UPower: allow reading battery status
var upowerActions = [
"org.freedesktop.upower.get-history",
"org.freedesktop.upower.get-statistics"
];
// UDisks2: allow reading disk info but not mounting/formatting
var udisksReadActions = [
"org.freedesktop.udisks2.ata-smart-selftest"
];
// Allow read-only systemd access
// NOTE: systemd1.manage-units covers both read and write operations.
// If you only want list/status (no start/stop/restart), you need
// Layer 2 (D-Bus bus policy) to restrict which methods can be called.
// polkit alone cannot distinguish between "list units" and "stop unit"
// under the same action ID.
if (systemdReadActions.indexOf(action.id) >= 0) {
// Only allow for local, active sessions
if (subject.local && subject.active) {
return polkit.Result.YES;
}
}
// Allow NetworkManager reads for local sessions
if (nmReadActions.indexOf(action.id) >= 0) {
if (subject.local && subject.active) {
return polkit.Result.YES;
}
}
// Allow UPower reads
if (upowerActions.indexOf(action.id) >= 0) {
return polkit.Result.YES;
}
// Allow UDisks2 reads
if (udisksReadActions.indexOf(action.id) >= 0) {
if (subject.local && subject.active) {
return polkit.Result.YES;
}
}
// Everything else: fall through to system defaults.
// Do NOT return polkit.Result.NO here -- that would override rules
// with lower priority numbers. NOT_HANDLED lets the chain continue.
return polkit.Result.NOT_HANDLED;
});