For a GUI (or a CLI) running as a different user to reach the agent, the control
socket needs to be group-accessible. This is set by the agent when it binds the
socket — correct from creation, not patched afterwards.
- ipc::ControlSocketAccess { Private, Group(gid) }. Private is the existing
owner-only 0600. Group sets the socket's group to the gid and mode 0660, and
creates the socket's parent directory 0755 so the group can traverse to it; if
the group cannot be set it falls back to owner-only rather than leaving it
wrong. The chown uses std::os::unix::fs::chown — no unsafe, no new lib
dependency.
- ControlSocket::bind takes the access policy (Windows accepts it and keeps its
pipe default for now; a pipe security descriptor is a later follow-up).
- CLI: `tsunagi up --control-group <name>` (env TSUNAGI_CONTROL_GROUP) resolves
the group to its gid via nix (safe wrapper, unix-only dep) and passes
Group(gid); without it the socket stays Private. A name that does not resolve
is reported, and the socket stays owner-only.
- control_socket() now serves the system path (default_control_socket_path) on
macOS too, not just Windows: /var/run/tsunagi/agent.sock, a runtime directory
the GUI can reach, rather than the owner-only state directory. A custom
--state-dir still keeps its own per-user socket.
So the packaged/daemon agent runs e.g. `tsunagi up --control-group tsunagi` and a
user in that group talks to it; a plain per-user agent is unchanged (0600).
Checks: fmt, clippy --workspace --all-targets -D warnings, tsunagi lib tests and
the wg-quic local_control tests pass on macOS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
48 lines
1.7 KiB
TOML
48 lines
1.7 KiB
TOML
[package]
|
|
name = "tsunagi-cli"
|
|
version = "0.1.0"
|
|
description = "The tsunagi command line agent."
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
|
|
[[bin]]
|
|
name = "tsunagi"
|
|
path = "src/main.rs"
|
|
# The binary and the library share a name, which `cargo doc` cannot map to
|
|
# two directories. The command line is documented by `--help`, not rustdoc,
|
|
# so the library keeps the name and this opts out.
|
|
doc = false
|
|
|
|
[dependencies]
|
|
tsunagi = { path = "../tsunagi", version = "0.1.0", features = ["tun-device", "dns-publish"] }
|
|
tsunagi-wireguard = { path = "../tsunagi-wireguard", version = "0.1.0" }
|
|
tsunagi-wg-quic = { path = "../tsunagi-wg-quic", version = "0.1.0" }
|
|
tsunagi-tcp-tls = { path = "../tsunagi-tcp-tls", version = "0.1.0" }
|
|
iroh.workspace = true
|
|
tokio = { version = "1.53", features = ["rt", "rt-multi-thread", "sync", "time", "macros", "signal"] }
|
|
tracing.workspace = true
|
|
tracing-subscriber.workspace = true
|
|
clap = { version = "4.5", features = ["derive", "env"] }
|
|
# Already in the tree through clap. `anstream` strips the escapes when stdout
|
|
# is not a terminal and turns on virtual terminal processing on Windows, so
|
|
# colour is never written where it would show up as rubbish.
|
|
anstream = "1.0"
|
|
anstyle = "1.0"
|
|
# Local interface addresses, for the diagnostics in `status`.
|
|
netwatch = "0.19.3"
|
|
|
|
# Resolving a group name to its gid for `up --control-group`, through a safe
|
|
# wrapper (no unsafe of our own). Unix only.
|
|
[target.'cfg(unix)'.dependencies]
|
|
nix = { version = "0.31", features = ["user"] }
|
|
|
|
[dev-dependencies]
|
|
tokio = { version = "1.53", features = ["rt", "rt-multi-thread", "sync", "time", "macros", "process"] }
|
|
tempfile.workspace = true
|
|
simple-dns = "0.12"
|
|
|
|
[lints]
|
|
workspace = true
|