Skip to content

Add secure local REST Unix socket for sonic-cli - #168

Open
dlanov wants to merge 1 commit into
sonic-net:masterfrom
dlanov:add-local-rest-unix-socket
Open

dlanov wants to merge 1 commit into
sonic-net:masterfrom
dlanov:add-local-rest-unix-socket

Conversation

@dlanov

@dlanov dlanov commented Sep 16, 2026

Copy link
Copy Markdown

Summary

Add a secure local Unix-domain-socket REST path for sonic-cli while preserving the existing authenticated HTTPS/TCP REST behavior.

A fresh SONiC image can run the REST server with client_auth=user by default, but the Python sonic-cli REST client currently talks to https://localhost without credentials. That makes local CLI REST requests fail with HTTP 401 even though remote REST authentication is intentionally enabled.

This change keeps remote REST authentication unchanged and adds a separate local transport at /var/run/rest-local.sock.

Changes

  • Add a local REST Unix socket listener at /var/run/rest-local.sock
  • Preserve the existing HTTPS/TCP listener and Basic Auth behavior unchanged
  • Use Linux SO_PEERCRED on accepted Unix connections to obtain the caller's kernel UID/GID/PID
  • Resolve the peer UID against the already-mounted host /host_etc/passwd
  • Preserve the existing read/write authorization model by checking host admin-group membership via /host_etc/passwd and /host_etc/group
  • Fail closed when the peer UID cannot be resolved
  • Do not trust CLI_USER, HTTP headers, or other client-provided identity for authorization
  • Update the Python ApiClient default local transport to use the Unix socket without introducing a new Python dependency
  • Leave the native rest_cl.cpp path unchanged; it already targets /var/run/rest-local.sock

Authorization behavior

Remote TCP/TLS behavior is unchanged:

  • unauthenticated request -> 401
  • authenticated non-admin read -> existing behavior
  • authenticated non-admin write -> 403
  • authenticated admin write -> existing behavior

Local Unix-socket behavior:

  • unknown peer UID -> 401
  • recognized non-admin read -> allowed
  • recognized non-admin write -> 403
  • recognized admin read/write -> allowed

The local username is derived server-side from kernel-provided peer credentials. Client-supplied headers or environment variables are not used for authorization.

Security rationale

The REST server's existing client_auth=user default is intentionally preserved. This PR does not weaken remote REST security and does not revert the secure default.

A flat "Unix socket access implies admin" bypass is also avoided because Klish itself does not enforce the local read/write privilege boundary. The Unix socket therefore bypasses only the password challenge; authorization is still enforced using the actual peer UID and host account/group data.

Testing

Python Unix-socket tests:

python3 -m pytest \
  CLI/tests/test_cli_client.py \
  CLI/actioner/test_cli_client_uds.py

Results:

  • existing CLI/tests/test_cli_client.py: 7 passed
  • new Unix-socket client tests: 4 passed

The new client tests use a real AF_UNIX HTTP server and cover GET, PATCH body delivery, default adapter wiring, and the absence of an Authorization header.

Go validation:

The repository's native REST Go test target is:

tools/test/rest-gotest.sh

It depends on the normal sonic-mgmt-common / libyang / generated ocbinds build chain, which was not available in the local checkout. The same pre-existing build failure was reproduced on the unmodified tree.

The new Go logic was additionally exercised in an isolated scratch module using the exact implementation logic, including a real net.Listen("unix", ...) / net.Dial("unix", ...) round trip for SO_PEERCRED; 14 tests passed covering peer credential extraction, host identity parsing, 401/403/200 authorization behavior, and forged-header resistance.

Additional checks:

gofmt -l <changed Go files>
python3 -m py_compile CLI/actioner/cli_client.py
git diff --check

All completed cleanly.

Fixes sonic-net/sonic-buildimage#29504

Signed-off-by: Dennis Lanov <dennis.lanov@gmail.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@mssonicbld

Copy link
Copy Markdown

Hi, there are workflow run(s) waiting for approval, you may be first-time contributor. I will notify maintainers to help approve once PR is approved. Thanks!

---Powered by SONiC BuildBot

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.

Bug:sonic-cli REST requests are rejected when REST server defaults to user authentication

2 participants