# API user

Create the dedicated RouterOS user the collector logs in as, with the policy each command needs, and see what that policy lets it read.

Source: https://docs.jmrp.io/mikroscope/security/api-user/

The agent needs no RouterOS account. Three things on your host do: the collector's API tier, the
relay transport, and the router-log markers. Give them one dedicated user with `read` and `api`,
plus `test` if you use the relay.

## Required policies

| Used by                                                                          | Runs over the binary API                                                                                                                                                                                                                                             | Policy          |
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `forward`'s API tier                                                             | `/interface/monitor-traffic`, `/interface/print` (`name`, `default-name`, `type`, `comment`, `actual-mtu`), `/interface/list/member/print` (`list`, `interface`), `/interface/bridge/port/print` (`interface`, `bridge`), `/interface/print stats-detail`, `/interface/ethernet/print stats`, `/system/resource/print`, `/system/resource/cpu/print`, `/system/health/print`, `/ip/firewall/connection/print count-only`, and once per reboot `/log/print` (`topics`, `message`, the memory buffer) | `read,api`      |
| `record --log-markers`, `mark --log-markers`                                     | `/log/print` (`time`, `topics`, `message`)                                                                                                                                                                                                                           | `read,api`      |
| the relay transport (`--transport relay`, or `auto` when direct does not answer) | `/tool/fetch output=user` against the agent's address                                                                                                                                                                                                                | `read,api,test` |

`/tool fetch` and `/tool profile` both require the `test` policy ([verified](https://docs.jmrp.io/mikroscope/about/status/#verified-test-policy)).
mikroscope uses `/tool fetch` for the relay and does not use `/tool profile`.

`read,api` is enough for the API tier and for `--log-markers`. `test` is needed only when the relay
is used — `--transport relay`, or `auto` when the direct transport does not answer — whatever
`--api-mode` is. With `--api-mode off` the tier needs no user at all.

Not every call in the first row runs every time. `/system/health/print` is skipped in `slow` and
with `--no-health`; the conntrack `count-only` runs only when `--conntrack-every` is above 0, and
its default is 0 even in `full`; `monitor-traffic` runs only when `--interfaces` is set, while the three
configuration reads behind the interface inventory run whenever the tier is on, once before the
first kernel pull and again every `--labels-every`; the two stats reads follow `--counters-every`,
10 s by default. Which calls
run at which cadence is on [RouterOS API tier](https://docs.jmrp.io/mikroscope/sinks/api-tier/).

Without an address and a user, each command says so differently:

- `forward` runs the kernel tier alone. With an address that does not answer it logs
  `api tier: not connected yet, will keep trying: …` and keeps retrying.
- `mark --log-markers` and `--transport relay` fail with
  `the RouterOS API needs --api, --api-user and MIKROSCOPE_API_PASSWORD`.
- `record --log-markers` keeps the recording, prints `log markers: the RouterOS API needs …` on
  stderr and exits 0.
- `--transport auto`, when the direct transport does not answer, fails with
  ``direct transport did not answer and the relay is not configured: the RouterOS API needs … (or `install --expose`)``.

That check looks only at `--api` and `--api-user`. An empty `MIKROSCOPE_API_PASSWORD` is not caught
there; it shows up as a failed login, `api <address>: …`.

## Create the user

1. Create a group that grants `read`, `api` and `test` and denies by name every other policy
   [RouterOS defines](https://help.mikrotik.com/docs/spaces/ROS/pages/8978504/User):

   ```routeros
   /user/group/add name=mikroscope policy=read,api,test,!write,!ftp,!local,!telnet,!ssh,!reboot,!policy,!winbox,!password,!web,!sniff,!sensitive,!romon,!rest-api
   ```

   Drop `test` from the list if you will never use the relay.

2. Create the user in that group, restricted to the collector's address:

   ```routeros
   /user/add name=mikroscope group=mikroscope password=<generate> address=<collector host>/32
   ```

3. Restrict `/ip/service` for `api` to your LAN. With `address=` on the user, both are
   RouterOS-side limits on where the password is accepted from, and neither depends on mikroscope.

4. Pass the address, the user and the password to the CLI, as in
   [Pass the credentials](https://docs.jmrp.io/mikroscope/security/api-user/#how-the-cli-passes-it).

Make this user for mikroscope rather than reusing one made for another tool. A least-privilege API
user built for something else typically belongs to a group that denies `test`, so it cannot run the
relay, and widening that group widens it for the other tool as well.

## What read can see

`read` is not narrow. **Over the binary API, `/container/print` returns every property of every
container, `cmd` and `envlist` included, to a user with only `read,api`** ([verified](https://docs.jmrp.io/mikroscope/about/status/#verified-read-user-envlist)).
Whether it can also read the envlist entries' values in `/container/envs` is [not tested](https://docs.jmrp.io/mikroscope/about/status/#not-tested);
the design assumes this user can, and so treats the agent's `TOKEN` entry, when one is set, as
readable by it.

The collector narrows what it asks for where it reads configuration. The three interface-inventory reads
name their properties — `name`, `default-name`, `type`, `comment` and `actual-mtu`; `list` and
`interface`; `interface` and `bridge` — and no other field, so none of them brings back a field that
could carry a secret; `/system/resource`, `/system/resource/cpu`, `/system/health` and `/log/print` carry
a `.proplist` as well. The counter reads — `monitor-traffic`, `stats`, `stats-detail` — and the
conntrack `count-only` do not. None of this limits what the user is allowed to request: it can
still ask for every container's properties.

## Pass the credentials

| Setting  | Flag         | Environment variable      |
| -------- | ------------ | ------------------------- |
| address  | `--api`      | `MIKROSCOPE_API_ADDR`     |
| user     | `--api-user` | `MIKROSCOPE_API_USER`     |
| password | none         | `MIKROSCOPE_API_PASSWORD` |

The password has no flag on purpose: a flag is visible in `ps` and in a shell history.
The repository's [`.env.example`](https://github.com/jmrplens/mikroscope/blob/main/.env.example) gives the address as `192.168.88.1:8728`.

> **The API connection is not encrypted**
>
> `record`, `mark` and `forward` connect to the plain binary API. The vendored client can dial TLS,
> but no flag uses it, so the login and every reply cross the network between the collector and the
> router unencrypted. `address=` limits where the login is accepted from; it does not change that.

## See also

- [Security model](https://docs.jmrp.io/mikroscope/security/): every piece, what it reaches and which credential it
  holds.
- [RouterOS API tier](https://docs.jmrp.io/mikroscope/sinks/api-tier/): what the collector reads over this user,
  and the `off`, `slow` and `full` presets.
- [Network access](https://docs.jmrp.io/mikroscope/install/reaching-the-agent/): the direct and relay transports,
  and when the relay needs `test`.
