Skip to content

Commit

Permalink
Introduce documentation about required capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelroquetto committed Jan 29, 2025
1 parent ab3c784 commit 0b47d08
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 17 deletions.
5 changes: 1 addition & 4 deletions docs/sources/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ While most eBPF programs require elevated privileges, Beyla allow you to specify

Some Beyla functionality requires further permissions, for example using the network observability probes with Linux Traffic Control requires `CAP_NET_ADMIN`, but it's a feature you have to optionally enable.

`CAP_SYS_ADMIN` is only required to enable context propagation in Go across multiple nodes, however if this permission
isn't granted Beyla gracefully degrades its functionality to support only partial traces.

Distributed tracing is only supported for Go services, while other programming language support remains on the road-map. Distributed tracing for other programming languages works on the same node, but not across different nodes.
For a comprehensive list of capabilities required by Beyla, refer to [Security, permissions and capabilities]({{< relref "./security" >}}).

## Get started

Expand Down
167 changes: 167 additions & 0 deletions docs/sources/security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
---
title: Security, permissions and capabilities
menuTitle: Security, permissions and capabilities
description: Privileges and capabilities required by Beyla
weight: 22
keywords:
- Beyla
- eBPF
- security
- capabilities
aliases:
- /docs/grafana-cloud/monitor-applications/beyla/security/
---

# Security, permissions and capabilities

Beyla needs access to various Linux interfaces to instrument applications, such as reading from the `/proc` filesystem, loading _eBPF_ programs, and managing network interface filters. Many of these operations require elevated permissions due to their nature. The simplest solution is to run Beyla as `root`, which gives it all the permissions it needs. However, this might not work well in more complex setups where full `root` access isn’t ideal. To address this, Beyla is designed to use only the specific Linux kernel capabilities needed for its current configuration.

## Linux kernel capabilities

Linux kernel capabilities are a fine-grained system for controlling access to privileged operations on the system. They allow you to grant specific permissions to processes without giving them full root (superuser) access, which helps improve security by adhering to the principle of least privilege. Instead of relying on the traditional all-or-nothing root model, capabilities split the powerful privileges typically associated with root into smaller, more manageable units.

Each capability corresponds to a particular privileged operation in the kernel.

Capabilities are assigned to processes and executable files. By using tools like `setcap`, administrators can assign specific capabilities to a binary, enabling it to perform only the operations it needs without running as `root`. For example:

```bash
sudo setcap cap_net_admin,cap_net_raw+ep myprogram
```

This example grants the `CAP_NET_ADMIN` and `CAP_NET_RAW` capabilities to `myprogram`, allowing it to manage network settings without requiring full superuser privileges.

By choosing and assigning capabilities carefully, you can lower the risk of privilege escalation while still letting processes do what they need to.

## Beyla operation modes

Beyla can operate in two distinct modes: _application observability_ and _network observability_. These modes are not mutually exclusive and can be used together as needed. The former is typically enabled using the `BEYLA_OPEN_PORT` or `BEYLA_EXECUTABLE_NAME` options, while the latter is controlled via the `BEYLA_NETWORK_METRICS` option. For more details on enabling these modes, refer to the [configuration documentation](/docs/beyla/latest/configure/options/).

What Beyla requires in terms of capabilities depends entirely on the modes and features you enable. Conversely, the capabilities you provide determine what Beyla is able to do.

When starting up, Beyla reads its configuration and checks for the required capabilities. If any are missing, Beyla displays a warning like the following:

```
time=2025-01-27T17:21:20.197-06:00 level=WARN msg="Required system capabilities not present, Beyla may malfunction" error="the following capabilities are required: CAP_DAC_READ_SEARCH, CAP_BPF, CAP_CHECKPOINT_RESTORE"
```

Beyla then attempts to continue running, but missing capabilities may lead to errors later on.

To prevent this, you can set `BEYLA_ENFORCE_SYS_CAPS=1`, which causes Beyla to fail immediately if the required capabilities are not available. In this case, it terminates right after printing the warning message above.

## List of capabilities required by Beyla

Below is a list of capabilities and their usage in the context of Beyla

| Capability | Usage in Beyla |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `CAP_BPF` | enables general BPF functionality and `BPF_PROG_TYPE_SOCK_FILTER` programs |
| `CAP_NET_RAW` | used to create `AF_PACKET` raw sockets |
| `CAP_NET_ADMIN` | required to load `BPF_PROG_TYPE_SCHED_CLS` (tc) programs |
| `CAP_PERFMON` | direct packet access and pointer arithmetic and loading `BPF_PROG_TYPE_KPROBE` programs |
| `CAP_DAC_READ_SEARCH` | access to `/proc/self/mem` to determine kernel version |
| `CAP_CHECKPOINT_RESTORE` | access to symlinks in the `/proc` filesystem |
| `CAP_SYS_PTRACE` | access to `/proc/pid/exe` and friends |
| `CAP_SYS_RESOURCE` | _(kernels **< 5.11** only)_ increase the amount of locked memory available. |
| `CAP_SYS_ADMIN` | Library-level Go trace-context propagation via `bpf_probe_write_user()` and access to BTF data by the BPF metrics exporter |

## Examples

The final set of required capabilities depends on the actual Beyla configuration and the type of tracers being used, as described in the section __Beyla operation modes__ above. Here are a few examples of how to run Beyla as a non-root user.

### Network Metrics (using a socket filter)

#### Required capabilities:
* `CAP_BPF`
* `CAP_NET_RAW`

```
sudo setcap cap_bpf,cap_net_raw+ep ./bin/beyla
BEYLA_NETWORK_METRICS=1 BEYLA_NETWORK_PRINT_FLOWS=1 bin/beyla
```

### Network Metrics (using traffic control)

#### Required capabilities:
* `CAP_BPF`
* `CAP_NET_ADMIN`
* `CAP_PERFMON`

```
sudo setcap cap_bpf,cap_net_admin,cap_perfmon+ep ./bin/beyla
BEYLA_NETWORK_METRICS=1 BEYLA_NETWORK_PRINT_FLOWS=1 BEYLA_NETWORK_SOURCE=tc bin/beyla
```

### Application observability

#### Required capabilities:
* `CAP_BPF`
* `CAP_DAC_READ_SEARCH`
* `CAP_CHECKPOINT_RESTORE`
* `CAP_PERFMON`
* `CAP_NET_RAW`
* `CAP_SYS_PTRACE`

```
sudo setcap cap_bpf,cap_dac_read_search,cap_perfmon,cap_net_raw,cap_sys_ptrace+ep ./bin/beyla
BEYLA_OPEN_PORT=8080 BEYLA_TRACE_PRINTER=text bin/beyla
```

### Application observability with trace context propagation

#### Required capabilities:
* `CAP_BPF`
* `CAP_DAC_READ_SEARCH`
* `CAP_CHECKPOINT_RESTORE`
* `CAP_PERFMON`
* `CAP_NET_RAW`
* `CAP_SYS_PTRACE`
* `CAP_NET_ADMIN`

```
sudo setcap cap_bpf,cap_dac_read_search,cap_perfmon,cap_net_raw,cap_sys_ptrace,cap_net_admin+ep ./bin/beyla
BEYLA_BPF_ENABLE_CONTEXT_PROPAGATION=1 BEYLA_OPEN_PORT=8080 BEYLA_TRACE_PRINTER=text bin/beyla
```

## Internal eBPF tracer capability requirement reference

Below is a list of internal eBPF tracers used by Beyla and their required capabilities
### Socket flow fetcher
- `CAP_BPF` -> for `BPF_PROG_TYPE_SOCK_FILTER`
- `CAP_NET_RAW` -> for creating `AF_PACKET` socket

### Flow fetcher (tc)
- `CAP_BPF`
- `CAP_NET_ADMIN` -> for `PROG_TYPE_SCHED_CLS`
- `CAP_PERFMON` -> direct access to `struct __sk_buff::data` and pointer arithmetic

### Watcher
- `CAP_BPF`
- `CAP_CHECKPOINT_RESTORE`
- `CAP_DAC_READ_SEARCH` -> access to `/proc/self/mem` to determine kernel version
- `CAP_PERFMON` -> for `BPF_PROG_TYPE_KPROBE`

### Generic tracer
- `CAP_BPF`
- `CAP_DAC_READ_SEARCH`
- `CAP_CHECKPOINT_RESTORE`
- `CAP_PERFMON`
- `CAP_NET_RAW` -> for creating `AF_PACKET` socket used by `beyla_socket__http_filter`
- `CAP_SYS_PTRACE` -> access to `/proc/pid/exe` and other nodes in `/proc`

### TC tracers
* `CAP_BPF`
* `CAP_DAC_READ_SEARCH`
* `CAP_PERFMON`
* `CAP_NET_ADMIN` -> for `BPF_PROG_TYPE_SCHED_CLS`, `BPF_PROG_TYPE_SOCK_OPS` and `BPF_PROG_TYPE_SK_MSG`

### GO tracer
- `CAP_BPF`
- `CAP_DAC_READ_SEARCH`
- `CAP_CHECKPOINT_RESTORE`
- `CAP_PERFMON`
- `CAP_NET_RAW` -> for creating `AF_PACKET` socket used by `beyla_socket__http_filter`
- `CAP_SYS_PTRACE` -> access to `/proc/pid/exe` and other nodes in `/proc`
- `CAP_SYS_ADMIN` -> for probe based (`bpf_probe_write_user()`) library level context propagation



15 changes: 2 additions & 13 deletions docs/sources/setup/kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,24 +251,13 @@ In all of the examples so far, `privileged:true` or the `SYS_ADMIN` Linux capabi

The following guide is based on tests performed mainly by running `containerd` with `GKE`, `kubeadm`, `k3s`, `microk8s` and `kind`.

To run Beyla unprivileged, you need to run a `privileged` init container which performs setup tasks which require elevated privileges. Then you need to replace the `privileged:true` setting with a set of Linux [capabilities](https://www.man7.org/linux/man-pages/man7/capabilities.7.html).
To run Beyla unprivileged, you need to run a `privileged` init container which performs setup tasks which require elevated privileges. Then you need to replace the `privileged:true` setting with a set of Linux [capabilities](https://www.man7.org/linux/man-pages/man7/capabilities.7.html). A comprehensive list of capabilities required by Beyla can be found in [Security, permissions and capabilities]({{< relref "../security" >}}).

- `CAP_BPF` is required to install most of the eBPF probes, because Beyla tracks system calls.
- `CAP_SYS_PTRACE` is required so that Beyla is able to look into the processes namespaces and inspect the executables. Beyla doesn't use `ptrace`, but for some of the operations it does require this capability.
- `CAP_NET_RAW` is required for using installing socket filters, which are used as a fallback for `kretprobes` for HTTP requests.
- `CAP_CHECKPOINT_RESTORE` is required to open ELF files.
- `CAP_DAC_READ_SEARCH` is required to open ELF files.
- `CAP_PERFMON` is required to load BPF programs, i.e. be able to perform `perf_event_open()`.
- `CAP_SYS_RESOURCE` is required only on kernels **< 5.11** so that Beyla can increase the amount of locked memory available.

In addition to these Linux capabilities, many Kubernetes versions include [AppArmour](https://kubernetes.io/docs/tutorials/security/apparmor/), which tough policies adds additional restrictions to unprivileged containers. By [default](https://github.com/moby/moby/blob/master/profiles/apparmor/template.go), the AppArmour policy restricts the use of `mount` and the access to `/sys/fs/` directories. Beyla uses the BPF Linux file system to store pinned BPF maps, for communication among the different BPF programs. For this reason, Beyla either needs to `mount` a BPF file system, or write to `/sys/fs/bpf`, which are both restricted.
In addition to these Linux capabilities, many Kubernetes versions include [AppArmour](https://kubernetes.io/docs/tutorials/security/apparmor/), which tough policies adds additional restrictions to unprivileged containers. By [default](https://github.com/moby/moby/blob/master/profiles/apparmor/template.go), the AppArmour policy restricts the use of `mount` and the access to `/sys/fs/` directories.

Because of the AppArmour restriction, to run Beyla as unprivileged container, you need to either:

- Set `container.apparmor.security.beta.kubernetes.io/beyla: "unconfined"` in your Kubernetes deployment files.
- Set a modified AppArmour policy which allows Beyla to perform `mount`.

**Note** Since the `beyla` container does not have the privileges required to mount or un-mount the BPF filesystem, this sample leaves the BPF filesystem mounted on the host, even after the sample is deleted. This samples uses a unique path for each namespace to ensure re-use the same mount if Beyla is re-deployed, but to avoid collisions if multiple instances of Beyla is run in different namespaces.
**Note** Loading BPF programs requires that Beyla is able to read the Linux performance events, or at least be able to execute the Linux Kernel API `perf_event_open()`.

Expand Down

0 comments on commit 0b47d08

Please sign in to comment.