Merge pull request #324 from naturallaw777/copilot/fix-rdp-boot-time-setup
fix(rdp): prepend /run/wrappers/bin to PATH and add pkexec preflight check
This commit is contained in:
@@ -53,17 +53,42 @@ class RdpModuleBootSetupTests(unittest.TestCase):
|
|||||||
self.assertIn('echo "grdctl command failed (exit $rc): $*" >&2', self.setup_service)
|
self.assertIn('echo "grdctl command failed (exit $rc): $*" >&2', self.setup_service)
|
||||||
|
|
||||||
def test_setup_runs_grdctl_directly_as_root(self):
|
def test_setup_runs_grdctl_directly_as_root(self):
|
||||||
# The oneshot service already runs as root; system-mode grdctl must be
|
# The oneshot service runs as root; grdctl --system is called directly.
|
||||||
# invoked directly so it does not attempt pkexec authorization.
|
# GRD 50.x invokes pkexec internally, but the call itself is plain
|
||||||
|
# grdctl --system, not a manual pkexec invocation.
|
||||||
self.assertIn('grdctl --system "$@"', self.setup_service)
|
self.assertIn('grdctl --system "$@"', self.setup_service)
|
||||||
self.assertNotIn("runuser", self.setup_service)
|
self.assertNotIn("runuser", self.setup_service)
|
||||||
self.assertNotIn("pkexec", self.setup_service)
|
|
||||||
self.assertNotIn("sudo", self.setup_service)
|
self.assertNotIn("sudo", self.setup_service)
|
||||||
|
# No direct Nix-store pkexec invocation (pkgs.polkit}/bin/pkexec).
|
||||||
|
self.assertNotIn("pkgs.polkit}/bin/pkexec", self.setup_service)
|
||||||
|
|
||||||
def test_privilege_escalation_packages_absent_from_setup_path(self):
|
def test_privilege_escalation_packages_absent_from_setup_path(self):
|
||||||
self.assertNotIn("pkgs.polkit", self.setup_service)
|
self.assertNotIn("pkgs.polkit", self.setup_service)
|
||||||
self.assertNotIn("pkgs.util-linux", self.setup_service)
|
self.assertNotIn("pkgs.util-linux", self.setup_service)
|
||||||
|
|
||||||
|
def test_run_wrappers_bin_prepended_to_path(self):
|
||||||
|
# /run/wrappers/bin must be prepended to PATH before any grdctl_system
|
||||||
|
# invocation so that grdctl --system resolves the NixOS setuid pkexec.
|
||||||
|
path_export = 'export PATH="/run/wrappers/bin:$PATH"'
|
||||||
|
grdctl_marker = "grdctl_system"
|
||||||
|
script = self.setup_service
|
||||||
|
path_idx = script.find(path_export)
|
||||||
|
grdctl_idx = script.find(grdctl_marker)
|
||||||
|
self.assertGreater(path_idx, -1, f"{path_export!r} not found in setup script")
|
||||||
|
self.assertGreater(
|
||||||
|
grdctl_idx, path_idx,
|
||||||
|
"PATH export must appear before the first grdctl_system usage",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_pkexec_preflight_check(self):
|
||||||
|
# A preflight must confirm /run/wrappers/bin/pkexec is executable
|
||||||
|
# with a clear error message before any GRD configuration changes.
|
||||||
|
self.assertIn("test -x /run/wrappers/bin/pkexec", self.setup_service)
|
||||||
|
self.assertIn(
|
||||||
|
"/run/wrappers/bin/pkexec is absent or not executable",
|
||||||
|
self.setup_service,
|
||||||
|
)
|
||||||
|
|
||||||
def test_hub_files_are_the_source_of_truth_for_username_and_password(self):
|
def test_hub_files_are_the_source_of_truth_for_username_and_password(self):
|
||||||
self.assertIn('DEFAULT_USERNAME="sovran"', self.setup_service)
|
self.assertIn('DEFAULT_USERNAME="sovran"', self.setup_service)
|
||||||
self.assertIn('if [ ! -f "$USERNAME_FILE" ]; then', self.setup_service)
|
self.assertIn('if [ ! -f "$USERNAME_FILE" ]; then', self.setup_service)
|
||||||
|
|||||||
@@ -51,6 +51,13 @@ lib.mkIf config.sovran_systemsOS.features.rdp {
|
|||||||
script = ''
|
script = ''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# GRD 50.x invokes pkexec internally for every grdctl --system call, even
|
||||||
|
# when the caller is root. NixOS exposes the required setuid wrapper at
|
||||||
|
# /run/wrappers/bin/pkexec; the Nix-store polkit binary is not setuid and
|
||||||
|
# must not shadow it. Prepend the wrapper directory so every subsequent
|
||||||
|
# grdctl --system resolves the correct binary.
|
||||||
|
export PATH="/run/wrappers/bin:$PATH"
|
||||||
|
|
||||||
STATE_DIR="/var/lib/gnome-remote-desktop"
|
STATE_DIR="/var/lib/gnome-remote-desktop"
|
||||||
TLS_DIR="$STATE_DIR/tls"
|
TLS_DIR="$STATE_DIR/tls"
|
||||||
USERNAME_FILE="$STATE_DIR/rdp-username"
|
USERNAME_FILE="$STATE_DIR/rdp-username"
|
||||||
@@ -166,6 +173,15 @@ lib.mkIf config.sovran_systemsOS.features.rdp {
|
|||||||
chown gnome-remote-desktop:gnome-remote-desktop "$CRED_FILE"
|
chown gnome-remote-desktop:gnome-remote-desktop "$CRED_FILE"
|
||||||
chmod 600 "$CRED_FILE"
|
chmod 600 "$CRED_FILE"
|
||||||
|
|
||||||
|
# Preflight: the NixOS setuid pkexec wrapper must be present and executable
|
||||||
|
# before any grdctl --system call. Absence means the system was booted
|
||||||
|
# without security.wrappers or the wrapper directory is not mounted yet.
|
||||||
|
if ! test -x /run/wrappers/bin/pkexec; then
|
||||||
|
echo "Preflight check failed: /run/wrappers/bin/pkexec is absent or not executable." >&2
|
||||||
|
echo "GNOME Remote Desktop system configuration requires the NixOS setuid pkexec wrapper at /run/wrappers/bin/pkexec." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
grdctl_system rdp enable
|
grdctl_system rdp enable
|
||||||
grdctl_system rdp set-tls-cert "$TLS_DIR/rdp-tls.crt"
|
grdctl_system rdp set-tls-cert "$TLS_DIR/rdp-tls.crt"
|
||||||
grdctl_system rdp set-tls-key "$TLS_DIR/rdp-tls.key"
|
grdctl_system rdp set-tls-key "$TLS_DIR/rdp-tls.key"
|
||||||
|
|||||||
Reference in New Issue
Block a user