Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: clarify different types of API access #535

Merged
merged 6 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions docs/explanation/api-and-clients.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The Pebble daemon exposes an API (HTTP over a unix socket) to allow remote clients to interact with the daemon. It can start and stop services, add configuration layers to the plan, and so on.

If `pebble run` is started with the `--http <address>` option, Pebble also allows access to "untrusted" HTTP endpoints using the given TCP address (see {ref}`api-access-levels` below).
If `pebble run` is started with the `--http <address>` option, Pebble also exposes open-access HTTP endpoints using the given TCP address (see {ref}`api-access-levels` below).
IronCore864 marked this conversation as resolved.
Show resolved Hide resolved

There is currently no official documentation for the API at the HTTP level (apart from the [code itself](https://github.com/canonical/pebble/blob/master/internals/daemon/api.go)!); most users will interact with it via the Pebble command line interface or by using the Go or Python clients.

Expand All @@ -18,13 +18,24 @@ In addition to the Go client, there's also a [Python client](https://github.com/

API endpoints fall into one of three access levels, from least restricted to most restricted:

* `untrusted`: these are allowed from any user, even unauthenticated users using the HTTP-over-TCP listener. The only untrusted endpoints are `/v1/system-info` and `/v1/health`.
* `read`: these are allowed from any authenticated user, regardless of access level. They are usually read operations that use the HTTP `GET` method, such as listing services or viewing notices.
* `admin`: these are only allowed from admin users. They are usually write or modify operations that use the HTTP `POST` method, such as adding a layer or starting a service.
* **Open-access** - Allowed from any user, even unauthenticated users using the HTTP-over-TCP listener.
* `GET /v1/system-info`, which returns the Pebble version and other information
* `GET /v1/health`, which returns a boolean to indicate whether Pebble's health checks are all healthy

* **Read-access** - Allowed from any authenticated user. For example, listing services or viewing notices.
* All `GET` endpoints except the admin-access `GET` endpoints
* `POST /v1/notices`, which records a custom notice

* **Admin-access** - Only allowed from admin users. For example, adding a layer or starting a service.
* `GET /v1/files`, which pulls a file from a remote system
* `GET /v1/tasks/{task-id}/websocket/{websocket-id}`
* All `POST` endpoints except `POST /v1/notices` (which is read-access)

Pebble authenticates clients that connect to the socket API using peer credentials ([`SO_PEERCRED`](https://man7.org/linux/man-pages/man7/socket.7.html)) to determine the user ID (UID) of the connecting process. If this UID is 0 (root) or the UID of the Pebble daemon, the user's access level is `admin`, otherwise the access level is `read`.

If Pebble can't authenticate the user at all, or if it's an unauthenticated user connecting over TCP, the user is considered `untrusted`.
If Pebble can't authenticate the user, the user's access level is `untrusted`. Unauthenticated users can only use open-access endpoints.

Pebble doesn't try to authenticate users that connect over TCP. So any user that connects over TCP is unauthenticated (access level `untrusted`) and can only use open-access endpoints.
IronCore864 marked this conversation as resolved.
Show resolved Hide resolved


## Controlling API access using identities
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/cli-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ pebble run --args myservice --port 8080 \; --hold
--create-dirs Create Pebble directory on startup if it doesn't exist
--hold Do not start default services automatically
--http= Start HTTP API listening on this address (e.g.,
":4000")
":4000") and expose open-access endpoints
-v, --verbose Log all output from services to stdout
--args= Provide additional arguments to a service
--identities= Seed identities from file (like update-identities
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/identities.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ identities:
<name>:
# (Required) Access level of this identity. Possible values are:
#
# - untrusted: has access only to untrusted or "open" endpoints
# - read: has access to read or "user" endpoints
# - untrusted: has access to open-access endpoints only
# - read: has access to read-access endpoints
# - admin: has access to all endpoints
access: untrusted | read | admin

Expand Down
2 changes: 1 addition & 1 deletion internals/cli/cmd_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type sharedRunEnterOpts struct {
var sharedRunEnterArgsHelp = map[string]string{
"--create-dirs": "Create {{.DisplayName}} directory on startup if it doesn't exist",
"--hold": "Do not start default services automatically",
"--http": `Start HTTP API listening on this address (e.g., ":4000")`,
"--http": `Start HTTP API listening on this address (e.g., ":4000") and expose open-access endpoints`,
"--verbose": "Log all output from services to stdout",
"--args": "Provide additional arguments to a service",
"--identities": "Seed identities from file (like update-identities --replace)",
Expand Down
Loading