Skip to content

Prove and document the non-root path through the master permission directive #19

Closed

Description

@marcinpsk

Parent

#14

What to build

Both the user documentation and the manual page name the master permission
directive as the supported way to run the subagent without root. Nobody has run
it, so an operator is following an untested instruction.

After this ticket the non-root path runs in the distribution containers that the
release gate already builds and installs into, and the documentation carries the
exact recipe that the test runs.

One shared scenario script holds the whole check. Each distribution test script
installs the master daemon and the walk tool with its own package manager, then
runs the shared script, so the two package formats cannot drift apart. The
scenario writes a master configuration that enables AgentX and grants group
access to the socket and to its parent directory, starts the master in the
foreground because the containers have no init, creates a system user and group,
runs the subagent as that user, and walks the table. Success is the boundary
rows of the container interfaces, in RFC index order.

Read the exact argument order of the master permission directive from the master
configuration manual page inside the container. Do not copy it from the parent
spec or from memory.

The shipped unit keeps the root user. This is a documented and tested option,
not a changed default, because dropping root by default would break every
installation that has not configured its master.

Acceptance criteria

  • One shared scenario script runs the non-root check, and both distribution
    test scripts call it after install.
  • The scenario starts the master in the foreground, grants access to
    the socket by group and makes the parent directory traversable, runs the subagent as a non-root
    system user in that group, and walks the table.
  • The walk returns the boundary rows of the container interfaces, in RFC
    index order, and the test fails if the walk returns nothing.
  • The installed manual section for the permission directive is printed in the log
    for diagnosis. The ownership and mode assertions prove the semantics.
  • The packaging policy test asserts that every distribution test script runs
    the shared scenario, so a new distribution cannot skip it.
  • The distribution test scripts no longer install iproute, which no command
    in them uses.
  • The whole check passes in Debian 12, Debian 13 and Fedora.
  • The user documentation carries the recipe the test runs: the master
    configuration line, the group, and a systemd drop-in that sets the user
    and the supplementary group.
  • The manual page carries the same recipe, and its notes section says that
    root is the default rather than a requirement.
  • The shipped unit still runs as root.

Correction to this ticket

This ticket asked for a directive that grants group access to the socket and to
its parent directory. net-snmp cannot do that. In agent/mibgroup/agentx/master.c
it applies chmod and chown to the socket path only. It never changes the
group of the parent directory.

A first draft used agentXPerms 0660 0770 root agentx-ifstack. That leaves
/var/agentx owned by root:root with no traverse bit for others, so the
subagent cannot reach the socket. The working form is:

agentXPerms 0660 0755 root agentx-ifstack

The directory grants traverse. The socket carries the access control, as mode
0660 owned by root:agentx-ifstack.

A second net-snmp behavior reached the documentation. In
snmplib/transports/snmpUnixDomain.c the directory is created only when bind
fails with ENOENT, so an existing /var/agentx keeps its mode and the
directory mode in the directive is ignored. An operator with a previous snmpd
installation meets exactly that case, so both documents now say it.

This ticket also asked for the argument order to be read from the manual page in
the container. The scenario prints that section, which is the useful part, but
does not assert its rendered text. A distribution that renders the line with
different spacing or a translated parameter name would fail the release gate
while the directive works. The ownership and mode assertions prove the
semantics instead.

Implementation

Commit 04a638a on packaging/non-root-path, open as #23 against develop.

Verified in CI, which is the only place this can run. All three container jobs
pass, and each log carries the printed manual section, the walk, and the
scenario result:

Job Result Rows
packages / debian (12) pass 4
packages / debian (13) pass 4
packages / fedora pass 4

The Debian 12 log shows the installed signature as
agentXPerms SOCKPERMS [DIRPERMS [USER|UID [GROUP|GID]]], and the walk returns
.1.3.6.1.2.1.31.1.2.1.3.0.1, .0.2, .1.0 and .2.0: the loopback and
container interfaces, each standalone, each with both boundary rows.

The scenario proves the rows belong to the subagent it started. It walks the
table before launch and requires no rows, reads the real and effective user IDs
of the child from /proc and rejects zero, and requires the boundary rows of
exactly the interfaces in /sys/class/net, so a fabricated walk cannot pass.

Known limit, stated in both documents: the containers run no service manager, so
the systemd drop-in, systemd's application of the supplementary group, and the
unit sandbox are not exercised. The shipped unit keeps User=root.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentFully specified, ready for an AFK agent

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions