Compare commits
10 commits
86cc251954
...
02d4b5ab13
Author | SHA1 | Date | |
---|---|---|---|
02d4b5ab13 | |||
d5ccea6fc3 | |||
|
2d82a9c06c | ||
|
56290d6801 | ||
|
a21dc2852e | ||
|
9f0eb7f050 | ||
|
8f586ed65b | ||
|
f0c7a8fbfc | ||
|
f8222bc5ab | ||
|
eb7455fa85 |
11 changed files with 547 additions and 601 deletions
|
@ -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
58
.github/workflows/ci.yaml
vendored
Normal 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 }}"]'
|
188
.github/workflows/release-binaries.yml
vendored
188
.github/workflows/release-binaries.yml
vendored
|
@ -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
566
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
28
Cargo.toml
28
Cargo.toml
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
61
README.md
61
README.md
|
@ -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
|
||||
|
|
57
src/main.rs
57
src/main.rs
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
131
src/wireguard.rs
131
src/wireguard.rs
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue