Rfc/privileged rshell helper - #55731
Conversation
There was a problem hiding this comment.
The package lets dd-agent change a program that systemd runs as root. It also puts the local policy in a dd-agent-writable directory, omits the socket units from the package lifecycle, and breaks RC client mocks.
🤖 Datadog Autotest · Commit 6b92ef3 · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest
| srcs = [ | ||
| "@rshell_binary//:rshell", | ||
| ], | ||
| attributes = pkg_attributes(mode = "755"), |
There was a problem hiding this comment.
Keep the root helper owned by root
A process with dd-agent rights can change code that systemd runs as root.
Assertion details
- Input: Install the Linux package and activate the privileged rshell service.
- Expected:
The installer must keep the helper owned by root and not writable by dd-agent. - Actual:
The installer changes the helper owner to dd-agent. The service runs this helper as root.
Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest · Open Bits AI session
There was a problem hiding this comment.
Addressed: the installer now reapplies root:root ownership to embedded/bin/rshell after the recursive package ownership pass, so dd-agent cannot replace the helper that systemd executes as root.
| Type=simple | ||
| Group=dd-agent | ||
| UMask=0077 | ||
| ExecStart={{.InstallDir}}/embedded/bin/rshell privileged-helper --policy={{.EtcDir}}/rshell-privileged-helper-policy.json --idle-timeout=30s |
There was a problem hiding this comment.
Put the policy in a root-owned directory
A process with dd-agent rights can remove local administrator restrictions.
Assertion details
- Input: An administrator creates the optional root-owned policy in /etc/datadog-agent.
- Expected:
Store the policy in a root-owned directory that dd-agent cannot change. - Actual:
The service reads the optional policy from a directory that the installer assigns to dd-agent. The dd-agent user can remove the policy before socket activation.
Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest · Open Bits AI session
There was a problem hiding this comment.
Addressed: the helper policy now lives at /etc/datadog-agent/rshell.d/policy.json. The installer creates rshell.d as root:root with mode 0755 and reapplies root ownership recursively after the /etc/datadog-agent dd-agent ownership pass. A regression test checks both the directory state and permission ordering.
| "datadog-agent-action-exp.service": mustReadSystemdUnit("datadog-agent-action.service", expData, ambiantCapabilitiesSupported), | ||
| "datadog-agent-rshell-privileged.service": mustReadSystemdUnit("datadog-agent-rshell-privileged.service", stableData, ambiantCapabilitiesSupported), | ||
| "datadog-agent-rshell-privileged-exp.service": mustReadSystemdUnit("datadog-agent-rshell-privileged.service", expData, ambiantCapabilitiesSupported), | ||
| "datadog-agent-rshell-privileged.socket": mustReadSystemdUnit("datadog-agent-rshell-privileged.socket", stableData, ambiantCapabilitiesSupported), |
There was a problem hiding this comment.
Privileged remote shell cannot connect to its socket after package installation.
Assertion details
- Input: Install a DEB, RPM, or OCI package and enable privileged remote shell.
- Expected:
Add both helper service and socket units to the stable and experiment lifecycle lists. - Actual:
The generated unit map contains the new socket units. The package lifecycle lists omit them, so installation does not write or start them.
Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest · Open Bits AI session
There was a problem hiding this comment.
Addressed: both the privileged helper service and socket are registered in the stable and experiment Systemd and Procmgr lifecycle lists. The focused installer and embedded-unit tests pass.
| // Component can also automatically subscribe to updates by returning a `ListenerProvider` struct | ||
| Subscribe(product data.Product, fn func(update map[string]state.RawConfig, applyStateCallback func(string, state.ApplyStatus))) | ||
| // GetConfigTUFProof returns the Director proof for one Remote Config target. | ||
| GetConfigTUFProof(targetPath string) (state.ConfigTUFProof, bool) |
There was a problem hiding this comment.
Update all RC client implementations
Affected test packages fail to compile and block CI.
Assertion details
- Input: Compile a test package that assigns an existing mock to rcclient.Component.
- Expected:
Update all RC client implementations, or use a smaller interface for proof access. - Actual:
Existing mock RC clients do not implement GetConfigTUFProof. Packages that use these mocks do not compile.
Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest · Open Bits AI session
There was a problem hiding this comment.
Addressed: the production RC component and adapter implement GetConfigTUFProof, and all five test doubles implementing rcclient.Component now provide the method as well. Focused tests for rcclient, queryactions, datasecurity, datastreams, SNMP check config, eBPF, and private action runner all pass.
Go Package Import DifferencesBaseline: bfea996
|
…-helper # Conflicts: # LICENSE-3rdparty.csv # go.mod # go.sum # pkg/config/schema/yaml/private_action_runner.yaml # pkg/config/setup/privateactionrunner.go # pkg/config/setup/privateactionrunner_settings.go # pkg/fleet/installer/packages/embedded/BUILD.bazel # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/debrpm-nc/datadog-agent-rshell-privileged-exp.service # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/debrpm-nc/datadog-agent-rshell-privileged-exp.socket # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/debrpm-nc/datadog-agent-rshell-privileged.service # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/debrpm-nc/datadog-agent-rshell-privileged.socket # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/debrpm/datadog-agent-rshell-privileged-exp.service # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/debrpm/datadog-agent-rshell-privileged-exp.socket # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/debrpm/datadog-agent-rshell-privileged.service # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/debrpm/datadog-agent-rshell-privileged.socket # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/oci-nc/datadog-agent-rshell-privileged-exp.service # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/oci-nc/datadog-agent-rshell-privileged-exp.socket # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/oci-nc/datadog-agent-rshell-privileged.service # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/oci-nc/datadog-agent-rshell-privileged.socket # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/oci/datadog-agent-rshell-privileged-exp.service # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/oci/datadog-agent-rshell-privileged-exp.socket # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/oci/datadog-agent-rshell-privileged.service # pkg/fleet/installer/packages/embedded/tmpl/gen/sd/oci/datadog-agent-rshell-privileged.socket # pkg/fleet/installer/packages/embedded/tmpl/main.go # pkg/privateactionrunner/adapters/config/config_adapter.go # pkg/privateactionrunner/adapters/config/transform.go # pkg/privateactionrunner/bundles/remoteaction/rshell/BUILD.bazel # pkg/privateactionrunner/bundles/remoteaction/rshell/entrypoint.go # pkg/privateactionrunner/bundles/remoteaction/rshell/run_command.go # pkg/privateactionrunner/task-verifier/keys_manager.go
Static quality checks✅ Please find below the results from static quality gates Error
Gate failure full details
Note: Some gates exceeded limits but are non-blocking because the size hasn't increased from the ancestor commit. Successful checksInfo
8 successful checks with minimal change (< 2 KiB)
|
…-helper # Conflicts: # go.sum # omnibus/config/software/datadog-agent.rb # pkg/fleet/installer/packages/datadog_agent_linux.go # test/static/static_quality_gates.yml
aiuto
left a comment
There was a problem hiding this comment.
It will help if you add Bazel tooling directly into https://github.com/DataDog/rshell/tree/main/cmd/rshell
Then we can depend on the BUILD file there directly.
…ce unless enabled by env var or yaml. Fail closed
…-helper # Conflicts: # go.sum # test/static/static_quality_gates.yml
|
Backport evaluation: View Slack thread |
|
This usually happens when the cherry-pick has merge conflicts and needs manual resolution. To backport manually, run: git fetch
git worktree add .worktrees/backport-7.84.x 7.84.x
cd .worktrees/backport-7.84.x
git switch --create backport-55731-to-7.84.x
git cherry-pick -x --mainline 1 aedb15d47cb61c56341d8ca209d6a30f9c707286
git push --set-upstream origin backport-55731-to-7.84.xWorkflow logs: https://github.com/DataDog/datadog-agent/actions/runs/33931844443 |
What does this PR do?
Adds an opt-in, Linux-only privileged execution path for Private Action Runner remediation commands.
private_action_runner.restricted_shell.privileged.enabledand.socket; privileged execution is limited to remediation tasks markedEscalationAllowed, while whole-script root execution remains rejected.Motivation
Some remediation commands require narrowly scoped root access, but the Private Action Runner should remain unprivileged and must not become the authorization boundary. The helper independently authenticates the backend-signed task, retains only the controlled per-command elevation path, and relies on rshell's Landlock/seccomp worker sandbox. Unsupported hosts and disabled configurations continue using the existing unprivileged path.
Describe how you validated your changes
bazelisk test //pkg/fleet/installer/packages/embedded:tmpl_test //pkg/fleet/installer/packages/embedded:embedded_test.dda inv -- -e linter.filenames.tools/build-privileged-rshell-agent.shend to end and verified the three binaries plus generated systemd service/socket contents and modes.Additional Notes