Files
akvorado/console/data/docs/02-configuration.md
2022-07-08 22:20:59 +02:00

448 lines
16 KiB
Markdown

# Configuration
The orchestrator service is configured through a YAML file and
includes the configuration of the other services. Other servcies are
expected to query the orchestrator through HTTP on start to retrieve
their configuration.
The default configuration can be obtained with `./akvorado
orchestrator --dump --check /dev/null`. Note that some sections are
generated from the configuration of another section. Notably, all
Kafka configuration comes from upper-level `kafka` key. Durations can
be written in seconds or using strings like `10h20m`.
It is also possible to override configuration settings using
environment variables. You need to remove any `-` from key names and
use `_` to handle nesting. Then, put `AKVORADO_ORCHESTRATOR_` as a
prefix. For example, let's consider the following configuration file:
```yaml
http:
listen: 127.0.0.1:8081
kafka:
topic: test-topic
brokers:
- 192.0.2.1:9092
- 192.0.2.2:9092
```
It can be translated to:
```sh
AKVORADO_ORCHESTRATOR_HTTP_LISTEN=127.0.0.1:8081
AKVORADO_ORCHESTRATOR_KAFKA_TOPIC=test-topic
AKVORADO_ORCHESTRATOR_KAFKA_BROKERS=192.0.2.1:9092,192.0.2.2:9092
```
The orchestrator service has its own configuration, as well as the
configuration for the other services under the key matching the
service name (`inlet` and `console`). For each service, it is possible
to provide a list of configuration. A service can query the
configuration it wants by appending an index to the configuration URL.
If the index does not match a provided configuration, the first
configuration is provided.
Each service is split into several functional components. Each of them
gets a section of the configuration file matching its name.
## Inlet service
This service is configured under the `inlet` key. The main components
of the inlet services are `flow`, `kafka`, and `core`.
### Flow
The flow component handles incoming flows. It only accepts the
`inputs` key to define the list of inputs to receive incoming flows.
Each input has a `type` and a `decoder`. For `decoder`, only `netflow`
is currently supported. As for the `type`, both `udp` and `file` are
supported.
For the UDP input, the supported keys are `listen` to set the
listening endpoint, `workers` to set the number of workers to listen
to the socket, `receive-buffer` to set the size of the kernel's
incoming buffer for each listening socket, and `queue-size` to define
the number of messages to buffer inside each worker. For example:
```yaml
flow:
inputs:
- type: udp
decoder: netflow
listen: 0.0.0.0:2055
workers: 3
workers: 2
```
The `file` input should only be used for testing. It supports a
`paths` key to define the files to read from. These files are injected
continuously in the pipeline. For example:
```yaml
flow:
inputs:
- type: file
decoder: netflow
paths:
- /tmp/flow1.raw
- /tmp/flow2.raw
workers: 2
```
Without configuration, *Akvorado* will listen for incoming
Netflow/IPFIX flows on a random port (check the logs to know which
one).
### Kafka
Received flows are exported to a Kafka topic using the [protocol
buffers format][]. The definition file is `flow/flow-*.proto`. Each
flow is written in the [length-delimited format][].
[protocol buffers format]: https://developers.google.com/protocol-buffers
[length-delimited format]: https://cwiki.apache.org/confluence/display/GEODE/Delimiting+Protobuf+Messages
The following keys are accepted:
- `topic`, `brokers` and `version` keys are described in the
configuration for the [inlet service](#kafka) (the values of these
keys come from the orchestrator configuration)
- `flush-interval` defines the maximum flush interval to send received
flows to Kafka
- `flush-bytes` defines the maximum number of bytes to store before
flushing flows to Kafka
- `max-message-bytes` defines the maximum size of a message (it should
be equal or smaller to the same setting in the broker configuration)
- `compression-codec` defines the compression codec to use to compress
messages (`none`, `gzip`, `snappy`, `lz4` and `zstd`)
- `queue-size` defines the size of the internal queues to send
messages to Kafka. Increasing this value will improve performance,
at the cost of losing messages in case of problems.
The topic name is suffixed by the version of the schema. For example,
if the configured topic is `flows` and the current schema version is
1, the topic used to send received flows will be `flows-v1`.
### Core
The core component queries the `geoip` and the `snmp` component to
hydrates the flows with additional information. It also classifies
exporters and interfaces into groups with a set of classification
rules.
The following configuration keys are accepted:
- `workers` key define how many workers should be spawned to process
incoming flows
- `exporter-classifiers` is a list of classifier rules to define a group
for exporters
- `interface-classifiers` is a list of classifier rules to define
connectivity type, network boundary and provider for an interface
- `classifier-cache-size` defines the size of the classifier cache. As
classifiers are pure, their result is cached in a cache. The metrics
should tell if the cache is big enough. It should be set at least to
twice the number of the most busy interfaces.
Classifier rules are written using [expr][].
Exporter classifiers gets the classifier IP address and its hostname.
If they can make a decision, they should invoke one of the
`Classify()` functions with the target group as an argument. Calling
this function makes the exporter part of the provided group. Evaluation
of rules stop on first match. The accessible variables and functions
are:
- `Exporter.IP` for the exporter IP address
- `Exporter.Name` for the exporter name
- `Classify()` to classify exporter to a group
Interface classifiers gets the following information and, like exporter
classifiers, should invoke one of the `Classify()` functions to make a
decision:
- `Exporter.IP` for the exporter IP address
- `Exporter.Name` for the exporter name
- `Interface.Name` for the interface name
- `Interface.Description` for the interface description
- `Interface.Speed` for the interface speed
- `ClassifyConnectivity()` to classify for a connectivity type (transit, PNI, PPNI, IX, customer, core, ...)
- `ClassifyProvider()` to classify for a provider (Cogent, Telia, ...)
- `ClassifyExternal()` to classify the interface as external
- `ClassifyInternal()` to classify the interface as internal
Once an interface is classified for a given criteria, it cannot be
changed by later rule. Once an interface is classified for all
criteria, remaining rules are skipped. Connectivity and provider are somewhat normalized (down case)
Each `Classify()` function, with the exception of `ClassifyExternal()`
and `ClassifyInternal()` have a variant ending with `Regex` which
takes a string and a regex before the original string and do a regex
match. The original string is expanded using the matching parts of the
regex. The syntax is the one [from Go][].
Here is an example:
```
Interface.Description startsWith "Transit:" &&
ClassifyConnectivity("transit") &&
ClassifyExternal() &&
ClassifyProviderRegex(Interface.Description, "^Transit: ([^ ]+)", "$1")
```
[expr]: https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md
[from Go]: https://pkg.go.dev/regexp#Regexp.Expand
### GeoIP
The GeoIP component adds source and destination country, as well as
the AS number of the source and destination IP if they are not present
in the received flows. It needs two databases using the [MaxMind DB
file format][], one for AS numbers, one for countries. If no database
is provided, the component is inactive. It accepts the following keys:
- `asn-database` tells the path to the ASN database
- `country-database` tells the path to the country database
- `optional` makes the presence of the databases optional on start
(when not present on start, the component is just disabled)
[MaxMind DB file format]: https://maxmind.github.io/MaxMind-DB/
If the files are updated while *Akvorado* is running, they are
automatically refreshed.
### SNMP
Flows only include interface indexes. To associate them with an
interface name and description, SNMP is used to poll the exporter
sending each flows. A cache is maintained to avoid polling
continuously the exporters. The following keys are accepted:
- `cache-duration` tells how much time to keep data in the cache
- `cache-refresh` tells how much time to wait before updating an entry
by polling it
- `cache-check-interval` tells how often to check if cached data is
about to expire or need an update
- `cache-persist-file` tells where to store cached data on shutdown and
read them back on startup
- `default-community` tells which community to use when polling exporters
- `communities` is a map from a exporter IP address to the community to
use for a exporter, overriding the default value set above,
- `poller-retries` is the number of retries on unsuccessful SNMP requests.
- `poller-timeout` tells how much time should the poller wait for an answer.
- `workers` tell how many workers to spawn to handle SNMP polling.
As flows missing interface information are discarded, persisting the
cache is useful to quickly be able to handle incoming flows. By
default, no persistent cache is configured.
### HTTP
The builtin HTTP server serves various pages. Its configuration
supports only the `listen` key to specify the address and port to
listen. For example:
```yaml
http:
listen: 0.0.0.0:8000
```
### Reporting
Reporting encompasses logging and metrics. Currently, as *Akvorado* is
expected to be run inside Docker, logging is done on the standard
output and is not configurable. As for metrics, they are reported by
the HTTP component on the `/api/v0/inlet/metrics` endpoint and there is
nothing to configure either.
## Orchestrator service
The two main components of the orchestrator service are `clickhouse`
and `kafka`. It also uses the [HTTP](#http) and
[reporting](#reporting) component from the inlet service and accepts
the same configuration settings.
### Kafka
The Kafka component creates or updates the Kafka topic to receive
flows. It accepts the following keys:
- `brokers` specifies the list of brokers to use to bootstrap the
connection to the Kafka cluster
- `version` tells which minimal version of Kafka to expect
- `topic` defines the base topic name
- `topic-configuration` describes how the topic should be configured
The following keys are accepted for the topic configuration:
- `num-partitions` for the number of partitions
- `replication-factor` for the replication factor
- `config-entries` is a mapping from configuration names to their values
For example:
```yaml
kafka:
topic: test-topic
topic-configuration:
num-partitions: 1
replication-factor: 1
config-entries:
segment.bytes: 1073741824
retention.ms: 86400000
cleanup.policy: delete
```
Currently, the orchestrator service won't update the replication
factor. The configuration entries are kept in sync with the content of
the configuration file.
### ClickHouse
The ClickHouse component exposes some useful HTTP endpoints to
configure a ClickHouse database. It also provisions and keep
up-to-date a ClickHouse database. The following keys should be
provided:
- `servers` defines the list of ClickHouse servers to connect to
- `username` is the username to use for authentication
- `password` is the password to use for authentication
- `database` defines the database to use to create tables
- `resolutions` defines the various resolutions to keep data
- `networks` maps subnets to names (used as `SrcNetName` and `DstNetName`)
- `asns` maps AS number to names (overriding the builtin ones)
- `orchestrator-url` defines the URL of the orchestrator to be used
by Clickhouse (autodetection when not specified)
The `resolutions` setting contains a list of resolutions. Each
resolution has two keys: `interval` and `ttl`. The first one is the
consolidation interval. The second is how long to keep the data in the
database. If `ttl` is 0, then the data is kept forever. If `interval`
is 0, it applies to the raw data (the one in the `flows` table). For
each resolution, a materialized view `flows_XXXX` is created with the
specified interval. It should be noted that consolidated tables do not
contain information about source/destination IP addresses and ports.
Here is the default configuration:
```yaml
resolutions:
- interval: 0
ttl: 6h
- interval: 1m
ttl: 168h # 1 week
- interval: 5m
ttl: 2160h # 3 months
- interval: 1h
ttl: 8760h # 1 year
```
## Console service
The main components of the console service are `http`, `console`,
`authentication` and `database`. `http` accepts the [same
configuration](#http) as for the inlet service.
### Authentication
The console does not store user identities and is unable to
authenticate them. It expects an authenticating proxy will add some
headers to the API endpoints:
- `Remote-User` is the user login,
- `Remote-Name` is the user display name,
- `Remote-Email` is the user email address,
- `X-Logout-URL` is a link to the logout link.
Only the first header is mandatory. The name of the headers can be
changed by providing a different mapping under the `headers` key. It
is also possible to modify the default user (when no header is
present) by tweaking the `default-user` key:
```yaml
authentication:
headers:
login: Remote-User
name: Remote-Name
email: Remote-Email
logout-url: X-Logout-URL
default-user:
login: default
name: Default User
```
To prevent access when not authenticated, the `login` field for the
`default-user` key should be empty.
There are several systems providing user management with all the bells
and whistles, including OAuth2 support, multi-factor authentication
and API tokens. Here is a short selection of solutions able to act as
an authenticating reverse-proxy for Akvorado:
- [Authelia](https://www.authelia.com/)
- [Authentik](https://goauthentik.io/)
- [Gluu](https://gluu.org/)
- [Keycloak](https://www.keycloak.org/)
- [Ory](https://www.ory.sh/), notably Kratos, Hydra and Oathkeeper
There also exist simpler solutions only providing authentication:
- [OAuth2 Proxy](https://oauth2-proxy.github.io/oauth2-proxy/), associated with [Dex](https://dexidp.io/)
- [Ory](https://www.ory.sh), notably Hydra and Oathkeeper
### Database
The console stores some data, like per-user filters, into a relational
database. When the database is not configured, data is only stored in
memory and will be lost on restart. Currently, the only accepted
driver is SQLite.
```yaml
database:
driver: sqlite
dsn: /var/lib/akvorado/console.sqlite
```
## Fake exporter service
For testing purpose, it is possible to generate flows using the fake
exporter service. It features a NetFlow generate and a simple SNMP
agent.
```yaml
snmp:
name: exporter1.example.com
interfaces:
10: "Transit: Telia"
11: "IX: AMSIX"
20: "core"
21: "core"
listen: 0.0.0.0:161
flows:
samplingrate: 50000
target: 127.0.0.1:2055
flows:
- per-second: 0.2
in-if-index: 10
out-if-index: 20
peak-hour: 16h
multiplier: 3
src-port: 0
dst-port: 80
protocol: tcp
size: 1300
dst-net: 192.0.2.0/24
dst-as: 64501
src-net: 198.38.120.0/23
src-as: 2906
```
In the `snmp` section, all fields are mandatory. The `interfaces`
section maps interface indexes to their descriptions. In the `flows`
section, all fields are mandatory. Have a look at the provided
`akvorado.yaml` configuration file for a more complete example. As
generating many flows is quite verbose, it may be useful to rely on
[YAML anchors][] to avoid repeating a lot of stuff.
[YAML anchors]: https://www.linode.com/docs/guides/yaml-anchors-aliases-overrides-extensions/