Compare commits

..

10 commits

Author SHA1 Message Date
02d4b5ab13 fix 2023-10-09 21:27:12 +02:00
d5ccea6fc3 set version persistent 2023-10-09 20:06:18 +02:00
Francesco Cogno
2d82a9c06c
Issue/105 (#106)
* fixed tests

* updated lock
2022-11-21 10:28:17 +01:00
Francesco Cogno
56290d6801
Fix semver error from prometheus_exporter_base (#104)
* Fixed semver error

* updated README
2022-11-21 09:46:12 +01:00
Francesco Cogno
a21dc2852e
Rust to latest in Dockerfile 2022-11-20 16:23:15 +01:00
Francesco Cogno
9f0eb7f050
Issue/100 (#101)
* Updating clap

* completed clap ugprade

* Upgraded other deps

* removed unused use

* fixed tests

* exported delay

* fixed multiple params

* added actual calculation
2022-11-20 16:13:06 +01:00
Tim Meusel
8f586ed65b
Document systemd unit for normal users (#97) 2022-11-20 09:24:02 +01:00
Marcel
f0c7a8fbfc
Added GitHub Actions to automatic publish binaries for various architectures (#95)
* Create ci.yaml

* Update ci.yaml

* Update ci.yaml

* Update ci.yaml

* Update config.toml

* Update ci.yaml

* Update ci.yaml

* Update ci.yaml

* Update ci.yaml

* Delete release-binaries.yml

* Update ci.yaml

* Update ci.yaml
2022-05-09 12:05:46 +02:00
Francesco Cogno
f8222bc5ab
version bump 2022-03-29 10:26:26 +02:00
Francesco Cogno
eb7455fa85
Clarify option behavior (#93)
* version bump, README fix

* Fixed "important" sign
2022-03-29 10:23:40 +02:00
11 changed files with 547 additions and 601 deletions

View file

@ -23,6 +23,3 @@ linker = "s390x-linux-musl-gcc"
[target.riscv64gc-unknown-linux-musl]
linker = "riscv64-linux-musl-gcc"
[target.x86_64-unknown-freebsd]
image = "docker.io/rustembedded/cross:x86_64-unknown-freebsd"

58
.github/workflows/ci.yaml vendored Normal file
View file

@ -0,0 +1,58 @@
name: CI
on:
push:
branches: [ master ]
tags: [ '*' ]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
channel: [stable]
target:
# https://doc.rust-lang.org/nightly/rustc/platform-support.html
- x86_64-unknown-linux-gnu
- aarch64-unknown-linux-gnu
- armv7-unknown-linux-gnueabihf # rpi
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-musl
- armv7-unknown-linux-musleabihf # rpi
- x86_64-unknown-freebsd
# - aarch64-unknown-freebsd <- std not precompiled
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.channel }}
target: ${{ matrix.target }}
override: true
- run: cargo install --git https://github.com/cross-rs/cross.git # cross in crates.io is too old
- name: Build
continue-on-error: ${{ matrix.channel != 'stable' }}
run: cross build --release --target ${{ matrix.target }}
- name: Rename binary
run: mv target/${{ matrix.target }}/release/prometheus_wireguard_exporter prometheus_wireguard_exporter_${{ matrix.target }}
- uses: actions/upload-artifact@v2
if: ${{ matrix.channel == 'stable' }}
with:
name: prometheus_wireguard_exporter_${{ matrix.target }}
path: prometheus_wireguard_exporter_${{ matrix.target }}
- uses: alexellis/upload-assets@0.3.0
if: startsWith(github.ref, 'refs/tags/')
env:
GITHUB_TOKEN: ${{ github.token }}
with:
asset_paths: '["prometheus_wireguard_exporter_${{ matrix.target }}"]'

View file

@ -1,188 +0,0 @@
name: Deploy binaries and create release
on:
release:
types:
- published
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
github_build:
name: Build release binaries
strategy:
fail-fast: true
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
name: prometheus_wireguard_exporter-x86_64-unknown-linux-gnu
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
name: prometheus_wireguard_exporter-x86_64-unknown-linux-musl
- target: i686-unknown-linux-musl
os: ubuntu-latest
name: prometheus_wireguard_exporter-i686-unknown-linux-musl
- target: aarch64-unknown-linux-musl
os: ubuntu-latest
name: prometheus_wireguard_exporter-aarch64-unknown-linux-musl
- target: arm-unknown-linux-musleabi
os: ubuntu-latest
name: prometheus_wireguard_exporter-arm-unknown-linux-musleabi
# - target: armv7-unknown-linux-musleabi
# os: ubuntu-latest
# name: prometheus_wireguard_exporter-armv7-unknown-linux-musleabi
- target: x86_64-apple-darwin
os: macOS-latest
name: prometheus_wireguard_exporter-x86_64-apple-darwin
# - target: aarch64-apple-darwin
# os: macOS-latest
# name: prometheus_wireguard_exporter-aarch64-apple-darwin
- target: x86_64-pc-windows-msvc
os: windows-latest
name: prometheus_wireguard_exporter-x86_64-pc-windows-msvc.exe
- target: i686-pc-windows-msvc
os: windows-latest
name: prometheus_wireguard_exporter-i686-pc-windows-msvc.exe
# - target: aarch64-pc-windows-msvc
# os: windows-latest
# name: prometheus_wireguard_exporter-aarch64-pc-windows-msvc.exe
- target: x86_64-unknown-freebsd
os: ubuntu-latest
name: prometheus_wireguard_exporter-x86_64-unknown-freebsd
runs-on: ${{ matrix.os }}
continue-on-error: false
steps:
- name: Setup | Checkout
uses: actions/checkout@v2.3.4
- name: Setup | Cache Cargo
uses: actions/cache@v2.1.6
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Setup | Rust
uses: actions-rs/toolchain@v1.0.7
with:
toolchain: stable
override: true
profile: minimal
target: ${{ matrix.target }}
- name: Build | Ubuntu
if: matrix.os != 'macOS-latest'
uses: actions-rs/cargo@v1.0.3
with:
command: build
args: --release --locked --target ${{ matrix.target }}
use-cross: ${{ matrix.os == 'ubuntu-latest' }}
- name: Build | macOS
if: matrix.os == 'macOS-latest'
uses: actions-rs/cargo@v1.0.3
with:
command: build
args: --release --locked --target ${{ matrix.target }}
- name: Post Build | Prepare artifacts [Windows]
if: matrix.os == 'windows-latest'
run: |
cd target/${{ matrix.target }}/release
strip prometheus_wireguard_exporter.exe
mv prometheus_wireguard_exporter.exe ../../../${{ matrix.name }}
cd -
- name: Post Build | Prepare artifacts [-nix]
if: matrix.os != 'windows-latest'
run: |
cd target/${{ matrix.target }}/release
strip prometheus_wireguard_exporter || true
mv prometheus_wireguard_exporter ../../../${{ matrix.name }}
cd -
- name: Display structure of downloaded files
run: ls -R
- name: Deploy | Upload artifacts
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.name }}
path: ${{ matrix.name }}
# Create GitHub release with Rust build targets and release notes
github_release:
name: Create GitHub Release
needs: github_build
runs-on: ubuntu-latest
steps:
- name: Setup | Checkout
uses: actions/checkout@v2.3.4
with:
fetch-depth: 0
- name: Setup | Go
uses: actions/setup-go@v2
with:
go-version: "^1.15.7"
- name: Setup | Download Artifacts
uses: actions/download-artifact@v2
- name: Display structure of downloaded files
run: ls -R
- name: Setup | Create Checksum files
run: |
for DIR in prometheus_wireguard_exporter-*
do
pushd "$DIR" || continue
FILE="$(echo prometheus_wireguard_exporter-*)"
sha256sum "$FILE" > "$FILE.sha256"
popd || exit
done
# - name: Setup | Release notes
# run: |
# GO111MODULE=on go get github.com/git-chglog/git-chglog/cmd/git-chglog@0.14.2
# git-chglog -c .github/chglog/release.yml $(git describe --tags) > RELEASE.md
- name: Build | Publish binaries
uses: alexellis/upload-assets@0.3.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
asset_paths: '["prometheus_wireguard_exporter-*/prometheus_wireguard_exporter-*"]'
# Publish prometheus_wireguard_exporter to Crates.io
# cargo_publish:
# name: Publish Cargo Package
# runs-on: ubuntu-latest
# needs: github_release
# steps:
# - name: Setup | Checkout
# uses: actions/checkout@v2.3.4
# - name: Setup | Rust
# uses: actions-rs/toolchain@v1.0.7
# with:
# toolchain: stable
# profile: minimal
# override: true
# - name: Build | Publish
# run: cargo publish --token ${{ secrets.CRATES_IO_TOKEN }}

566
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[package]
name = "prometheus_wireguard_exporter"
version = "3.6.2"
version = "3.6.6"
authors = ["Francesco Cogno <francesco.cogno@outlook.com>"]
description = "Prometheus WireGuard Exporter"
edition = "2018"
@ -19,18 +19,18 @@ default = []
leaky_log = []
[dependencies]
log = "0.4.14"
env_logger = "0.9.0"
clap = { version = "3.1.0", features = ["cargo", "env"] }
serde_json = "1.0"
serde = "1.0"
thiserror = "1.0"
anyhow = "1.0"
hyper = { version = "0.14", features = ["stream"] }
http = "0.2"
tokio = { version = "1.0", features = ["macros", "rt"] }
prometheus_exporter_base = { version = "1.3", features = ["hyper_server"] }
regex = "1.5.4"
log = "0.4.17"
env_logger = "0.9.3"
clap = { version = "4.0.26", features = ["cargo", "env"] }
serde_json = "1.0.88"
serde = "1.0.147"
thiserror = "1.0.37"
anyhow = "1.0.66"
hyper = { version = "0.14.23", features = ["stream"] }
http = "0.2.8"
tokio = { version = "1.22.0", features = ["macros", "rt"] }
prometheus_exporter_base = { version = "1.3.0", features = ["hyper_server"] }
regex = "1.7.0"
[dev-dependencies]
clippy = "0.0"
clippy = "0.0.302"

View file

@ -1,7 +1,7 @@
ARG BUILDPLATFORM=linux/amd64
ARG ALPINE_VERSION=3.14
ARG RUST_VERSION=1-slim-bullseye
ARG RUST_VERSION=1.69-bullseye
FROM --platform=${BUILDPLATFORM} rust:${RUST_VERSION} AS base
WORKDIR /usr/src/prometheus_wireguard_exporter
@ -129,6 +129,7 @@ RUN adduser prometheus-wireguard-exporter -s /bin/sh -D -u 1000 1000 && \
chmod 0440 /etc/sudoers.d/prometheus-wireguard-exporter
RUN apk add --update -q --no-cache wireguard-tools-wg sudo
USER prometheus-wireguard-exporter
#USER root
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/prometheus_wireguard_exporter"]
CMD [ "-a" ]
COPY --from=build --chown=prometheus-wireguard-exporter /tmp/binary ./prometheus_wireguard_exporter

View file

@ -4,11 +4,11 @@
[![Crate](https://img.shields.io/crates/v/prometheus_wireguard_exporter.svg)](https://crates.io/crates/prometheus_wireguard_exporter) [![cratedown](https://img.shields.io/crates/d/prometheus_wireguard_exporter.svg)](https://crates.io/crates/prometheus_wireguard_exporter) [![cratelastdown](https://img.shields.io/crates/dv/prometheus_wireguard_exporter.svg)](https://crates.io/crates/prometheus_wireguard_exporter)
[![release](https://img.shields.io/github/release/MindFlavor/prometheus_wireguard_exporter.svg)](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.6.2)
[![tag](https://img.shields.io/github/tag/mindflavor/prometheus_wireguard_exporter.svg)](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.6.2)
[![release](https://img.shields.io/github/release/MindFlavor/prometheus_wireguard_exporter.svg)](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.6.6)
[![tag](https://img.shields.io/github/tag/mindflavor/prometheus_wireguard_exporter.svg)](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.6.6)
[![Rust build](https://github.com/mindflavor/prometheus_wireguard_exporter/workflows/Rust/badge.svg)](https://github.com/mindflavor/prometheus_wireguard_exporter/actions?query=workflow%3ARust)
[![commitssince](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.6.2)](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.6.2)
[![commitssince](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.6.6)](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.6.6)
[![Docker build](https://github.com/MindFlavor/prometheus_wireguard_exporter/actions/workflows/docker.yml/badge.svg)](https://github.com/qdm12/godevcontainer/actions/workflows/docker.yml)
@ -22,6 +22,8 @@ A Prometheus exporter for [WireGuard](https://www.wireguard.com), written in Rus
## Changelog
* From release [3.6.4](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.6.4) the exporter optionally calculates the delta, in seconds, since the last handshake. The metric is `wireguard_latest_handshake_delay_seconds`. Thanks to [mmahacek](https://github.com/mmahacek) for the [idea](https://github.com/MindFlavor/prometheus_wireguard_exporter/issues/100).
* From release [3.6.3](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.6.3) the exporter automatically parses the systemd-networkd's peer syntax too (`[WireGuardPeer]` rather than `[Peer]`). Thanks to [mbonino](https://github.com/mbonino) for the PR (see https://github.com/MindFlavor/prometheus_wireguard_exporter/pull/92).
* From release [3.6.1](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.6.1) the exporter correctly escapes the double quotes in `friendly_name`. Thanks to [Steven Wood](https://github.com/stvnw) for finding the bug in #82.
* **BREAKING** From version `3.6.0` the exporter takes fallback configuration values from the environment variables. Thanks to [j_r0dd](https://github.com/jr0dd) for the idea. This changes how the exporter evaluates the command line parameters: make sure to consult the documentation on how to convert your command line to the new format. Basically every switch (for example verbose `-v`) not expect values, either `true` or `false`. This is necessary because there is no way to discriminate between an empty environment variable and one that has not been set.
* From release [3.5.1](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.5.1) the exporter supports multiple peer files. Thanks to [Tobias Krischer](https://github.com/tobikris) for the idea.
@ -104,7 +106,15 @@ docker build -t mindflavor/prometheus_wireguard_exporter https://github.com/Mind
### Flags available
Start the binary with `-h` to get the complete syntax. The parameters are:
Start the binary with `-h` to get the complete syntax. The parameters are below.
❗**Important** ❗: since 3.6.0, every parameter requires a value. In other words, even the `-v` (verbose) parameter requires `true` or `false` after it. Passing a parameter without value (for example `-v`) is the same of not passing the parameter at all: the default value will be used instead (in the case of the verbose option, it means `false`).
For example, if you want to enable the verbose mode and enable the *prepend sudo* option you would use the following command line:
```bash
prometheus_wireguard_exporter -a true -v true <...>
```
| Parameter | Env | Mandatory | Valid values | Default | Accepts multiple occurrences? | Description |
| -- | -- | -- | -- | -- | -- | -- |
@ -116,6 +126,7 @@ Start the binary with `-h` to get the complete syntax. The parameters are:
| `-s` | `PROMETHEUS_WIREGUARD_EXPORTER_SEPARATE_ALLOWED_IPS_ENABLED` | No | `true` or `false` | `false` | No | Enable the allowed ip + subnet split mode for the labels.
| `-r` | `PROMETHEUS_WIREGUARD_EXPORTER_EXPORT_REMOTE_IP_AND_PORT_ENABLED` | No | `true` or `false` | `false` | No | Exports peer's remote ip and port as labels (if available).
| `-i` | `PROMETHEUS_WIREGUARD_EXPORTER_INTERFACES` | No | Your interface name(s) | `all` | Yes | Specifies the interface(s) passed to the `wg show <interface> dump` parameter. Multiple parameters are allowed.
| `-d` | `EXPORT_LATEST_HANDSHAKE_DELAY` | No | `true` or `false` | `false` | No | Adds the `wireguard_latest_handshake_delay_seconds` metric that automatically calculates the seconds passed since the last handshake.
Keep in mind that command line values take precedence over environment variables.
@ -253,7 +264,7 @@ wireguard_latest_handshake_seconds{interface="wg0",public_key="wTjv6hS6fKfNK+SzO
### Systemd service file
Now add the exporter to the Prometheus exporters as usual. I recommend to start it as a service. It's necessary to run it as root (if there is a non-root way to call `wg show all dump` please let me know). My systemd service file is like this one:
Now add the exporter to the Prometheus exporters as usual. I recommend to start it as a service. It's necessary to run it as root or configure a sudo rule (if there is a non-root way to call `wg show all dump` please let me know). My systemd service file is like this one:
```ini
[Unit]
@ -271,6 +282,46 @@ ExecStart=/usr/local/bin/prometheus_wireguard_exporter -n /etc/wireguard/peers.c
WantedBy=multi-user.target
```
Running it as normal user + hardening:
```ini
[Unit]
Description=Prometheus WireGuard Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=wireguard_exporter
Group=wireguard_exporter
Type=simple
Restart=on-failure
EnvironmentFile=-/etc/conf.d/prometheus-wireguard-exporter
ExecStart=/usr/local/bin/prometheus-wireguard-exporter $WIREGUARD_EXPORTER_ARGS
PrivateTmp=yes
ProtectHome=yes
ProtectControlGroups=yes
UMask=077
RemoveIPC=yes
BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout
ProtectSystem=strict
ProtectProc=noaccess
[Install]
WantedBy=multi-user.target
```
Most of the other systemd hardening options won't work because they block sudo. With the above unit, you can use the following sudo rule:
```
wireguard_exporter ALL=(root) NOPASSWD: /usr/bin/wg
```
If you're interested in more hardening, you can analyze the unit with:
```
systemd-analyze security prometheus-wireguard-exporter.service
```
## Development
### Locally

View file

@ -1,8 +1,8 @@
use anyhow::Context;
//extern crate serde_json;
use clap::{crate_authors, crate_name, crate_version, Arg};
use clap::{crate_authors, crate_name, crate_version, value_parser, Arg};
use hyper::{Body, Request};
use log::{debug, info, trace};
use prometheus_exporter_base::prelude::{Authorization, ServerOptions};
use std::env;
mod options;
use options::Options;
@ -105,11 +105,7 @@ async fn perform_request(
}
if let Some(wg_accumulator) = wg_accumulator {
Ok(wg_accumulator.render_with_names(
peer_entry_hashmap.as_ref(),
options.separate_allowed_ips,
options.export_remote_ip_and_port,
))
Ok(wg_accumulator.render_with_names(peer_entry_hashmap.as_ref(), &options))
} else {
panic!();
}
@ -125,74 +121,81 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
.short('l')
.long("address")
.env("PROMETHEUS_WIREGUARD_EXPORTER_ADDRESS")
.value_parser(value_parser!(IpAddr))
.help("exporter address")
.default_value("0.0.0.0")
.takes_value(true),
)
.arg(
Arg::new("port")
.short('p')
.long("port")
.env("PROMETHEUS_WIREGUARD_EXPORTER_PORT")
.value_parser(value_parser!(u16))
.help("exporter port")
.default_value("9586")
.takes_value(true),
)
.arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.env("PROMETHEUS_WIREGUARD_EXPORTER_VERBOSE_ENABLED")
.value_parser(value_parser!(bool))
.help("verbose logging")
.default_value("false")
.takes_value(true),
)
.arg(
Arg::new("prepend_sudo")
.short('a')
.long("prepend_sudo")
.env("PROMETHEUS_WIREGUARD_EXPORTER_PREPEND_SUDO_ENABLED")
.value_parser(value_parser!(bool))
.help("Prepend sudo to the wg show commands")
.default_value("false")
.takes_value(true),
)
.arg(
Arg::new("separate_allowed_ips")
.short('s')
.long("separate_allowed_ips")
.env("PROMETHEUS_WIREGUARD_EXPORTER_SEPARATE_ALLOWED_IPS_ENABLED")
.value_parser(value_parser!(bool))
.help("separate allowed ips and ports")
.default_value("false")
.takes_value(true),
)
.arg(
Arg::new("export_remote_ip_and_port")
.short('r')
.long("export_remote_ip_and_port")
.env("PROMETHEUS_WIREGUARD_EXPORTER_EXPORT_REMOTE_IP_AND_PORT_ENABLED")
.value_parser(value_parser!(bool))
.help("exports peer's remote ip and port as labels (if available)")
.default_value("false")
.takes_value(true),
)
.arg(
Arg::new("extract_names_config_files")
.short('n')
.long("extract_names_config_files")
.num_args(0..)
.env("PROMETHEUS_WIREGUARD_EXPORTER_CONFIG_FILE_NAMES")
.help("If set, the exporter will look in the specified WireGuard config file for peer names (must be in [Peer] definition and be a comment). Multiple files are supported.")
.multiple_values(true)
.use_value_delimiter(true)
.takes_value(true))
.use_value_delimiter(false))
.arg(
Arg::new("interfaces")
.short('i')
.long("interfaces")
.num_args(0..)
.env("PROMETHEUS_WIREGUARD_EXPORTER_INTERFACES")
.help("If set specifies the interface passed to the wg show command. It is relative to the same position config_file. In not specified, all will be passed.")
.multiple_values(true)
.use_value_delimiter(true)
.takes_value(true))
.get_matches();
.use_value_delimiter(false))
.arg(
Arg::new("export_latest_handshake_delay")
.short('d')
.long("export_latest_handshake_delay")
.env("EXPORT_LATEST_HANDSHAKE_DELAY")
.value_parser(value_parser!(bool))
.help("exports runtime calculated latest handshake delay")
.default_value("false")
)
.get_matches();
let options = Options::from_claps(&matches);
@ -216,14 +219,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
);
info!("using options: {:?}", options);
let bind = matches.value_of("port").unwrap();
let bind = bind.parse::<u16>().expect("port must be a valid number");
let ip = matches.value_of("addr").unwrap().parse::<IpAddr>().unwrap();
let addr = (ip, bind).into();
let bind: u16 = *matches.get_one("port").unwrap();
let ip: IpAddr = *matches.get_one("addr").unwrap();
let addr: std::net::SocketAddr = (ip, bind).into();
info!("starting exporter on http://{}/metrics", addr);
render_prometheus(addr, options, |request, options| {
let server_options = ServerOptions {
addr,
authorization: Authorization::None,
};
render_prometheus(server_options, options, |request, options| {
Box::pin(perform_request(request, options))
})
.await;

View file

@ -1,3 +1,5 @@
use clap::parser::ValuesRef;
#[derive(Debug, Clone)]
pub(crate) struct Options {
pub verbose: bool,
@ -6,49 +8,27 @@ pub(crate) struct Options {
pub extract_names_config_files: Option<Vec<String>>,
pub interfaces: Option<Vec<String>>,
pub export_remote_ip_and_port: bool,
pub export_latest_handshake_delay: bool,
}
impl Options {
pub fn from_claps(matches: &clap::ArgMatches) -> Options {
let options = Options {
verbose: matches
.value_of("verbose")
.map(|e| {
e.to_lowercase()
.parse()
.expect("cannot parse verbose as a bool")
})
.unwrap_or_default(),
prepend_sudo: matches
.value_of("prepend_sudo")
.map(|e| {
e.to_lowercase()
.parse()
.expect("cannot parse prepend_sudo as a bool")
})
.unwrap_or_default(),
separate_allowed_ips: matches
.value_of("separate_allowed_ips")
.map(|e| {
e.to_lowercase()
.parse()
.expect("cannot parse separate_allowed_ips as a bool")
})
.unwrap_or_default(),
verbose: *matches.get_one("verbose").unwrap_or(&false),
prepend_sudo: *matches.get_one("prepend_sudo").unwrap_or(&false),
separate_allowed_ips: *matches.get_one("separate_allowed_ips").unwrap_or(&false),
extract_names_config_files: matches
.values_of("extract_names_config_files")
.map(|e| e.into_iter().map(|e| e.to_owned()).collect()),
.get_many("extract_names_config_files")
.map(|e: ValuesRef<'_, String>| e.into_iter().map(|a| a.to_owned()).collect()),
interfaces: matches
.values_of("interfaces")
.map(|e| e.into_iter().map(|a| a.to_owned()).collect()),
export_remote_ip_and_port: matches
.value_of("export_remote_ip_and_port")
.map(|e| {
e.to_lowercase()
.parse()
.expect("cannot parse export_remote_ip_and_port as a bool")
})
.unwrap_or_default(),
.get_many("interfaces")
.map(|e: ValuesRef<'_, String>| e.into_iter().map(|a| a.to_string()).collect()),
export_remote_ip_and_port: *matches
.get_one("export_remote_ip_and_port")
.unwrap_or(&false),
export_latest_handshake_delay: *matches
.get_one("export_latest_handshake_delay")
.unwrap_or(&false),
};
options

View file

@ -1,4 +1,5 @@
use crate::exporter_error::ExporterError;
use crate::options::Options;
use crate::wireguard_config::PeerEntryHashMap;
use crate::FriendlyDescription;
use log::{debug, trace};
@ -8,6 +9,7 @@ use std::collections::HashMap;
use std::convert::TryFrom;
use std::fmt::Debug;
use std::net::SocketAddr;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
const EMPTY: &str = "(none)";
@ -34,6 +36,7 @@ impl From<&str> for SecureString {
}
}
#[allow(dead_code)]
#[derive(Default, Debug, Clone)]
pub(crate) struct LocalEndpoint {
pub public_key: String,
@ -51,6 +54,7 @@ pub(crate) struct RemoteEndpoint {
pub latest_handshake: u64,
pub sent_bytes: u128,
pub received_bytes: u128,
#[allow(dead_code)]
pub persistent_keepalive: bool,
}
@ -165,10 +169,12 @@ impl WireGuard {
pub(crate) fn render_with_names(
&self,
pehm: Option<&PeerEntryHashMap>,
split_allowed_ips: bool,
export_remote_ip_and_port: bool,
options: &Options,
) -> String {
debug!("WireGuard::render_with_names(self == {:?}, pehm == {:?}, split_allowed_ips == {:?}, export_remote_ip_and_port == {:?} called", self, pehm, split_allowed_ips,export_remote_ip_and_port);
debug!(
"WireGuard::render_with_names(self == {:?}, pehm == {:?}, options == {:?} called",
self, pehm, options
);
// these are the exported counters
let mut pc_sent_bytes_total = PrometheusMetric::build()
@ -184,8 +190,19 @@ impl WireGuard {
let mut pc_latest_handshake = PrometheusMetric::build()
.with_name("wireguard_latest_handshake_seconds")
.with_metric_type(MetricType::Gauge)
.with_help("Seconds from the last handshake")
.with_help("UNIX timestamp seconds of the last handshake")
.build();
let mut pc_latest_handshake_delay = if options.export_latest_handshake_delay {
Some(
PrometheusMetric::build()
.with_name("wireguard_latest_handshake_delay_seconds")
.with_metric_type(MetricType::Gauge)
.with_help("Seconds from the last handshake")
.build(),
)
} else {
None
};
// Here we make sure we process the interfaces in the
// lexicographical order.
@ -214,7 +231,7 @@ impl WireGuard {
let mut attributes: Vec<(&str, &str)> =
vec![("interface", interface), ("public_key", &ep.public_key)];
if split_allowed_ips {
if options.separate_allowed_ips {
let v_ip_and_subnet: Vec<(&str, &str)> = ep
.allowed_ips
.split(',')
@ -286,7 +303,7 @@ impl WireGuard {
}
}
if export_remote_ip_and_port {
if options.export_remote_ip_and_port {
if let Some(r_ip) = &ep.remote_ip {
attributes.push(("remote_ip", r_ip));
}
@ -304,6 +321,18 @@ impl WireGuard {
instance = instance.with_label(h, v);
}
pc_latest_handshake_delay
.as_mut()
.map(|pc_latest_handshake_delay| {
let earlier = UNIX_EPOCH + Duration::from_secs(ep.latest_handshake);
let delta = SystemTime::now()
.duration_since(earlier)
.expect("time went backwards");
pc_latest_handshake_delay.render_and_append_instance(
&instance.clone().with_value(delta.as_secs() as u128),
)
});
pc_sent_bytes_total
.render_and_append_instance(&instance.clone().with_value(ep.sent_bytes))
.render();
@ -320,10 +349,15 @@ impl WireGuard {
}
format!(
"{}\n{}\n{}",
"{}\n{}\n{}{}",
pc_sent_bytes_total.render(),
pc_received_bytes_total.render(),
pc_latest_handshake.render()
pc_latest_handshake.render(),
pc_latest_handshake_delay.map_or_else(
// this row adds pc_latest_handshake_delay only if configured
|| "".to_owned(),
|pc_latest_handshake_delay| format!("\n{}", pc_latest_handshake_delay.render())
)
)
}
}
@ -397,7 +431,17 @@ wg0\tsUsR6xufQQ8Tf0FuyY9tfEeYdhVMeFelr4ZMUrj+B0E=\t(none)\t10.211.123.128:51820\
let pe = PeerEntryHashMap::new();
let s = a.render_with_names(Some(&pe), true, true);
let options = Options {
verbose: true,
prepend_sudo: true,
separate_allowed_ips: true,
extract_names_config_files: None,
interfaces: None,
export_remote_ip_and_port: true,
export_latest_handshake_delay: false,
};
let s = a.render_with_names(Some(&pe), &options);
println!("{}", s);
let s_ok = "# HELP wireguard_sent_bytes_total Bytes sent to the peer
@ -440,7 +484,7 @@ wireguard_received_bytes_total{interface=\"wg0\",public_key=\"yjeBkrZqUThSSHySFz
wireguard_received_bytes_total{interface=\"wg0\",public_key=\"HtOSi37ALMnSkeAFqeWYZqlBnZqAJERhb5o/i3ZPEFI=\",remote_ip=\"10.211.123.127\",allowed_ip_0=\"10.90.0.17\",allowed_subnet_0=\"32\",remote_port=\"51820\"} 62592693520
wireguard_received_bytes_total{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0FuyY9tfEeYdhVMeFelr4ZMUrj+B0E=\",remote_ip=\"10.211.123.128\",allowed_ip_0=\"10.90.0.18\",allowed_subnet_0=\"32\",remote_port=\"51820\"} 75066288152
# HELP wireguard_latest_handshake_seconds Seconds from the last handshake
# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake
# TYPE wireguard_latest_handshake_seconds gauge
wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"923V/iAdcz8BcqB0Xo6pDJzARGBJCQ6fWe+peixQyB4=\",remote_ip=\"10.211.123.112\",allowed_ip_0=\"10.90.0.10\",allowed_subnet_0=\"32\",allowed_ip_1=\"10.0.1.0\",allowed_subnet_1=\"24\",remote_port=\"51820\"} 0
wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"9M1fhLa9sIlT39z+SI/0a5H3mNSHYmM+NGA6sirD2nU=\",remote_ip=\"10.211.123.113\",allowed_ip_0=\"10.90.0.3\",allowed_subnet_0=\"32\",allowed_ip_1=\"10.198.171.0\",allowed_subnet_1=\"24\",remote_port=\"51820\"} 0
@ -487,13 +531,24 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
#[test]
fn test_parse_and_serialize() {
let a = WireGuard::try_from(TEXT).unwrap();
let s = a.render_with_names(None, false, true);
let options = Options {
verbose: true,
prepend_sudo: true,
separate_allowed_ips: false,
extract_names_config_files: None,
interfaces: None,
export_remote_ip_and_port: true,
export_latest_handshake_delay: true,
};
let s = a.render_with_names(None, &options);
println!("{}", s);
}
#[test]
fn test_render_to_prometheus_simple() {
const REF : &str= "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"to_change\",remote_ip=\"remote_ip\",remote_port=\"100\"} 1000\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"to_change\",remote_ip=\"remote_ip\",remote_port=\"100\"} 5000\n\n# HELP wireguard_latest_handshake_seconds Seconds from the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"to_change\",remote_ip=\"remote_ip\",remote_port=\"100\"} 500\n";
const REF : &str= "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"to_change\",remote_ip=\"remote_ip\",remote_port=\"100\"} 1000\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"to_change\",remote_ip=\"remote_ip\",remote_port=\"100\"} 5000\n\n# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"to_change\",remote_ip=\"remote_ip\",remote_port=\"100\"} 500\n";
let re = Endpoint::Remote(RemoteEndpoint {
public_key: "test".to_owned(),
@ -509,11 +564,20 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
interfaces: HashMap::new(),
};
let mut v = Vec::new();
v.push(re);
let v = vec![re];
wg.interfaces.insert("Pippo".to_owned(), v);
let prometheus = wg.render_with_names(None, false, true);
let options = Options {
verbose: true,
prepend_sudo: true,
separate_allowed_ips: false,
extract_names_config_files: None,
interfaces: None,
export_remote_ip_and_port: true,
export_latest_handshake_delay: false,
};
let prometheus = wg.render_with_names(None, &options);
assert_eq!(prometheus, REF);
}
@ -522,13 +586,13 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
fn test_render_to_prometheus_complex() {
use crate::wireguard_config::PeerEntry;
const REF :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",remote_port=\"100\"} 14\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",remote_port=\"100\"} 1000000000\n\n# HELP wireguard_latest_handshake_seconds Seconds from the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",remote_port=\"100\"} 50\n";
const REF :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",remote_port=\"100\"} 14\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",remote_port=\"100\"} 1000000000\n\n# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",remote_port=\"100\"} 50\n";
const REF_SPLIT :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 14\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 1000000000\n\n# HELP wireguard_latest_handshake_seconds Seconds from the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 50\n";
const REF_SPLIT :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 14\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 1000000000\n\n# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 50\n";
const REF_SPLIT_NO_REMOTE :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 14\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 1000000000\n\n# HELP wireguard_latest_handshake_seconds Seconds from the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 50\n";
const REF_SPLIT_NO_REMOTE :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 14\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 1000000000\n\n# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 50\n";
const REF_JSON :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",remote_ip=\"remote_ip\",auth_date=\"1614869789\",first_name=\"Coordinator\",id=\"482217555\",last_name=\"DrProxy.me\",username=\"DrProxyMeCoordinator\",remote_port=\"100\"} 14\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",remote_ip=\"remote_ip\",auth_date=\"1614869789\",first_name=\"Coordinator\",id=\"482217555\",last_name=\"DrProxy.me\",username=\"DrProxyMeCoordinator\",remote_port=\"100\"} 1000000000\n\n# HELP wireguard_latest_handshake_seconds Seconds from the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",remote_ip=\"remote_ip\",auth_date=\"1614869789\",first_name=\"Coordinator\",id=\"482217555\",last_name=\"DrProxy.me\",username=\"DrProxyMeCoordinator\",remote_port=\"100\"} 50\n";
const REF_JSON :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",remote_ip=\"remote_ip\",auth_date=\"1614869789\",first_name=\"Coordinator\",id=\"482217555\",last_name=\"DrProxy.me\",username=\"DrProxyMeCoordinator\",remote_port=\"100\"} 14\n\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",remote_ip=\"remote_ip\",auth_date=\"1614869789\",first_name=\"Coordinator\",id=\"482217555\",last_name=\"DrProxy.me\",username=\"DrProxyMeCoordinator\",remote_port=\"100\"} 1000000000\n\n# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ips=\"10.0.0.2/32,fd86:ea04:::4/128\",remote_ip=\"remote_ip\",remote_port=\"100\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",allowed_ips=\"10.0.0.4/32,fd86:ea04:::4/128,192.168.0.0/16\",remote_ip=\"remote_ip\",auth_date=\"1614869789\",first_name=\"Coordinator\",id=\"482217555\",last_name=\"DrProxy.me\",username=\"DrProxyMeCoordinator\",remote_port=\"100\"} 50\n";
let re1 = Endpoint::Remote(RemoteEndpoint {
public_key: "test".to_owned(),
@ -555,9 +619,7 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
interfaces: HashMap::new(),
};
let mut v = Vec::new();
v.push(re1);
v.push(re2);
let v = vec![re1, re2];
wg.interfaces.insert("Pippo".to_owned(), v);
let mut pehm = PeerEntryHashMap::new();
@ -570,13 +632,27 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
};
pehm.insert(pe.public_key, pe.clone());
let prometheus = wg.render_with_names(Some(&pehm), false, true);
let mut options = Options {
verbose: true,
prepend_sudo: true,
separate_allowed_ips: false,
extract_names_config_files: None,
interfaces: None,
export_remote_ip_and_port: true,
export_latest_handshake_delay: false,
};
let prometheus = wg.render_with_names(Some(&pehm), &options);
assert_eq!(prometheus, REF);
let prometheus = wg.render_with_names(Some(&pehm), true, true);
options.separate_allowed_ips = true;
let prometheus = wg.render_with_names(Some(&pehm), &options);
assert_eq!(prometheus, REF_SPLIT);
let prometheus = wg.render_with_names(Some(&pehm), true, false);
options.export_remote_ip_and_port = false;
let prometheus = wg.render_with_names(Some(&pehm), &options);
assert_eq!(prometheus, REF_SPLIT_NO_REMOTE);
// second test
@ -604,7 +680,10 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
};
pehm.insert(pe.public_key, pe.clone());
let prometheus = wg.render_with_names(Some(&pehm), false, true);
options.separate_allowed_ips = false;
options.export_remote_ip_and_port = true;
let prometheus = wg.render_with_names(Some(&pehm), &options);
assert_eq!(prometheus, REF_JSON);
}
}

View file

@ -8,6 +8,7 @@ use std::convert::TryInto;
#[derive(Debug, Default, Clone)]
pub(crate) struct PeerEntry<'a> {
pub public_key: &'a str,
#[allow(dead_code)]
pub allowed_ips: &'a str,
pub friendly_description: Option<FriendlyDescription<'a>>,
}