feat(builtins): implement systemctl#558
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ffaee1e925
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ffaee1e925
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
Pull request overview
This PR adds a new remediation-only, capability-bounded systemctl builtin backed by a pure-Go, fixed-surface systemd D-Bus client, extending the existing internal/systemd trusted-target model and the shared AllowedSystemServices policy to cover additional unit-control actions.
Changes:
- Introduces a restricted
systemctlbuiltin (list/inspect/predicates/jobs/reset-failed/enable-disable) gated entirely behind remediation mode and exact unit/action grants. - Extends systemd target configuration with
ManagerBusSocketand implements a bounded Linux-only D-Bus manager backend (with strict message/signal bounds and target machine-id verification). - Updates policy, docs, CLI flags, allowlists, and adds scenario + unit test coverage for the new systemctl surface.
Reviewed changes
Copilot reviewed 41 out of 42 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/scenarios/cmd/systemctl/help/help.yaml | Scenario coverage for systemctl --help output and remediation-only gating. |
| tests/scenarios/cmd/systemctl/errors/start_denied.yaml | Scenario coverage for exact action-grant enforcement (start). |
| tests/scenarios/cmd/systemctl/errors/read_only.yaml | Scenario coverage for remediation-mode requirement (list-units). |
| tests/scenarios/cmd/systemctl/errors/help_read_only.yaml | Scenario coverage for remediation-mode requirement (--help). |
| tests/scenarios/cmd/systemctl/errors/glob_rejected.yaml | Scenario coverage for rejecting globbed unit operands. |
| tests/scenarios/cmd/systemctl/errors/denied_status.yaml | Scenario coverage for read-grant enforcement on inspection (status). |
| tests/scenarios/cmd/systemctl/basic/restricted_empty_list.yaml | Scenario coverage for restricted enumeration when no read grants exist. |
| tests/scenarios/cmd/help/help_readonly_mode.yaml | Updates help scenario to reflect remediation-only commands (incl. systemctl). |
| SHELL_FEATURES.md | Documents the bounded systemctl surface and expanded systemd policy/target behavior. |
| README.md | Updates user-facing documentation for unit/action grants, systemd target config, and restricted systemctl. |
| LICENSE-3rdparty.csv | Adds third-party license entry for github.com/godbus/dbus/v5. |
| interp/systemd_target.go | Adds ManagerBusSocket to runner systemd target configuration. |
| interp/systemd_target_test.go | Tests default/copy behavior for ManagerBusSocket. |
| interp/system_services.go | Expands allowed actions; adds readable-unit enumeration helper; tightens name validation. |
| interp/system_services_test.go | Adds tests for new actions, readable grants, and validation boundaries. |
| interp/runner_exec.go | Wires ReadableSystemServices into builtin call context. |
| interp/register_builtins.go | Registers the new systemctl builtin. |
| interp/api.go | Hooks systemd manager capabilities into runner systemd services; updates mode comments. |
| internal/systemd/target.go | Adds ManagerBusSocket and resolves defaults/explicit-target behavior. |
| internal/systemd/target_test.go | Tests manager-only explicit target resolution and validation. |
| internal/systemd/manager_unsupported.go | Non-Linux stubs for manager-backed operations (fail closed). |
| internal/systemd/manager_signal.go | Implements bounded synchronous D-Bus signal delivery with overflow detection. |
| internal/systemd/manager_signal_test.go | Tests signal overflow handling and lifecycle behavior. |
| internal/systemd/manager_protocol.go | Implements fixed manager protocol methods (list/inspect/jobs/reset-failed/enable/disable) with strict validation. |
| internal/systemd/manager_protocol_test.go | Validates protocol behavior via a fake bus, including bounds and partial-progress errors. |
| internal/systemd/manager_linux.go | Linux manager bus connection: pinned socket via /proc/self/fd, EXTERNAL auth, Hello, machine-id verification, fixed timeouts. |
| internal/systemd/manager_incoming.go | Rejects unsolicited inbound method calls by closing transport early. |
| internal/systemd/manager_incoming_test.go | Tests inbound-method-call rejection behavior. |
| internal/systemd/manager_dbus_limit.go | Bounds incoming D-Bus authentication and message sizes before decode. |
| internal/systemd/manager_dbus_limit_test.go | Tests frame sizing, endian validation, and auth input bounds. |
| go.mod | Adds github.com/godbus/dbus/v5 dependency. |
| go.sum | Adds checksums for github.com/godbus/dbus/v5. |
| docs/RULES.md | Extends systemd backend rules to cover manager bus socket + restricted systemctl requirements/bounds. |
| cmd/rshell/main.go | Adds --systemd-manager-socket flag and updates allowed-services wording. |
| cmd/rshell/main_test.go | Updates CLI tests for new flags and expanded allowed-services semantics. |
| builtins/systemd.go | Adds bounded systemctl state/control interfaces and limits to the builtins API surface. |
| builtins/systemctl/systemctl.go | Implements the remediation-only restricted systemctl builtin and its request validation/authorization flow. |
| builtins/systemctl/systemctl_test.go | Unit tests covering mode gating, flag scoping, validation, authorization ordering, and output sanitization. |
| builtins/builtins.go | Extends system service/unit actions and adds ReadableSystemServices to call context. |
| analysis/symbols_interp.go | Allows new symbols used by interp changes (sorting, UTF-8 validation). |
| analysis/symbols_builtins.go | Adds allowlisted symbols and call-context fields for the systemctl builtin. |
| AGENTS.md | Documents trusted systemd target bypass and manager-bus behavior for agents/operators. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
systemctlbuiltin for bounded unit listing, inspection, state predicates, runtime jobs, failed-state reset, and unit-file enable/disable operations.systemctlsurface, including listing, inspection, state predicates, and--help.AllowedSystemServicespolicy.systemctlor exposing a generic D-Bus client.Why
Agents need a controlled way to inspect and remediate explicitly authorized systemd units. The command-wide remediation gate keeps all manager access behind an explicit operator opt-in, while exact unit/action grants constrain which units are visible and which operations are permitted.
Required configuration
Every invocation must pass all three policy gates:
rshell:systemctlinAllowedCommands, unless all commands are explicitly allowedinterp.WithMode(interp.ModeRemediation)systemctlinvocation now requires itAllowedSystemServicessystemctlThe existing
read,reload, andrestartgrants are reused. This PR addsstart,stop,reset-failed,enable, anddisable. The existingcleangrant remains specific to boundedjournalctlcleanup and does not enable hostsystemctl clean.The development CLI accepts the equivalent configuration through:
--allowed-commands rshell:systemctl--mode remediation--allowed-services UNIT:ACTION[+ACTION...]Host access requirements
The process embedding rshell needs access to the target system manager:
/etc/machine-idMachineIDPath, reused fromjournalctl/run/dbus/system_bus_socketManagerBusSocketfield and--systemd-manager-socketflag/proc/self/fdNo explicit
SystemdTargetConfigis needed for the local host when these standard paths are available. A container or mounted-host integration supplies the container-visible absolute paths:Once any explicit target field is configured, omitted fields do not fall back to local paths.
MachineIDPathremains mandatory, andManagerBusSocketmust be supplied for manager-backedsystemctloperations. Both resources must come from the same host.The process authenticates to the public system bus with its effective UID and must already be authorized by the host D-Bus, systemd, and any applicable Polkit policy. Rshell performs no privilege elevation or interactive authorization. The private
/run/systemd/privatesocket is unsupported.JournalDirsandJournalControlSocketare not required solely forsystemctl. The configured machine ID and manager socket are trusted target paths that bypassAllowedPaths./proc/self/fdis a fixed backend path that is also accessed directly; it is not configurable throughProcPath.The configured manager endpoint must be a real Unix socket rather than a final symlink. Missing socket or procfs access, D-Bus authentication or authorization denial, and a machine-ID mismatch all fail closed.
Behavior and security boundaries
list-unitsconsiders only units carrying an exactreadgrant.enableanddisablemay follow installation metadata and perform an implicit global manager reload.daemon-reloadremain unavailable.libsystemd, or the hostsystemctlexecutable.Validation
make fmtgo test ./...go test -race ./internal/systemdRSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash -timeout 120ssystemctlpackages