Skip to content

feat(builtins): implement systemctl#558

Open
matt-dz wants to merge 5 commits into
mainfrom
matthew.deguzman/systemctl-builtin
Open

feat(builtins): implement systemctl#558
matt-dz wants to merge 5 commits into
mainfrom
matthew.deguzman/systemctl-builtin

Conversation

@matt-dz

@matt-dz matt-dz commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add a restricted systemctl builtin for bounded unit listing, inspection, state predicates, runtime jobs, failed-state reset, and unit-file enable/disable operations.
  • Require remediation mode for the entire systemctl surface, including listing, inspection, state predicates, and --help.
  • Enforce exact per-unit action grants through the shared AllowedSystemServices policy.
  • Add a bounded pure-Go systemd D-Bus backend without executing host systemctl or 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:

Control Required configuration Change in this PR
Command authorization Include rshell:systemctl in AllowedCommands, unless all commands are explicitly allowed Reuses the existing command policy
Execution mode Set interp.WithMode(interp.ModeRemediation) Reuses the existing mode; every systemctl invocation now requires it
Unit allowlist Add exact, fully suffixed unit/action grants through AllowedSystemServices Extends the existing policy for restricted systemctl

The existing read, reload, and restart grants are reused. This PR adds start, stop, reset-failed, enable, and disable. The existing clean grant remains specific to bounded journalctl cleanup and does not enable host systemctl 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:

Resource Standard local path Required access Change in this PR
Machine ID /etc/machine-id Read access for target validation Existing MachineIDPath, reused from journalctl
Public system D-Bus socket /run/dbus/system_bus_socket Connect access and noninteractive authorization for the requested systemd methods New ManagerBusSocket field and --systemd-manager-socket flag
Procfs descriptor links /proc/self/fd Procfs mounted and accessible for pinned-socket connections Existing requirement for journal rotation; required for all manager connections

No explicit SystemdTargetConfig is needed for the local host when these standard paths are available. A container or mounted-host integration supplies the container-visible absolute paths:

interp.WithSystemdTarget(interp.SystemdTargetConfig{
	MachineIDPath:    "/host/etc/machine-id",
	ManagerBusSocket: "/host/run/dbus/system_bus_socket",
})

Once any explicit target field is configured, omitted fields do not fall back to local paths. MachineIDPath remains mandatory, and ManagerBusSocket must be supplied for manager-backed systemctl operations. 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/private socket is unsupported.

JournalDirs and JournalControlSocket are not required solely for systemctl. The configured machine ID and manager socket are trusted target paths that bypass AllowedPaths. /proc/self/fd is a fixed backend path that is also accessed directly; it is not configurable through ProcPath.

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-units considers only units carrying an exact read grant.
  • Inspection exposes a fixed, bounded property set.
  • Compound operations authorize every required unit/action pair before any effect.
  • Systemd may still operate on dependencies of an authorized unit as part of its normal transaction semantics.
  • enable and disable may follow installation metadata and perform an implicit global manager reload.
  • Generic D-Bus methods, arbitrary properties, globs, user/machine/root targets, power verbs, and standalone daemon-reload remain unavailable.
  • Manager-backed operations require Linux, but do not require cgo, libsystemd, or the host systemctl executable.

Validation

  • make fmt
  • go test ./...
  • go test -race ./internal/systemd
  • RSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash -timeout 120s
  • Linux and Windows cross-compilation checks for the systemd backend and systemctl packages
  • Independent security audit of the implementation and command-wide remediation gate

matt-dz commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread builtins/systemctl/systemctl.go

matt-dz commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread builtins/systemctl/systemctl.go
@matt-dz

matt-dz commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

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".

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 systemctl builtin (list/inspect/predicates/jobs/reset-failed/enable-disable) gated entirely behind remediation mode and exact unit/action grants.
  • Extends systemd target configuration with ManagerBusSocket and 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.

Comment thread cmd/rshell/main.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 41 out of 42 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 41 out of 42 changed files in this pull request and generated 1 comment.

Comment thread internal/systemd/manager_protocol.go

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 41 out of 42 changed files in this pull request and generated no new comments.

@matt-dz
matt-dz marked this pull request as ready for review July 20, 2026 17:55
@matt-dz matt-dz changed the title Add restricted systemctl builtin feat(builtins): implement systemctl Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants