Compare commits
27 commits
Author | SHA1 | Date | |
---|---|---|---|
02d4b5ab13 | |||
d5ccea6fc3 | |||
|
2d82a9c06c | ||
|
56290d6801 | ||
|
a21dc2852e | ||
|
9f0eb7f050 | ||
|
8f586ed65b | ||
|
f0c7a8fbfc | ||
|
f8222bc5ab | ||
|
eb7455fa85 | ||
|
86cc251954 | ||
|
9206a4f595 | ||
|
61de41169b | ||
|
d987baf1f1 | ||
|
23298a72c4 | ||
|
72d3f7393e | ||
|
5b709b19f1 | ||
|
6222d71685 | ||
|
6678669dfb | ||
|
d8237c8b7c | ||
|
62fe64e1c0 | ||
|
638b9d1c33 | ||
|
5752476184 | ||
|
d18c045c98 | ||
|
2bc7ea9e06 | ||
|
8f44776745 | ||
|
45472a35b1 |
24 changed files with 1146 additions and 639 deletions
5
.devcontainer/.dockerignore
Normal file
5
.devcontainer/.dockerignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.dockerignore
|
||||||
|
devcontainer.json
|
||||||
|
docker-compose.yml
|
||||||
|
Dockerfile
|
||||||
|
README.md
|
1
.devcontainer/Dockerfile
Normal file
1
.devcontainer/Dockerfile
Normal file
|
@ -0,0 +1 @@
|
||||||
|
FROM qmcgaw/rustdevcontainer
|
70
.devcontainer/README.md
Normal file
70
.devcontainer/README.md
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
# Development container
|
||||||
|
|
||||||
|
Development container that can be used with VSCode.
|
||||||
|
|
||||||
|
It works on Linux, Windows and OSX.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [VS code](https://code.visualstudio.com/download) installed
|
||||||
|
- [VS code remote containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) installed
|
||||||
|
- [Docker](https://www.docker.com/products/docker-desktop) installed and running
|
||||||
|
- [Docker Compose](https://docs.docker.com/compose/install/) installed
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. Create the following files on your host if you don't have them:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
touch ~/.gitconfig ~/.zsh_history
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the development container will create the empty directories `~/.docker`, `~/.ssh` and `~/.kube` if you don't have them.
|
||||||
|
|
||||||
|
1. **For Docker on OSX or Windows without WSL**: ensure your home directory `~` is accessible by Docker.
|
||||||
|
1. **For Docker on Windows without WSL:** if you want to use SSH keys, bind mount your host `~/.ssh` to `/tmp/.ssh` instead of `~/.ssh` by changing the `volumes` section in the [docker-compose.yml](docker-compose.yml).
|
||||||
|
1. Open the command palette in Visual Studio Code (CTRL+SHIFT+P).
|
||||||
|
1. Select `Remote-Containers: Open Folder in Container...` and choose the project directory.
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
### Customize the image
|
||||||
|
|
||||||
|
You can make changes to the [Dockerfile](Dockerfile) and then rebuild the image. For example, your Dockerfile could be:
|
||||||
|
|
||||||
|
```Dockerfile
|
||||||
|
FROM qmcgaw/rustdevcontainer
|
||||||
|
RUN apk add curl
|
||||||
|
```
|
||||||
|
|
||||||
|
To rebuild the image, either:
|
||||||
|
|
||||||
|
- With VSCode through the command palette, select `Remote-Containers: Rebuild and reopen in container`
|
||||||
|
- With a terminal, go to this directory and `docker-compose build`
|
||||||
|
|
||||||
|
### Customize VS code settings
|
||||||
|
|
||||||
|
You can customize **settings** and **extensions** in the [devcontainer.json](devcontainer.json) definition file.
|
||||||
|
|
||||||
|
### Entrypoint script
|
||||||
|
|
||||||
|
You can bind mount a shell script to `/home/vscode/.welcome.sh` to replace the [current welcome script](shell/.welcome.sh).
|
||||||
|
|
||||||
|
### Publish a port
|
||||||
|
|
||||||
|
To access a port from your host to your development container, publish a port in [docker-compose.yml](docker-compose.yml). You can also now do it directly with VSCode without restarting the container.
|
||||||
|
|
||||||
|
### Run other services
|
||||||
|
|
||||||
|
1. Modify [docker-compose.yml](docker-compose.yml) to launch other services at the same time as this development container, such as a test database:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
database:
|
||||||
|
image: postgres
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: password
|
||||||
|
```
|
||||||
|
|
||||||
|
1. In [devcontainer.json](devcontainer.json), change the line `"runServices": ["vscode"],` to `"runServices": ["vscode", "database"],`.
|
||||||
|
1. In the VS code command palette, rebuild the container.
|
40
.devcontainer/devcontainer.json
Normal file
40
.devcontainer/devcontainer.json
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "prometheus_wireguard_exporter_dev",
|
||||||
|
"dockerComposeFile": ["docker-compose.yml"],
|
||||||
|
"service": "vscode",
|
||||||
|
"runServices": ["vscode"],
|
||||||
|
"shutdownAction": "stopCompose",
|
||||||
|
"postCreateCommand": "",
|
||||||
|
"workspaceFolder": "/workspace",
|
||||||
|
// "overrideCommand": "",
|
||||||
|
"extensions": [
|
||||||
|
"matklad.rust-analyzer",
|
||||||
|
"tamasfe.even-better-toml", // for Cargo.toml
|
||||||
|
"eamodio.gitlens", // IDE Git information
|
||||||
|
"davidanson.vscode-markdownlint",
|
||||||
|
"ms-azuretools.vscode-docker", // Docker integration and linting
|
||||||
|
"shardulm94.trailing-spaces", // Show trailing spaces
|
||||||
|
"Gruntfuggly.todo-tree", // Highlights TODO comments
|
||||||
|
"bierner.emojisense", // Emoji sense for markdown
|
||||||
|
"stkb.rewrap", // rewrap comments after n characters on one line
|
||||||
|
"vscode-icons-team.vscode-icons", // Better file extension icons
|
||||||
|
"github.vscode-pull-request-github", // Github interaction
|
||||||
|
"redhat.vscode-yaml", // Kubernetes, Drone syntax highlighting
|
||||||
|
"bajdzis.vscode-database", // Supports connections to mysql or postgres, over SSL, socked
|
||||||
|
"IBM.output-colorizer", // Colorize your output/test logs
|
||||||
|
// "mohsen1.prettify-json", // Prettify JSON data
|
||||||
|
// "zxh404.vscode-proto3", // Supports Proto syntax
|
||||||
|
// "jrebocho.vscode-random", // Generates random values
|
||||||
|
// "alefragnani.Bookmarks", // Manage bookmarks
|
||||||
|
// "quicktype.quicktype", // Paste JSON as code
|
||||||
|
// "spikespaz.vscode-smoothtype", // smooth cursor animation
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"files.eol": "\n",
|
||||||
|
"remote.extensionKind": {
|
||||||
|
"ms-azuretools.vscode-docker": "workspace"
|
||||||
|
},
|
||||||
|
"editor.codeActionsOnSaveTimeout": 3000,
|
||||||
|
"rust-analyzer.serverPath": "/usr/local/bin/rust-analyzer"
|
||||||
|
}
|
||||||
|
}
|
31
.devcontainer/docker-compose.yml
Normal file
31
.devcontainer/docker-compose.yml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
version: "3.7"
|
||||||
|
|
||||||
|
services:
|
||||||
|
vscode:
|
||||||
|
build: .
|
||||||
|
image: rustdevcontainer
|
||||||
|
volumes:
|
||||||
|
- ../:/workspace
|
||||||
|
# Docker
|
||||||
|
- ~/.docker:/root/.docker:z
|
||||||
|
# Docker socket to access Docker server
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
# SSH directory for Linux, OSX and WSL
|
||||||
|
- ~/.ssh:/root/.ssh:z
|
||||||
|
# For Windows without WSL, a copy will be made
|
||||||
|
# from /tmp/.ssh to ~/.ssh to fix permissions
|
||||||
|
# - ~/.ssh:/tmp/.ssh:ro
|
||||||
|
# Shell history persistence
|
||||||
|
- ~/.zsh_history:/root/.zsh_history:z
|
||||||
|
# Git config
|
||||||
|
- ~/.gitconfig:/root/.gitconfig:z
|
||||||
|
# Kubernetes
|
||||||
|
- ~/.kube:/root/.kube:z
|
||||||
|
environment:
|
||||||
|
- TZ=
|
||||||
|
# Needed for debugging
|
||||||
|
# cap_add:
|
||||||
|
# - SYS_PTRACE
|
||||||
|
# security_opt:
|
||||||
|
# - seccomp:unconfined
|
||||||
|
entrypoint: zsh -c "while sleep 1000; do :; done"
|
28
.github/workflows/build.yml
vendored
28
.github/workflows/build.yml
vendored
|
@ -1,28 +0,0 @@
|
||||||
name: Docker build
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [master]
|
|
||||||
paths-ignore:
|
|
||||||
- .github/workflows/buildx-branch.yml
|
|
||||||
- .github/workflows/buildx-latest.yml
|
|
||||||
- .github/workflows/buildx-release.yml
|
|
||||||
- .github/workflows/dockerhub-description.yml
|
|
||||||
- .github/workflows/rust.yml
|
|
||||||
- extra
|
|
||||||
- _config.yml
|
|
||||||
- .gitignore
|
|
||||||
- .rustfmt.toml
|
|
||||||
- .gitignore
|
|
||||||
- example.json
|
|
||||||
- LICENSE
|
|
||||||
- README.md
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
DOCKER_BUILDKIT: "1"
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
- name: Build image
|
|
||||||
run: docker build .
|
|
42
.github/workflows/buildx-branch.yml
vendored
42
.github/workflows/buildx-branch.yml
vendored
|
@ -1,42 +0,0 @@
|
||||||
name: Buildx branch
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- '*'
|
|
||||||
- '*/*'
|
|
||||||
- '!master'
|
|
||||||
paths-ignore:
|
|
||||||
- .github/workflows/build.yml
|
|
||||||
- .github/workflows/buildx-latest.yml
|
|
||||||
- .github/workflows/buildx-release.yml
|
|
||||||
- .github/workflows/dockerhub-description.yml
|
|
||||||
- .github/workflows/rust.yml
|
|
||||||
- extra
|
|
||||||
- _config.yml
|
|
||||||
- .gitignore
|
|
||||||
- .rustfmt.toml
|
|
||||||
- .gitignore
|
|
||||||
- example.json
|
|
||||||
- LICENSE
|
|
||||||
- README.md
|
|
||||||
jobs:
|
|
||||||
buildx:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Buildx setup
|
|
||||||
uses: crazy-max/ghaction-docker-buildx@v1
|
|
||||||
- name: Dockerhub login
|
|
||||||
run: echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login -u mindflavor --password-stdin 2>&1
|
|
||||||
- name: Run Buildx
|
|
||||||
run: |
|
|
||||||
docker buildx build \
|
|
||||||
--progress plain \
|
|
||||||
--platform=linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7 \
|
|
||||||
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
|
|
||||||
--build-arg COMMIT=`git rev-parse --short HEAD` \
|
|
||||||
--build-arg VERSION=${GITHUB_REF##*/} \
|
|
||||||
-t mindflavor/prometheus-wireguard-exporter:${GITHUB_REF##*/} \
|
|
||||||
--push \
|
|
||||||
.
|
|
||||||
- run: curl -X POST https://hooks.microbadger.com/images/mindflavor/prometheus-wireguard-exporter/TODO || exit 0
|
|
39
.github/workflows/buildx-latest.yml
vendored
39
.github/workflows/buildx-latest.yml
vendored
|
@ -1,39 +0,0 @@
|
||||||
name: Buildx latest
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
branches: [master]
|
|
||||||
paths-ignore:
|
|
||||||
- .github/workflows/build.yml
|
|
||||||
- .github/workflows/buildx-branch.yml
|
|
||||||
- .github/workflows/buildx-release.yml
|
|
||||||
- .github/workflows/dockerhub-description.yml
|
|
||||||
- .github/workflows/rust.yml
|
|
||||||
- extra
|
|
||||||
- _config.yml
|
|
||||||
- .gitignore
|
|
||||||
- .rustfmt.toml
|
|
||||||
- .gitignore
|
|
||||||
- example.json
|
|
||||||
- LICENSE
|
|
||||||
- README.md
|
|
||||||
jobs:
|
|
||||||
buildx:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Buildx setup
|
|
||||||
uses: crazy-max/ghaction-docker-buildx@v1
|
|
||||||
- name: Dockerhub login
|
|
||||||
run: echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login -u mindflavor --password-stdin 2>&1
|
|
||||||
- name: Run Buildx
|
|
||||||
run: |
|
|
||||||
docker buildx build \
|
|
||||||
--progress plain \
|
|
||||||
--platform=linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7 \
|
|
||||||
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
|
|
||||||
--build-arg COMMIT=`git rev-parse --short HEAD` \
|
|
||||||
--build-arg VERSION=latest \
|
|
||||||
-t mindflavor/prometheus-wireguard-exporter:latest \
|
|
||||||
--push \
|
|
||||||
.
|
|
||||||
- run: curl -X POST https://hooks.microbadger.com/images/mindflavor/prometheus-wireguard-exporter/TODO || exit 0
|
|
39
.github/workflows/buildx-release.yml
vendored
39
.github/workflows/buildx-release.yml
vendored
|
@ -1,39 +0,0 @@
|
||||||
name: Buildx release
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
paths-ignore:
|
|
||||||
- .github/workflows/build.yml
|
|
||||||
- .github/workflows/buildx-branch.yml
|
|
||||||
- .github/workflows/buildx-latest.yml
|
|
||||||
- .github/workflows/dockerhub-description.yml
|
|
||||||
- .github/workflows/rust.yml
|
|
||||||
- extra
|
|
||||||
- _config.yml
|
|
||||||
- .gitignore
|
|
||||||
- .rustfmt.toml
|
|
||||||
- .gitignore
|
|
||||||
- example.json
|
|
||||||
- LICENSE
|
|
||||||
- README.md
|
|
||||||
jobs:
|
|
||||||
buildx:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Buildx setup
|
|
||||||
uses: crazy-max/ghaction-docker-buildx@v1
|
|
||||||
- name: Dockerhub login
|
|
||||||
run: echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login -u mindflavor --password-stdin 2>&1
|
|
||||||
- name: Run Buildx
|
|
||||||
run: |
|
|
||||||
docker buildx build \
|
|
||||||
--progress plain \
|
|
||||||
--platform=linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7 \
|
|
||||||
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
|
|
||||||
--build-arg COMMIT=`git rev-parse --short HEAD` \
|
|
||||||
--build-arg VERSION=${GITHUB_REF##*/} \
|
|
||||||
-t mindflavor/prometheus-wireguard-exporter:${GITHUB_REF##*/} \
|
|
||||||
--push \
|
|
||||||
.
|
|
||||||
- run: curl -X POST https://hooks.microbadger.com/images/mindflavor/prometheus-wireguard-exporter/TODO || exit 0
|
|
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 }}"]'
|
84
.github/workflows/docker.yml
vendored
Normal file
84
.github/workflows/docker.yml
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
name: CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- .github/workflows/docker.yml
|
||||||
|
- src/**
|
||||||
|
- .dockerignore
|
||||||
|
- Cargo.lock
|
||||||
|
- Cargo.toml
|
||||||
|
- Dockerfile
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- .github/workflows/docker.yml
|
||||||
|
- src/**
|
||||||
|
- .dockerignore
|
||||||
|
- Cargo.lock
|
||||||
|
- Cargo.toml
|
||||||
|
- Dockerfile
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
verify:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
DOCKER_BUILDKIT: "1"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: docker build --target lint .
|
||||||
|
|
||||||
|
- name: Build test image
|
||||||
|
run: docker build --target test -t test-container .
|
||||||
|
|
||||||
|
- name: Run tests in test container
|
||||||
|
run: |
|
||||||
|
docker run --rm test-container
|
||||||
|
|
||||||
|
# We run this using the caching from the previous steps
|
||||||
|
- name: Build final image
|
||||||
|
run: docker build .
|
||||||
|
|
||||||
|
publish:
|
||||||
|
needs: [verify]
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
|
||||||
|
- uses: docker/setup-qemu-action@v1
|
||||||
|
- uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- uses: docker/login-action@v1.9.0
|
||||||
|
with:
|
||||||
|
username: mindflavor
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Set variables
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
BRANCH=${GITHUB_REF#refs/heads/}
|
||||||
|
TAG=${GITHUB_REF#refs/tags/}
|
||||||
|
echo ::set-output name=commit::$(git rev-parse --short HEAD)
|
||||||
|
echo ::set-output name=build_date::$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||||
|
if [ "$TAG" != "$GITHUB_REF" ]; then
|
||||||
|
echo ::set-output name=version::$TAG
|
||||||
|
echo ::set-output name=platforms::linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7
|
||||||
|
elif [ "$BRANCH" = "master" ]; then
|
||||||
|
echo ::set-output name=version::latest
|
||||||
|
echo ::set-output name=platforms::linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7
|
||||||
|
else
|
||||||
|
echo ::set-output name=version::$BRANCH
|
||||||
|
echo ::set-output name=platforms::linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build and push final image
|
||||||
|
uses: docker/build-push-action@v2.4.0
|
||||||
|
with:
|
||||||
|
platforms: ${{ steps.vars.outputs.platforms }}
|
||||||
|
build-args: |
|
||||||
|
BUILD_DATE=${{ steps.vars.outputs.build_date }}
|
||||||
|
COMMIT=${{ steps.vars.outputs.commit }}
|
||||||
|
VERSION=${{ steps.vars.outputs.version }}
|
||||||
|
tags: mindflavor/prometheus-wireguard-exporter:${{ steps.vars.outputs.version }}
|
||||||
|
push: true
|
12
.github/workflows/dockerhub-description.yml
vendored
12
.github/workflows/dockerhub-description.yml
vendored
|
@ -10,10 +10,10 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2.3.4
|
||||||
- name: Docker Hub Description
|
- name: Docker Hub Description
|
||||||
uses: peter-evans/dockerhub-description@v2.1.0
|
uses: peter-evans/dockerhub-description@v2.4.3
|
||||||
env:
|
with:
|
||||||
DOCKERHUB_USERNAME: mindflavor
|
username: mindflavor
|
||||||
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
DOCKERHUB_REPOSITORY: mindflavor/prometheus-wireguard-exporter
|
repository: mindflavor/prometheus-wireguard-exporter
|
||||||
|
|
19
.github/workflows/rust.yml
vendored
19
.github/workflows/rust.yml
vendored
|
@ -1,19 +0,0 @@
|
||||||
name: Rust
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Build
|
|
||||||
run: cargo build --verbose
|
|
||||||
- name: Run tests
|
|
||||||
run: cargo test --verbose
|
|
711
Cargo.lock
generated
711
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
29
Cargo.toml
29
Cargo.toml
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "prometheus_wireguard_exporter"
|
name = "prometheus_wireguard_exporter"
|
||||||
version = "3.5.1"
|
version = "3.6.6"
|
||||||
authors = ["Francesco Cogno <francesco.cogno@outlook.com>"]
|
authors = ["Francesco Cogno <francesco.cogno@outlook.com>"]
|
||||||
description = "Prometheus WireGuard Exporter"
|
description = "Prometheus WireGuard Exporter"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -19,15 +19,18 @@ default = []
|
||||||
leaky_log = []
|
leaky_log = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.14"
|
log = "0.4.17"
|
||||||
env_logger = "0.8.4"
|
env_logger = "0.9.3"
|
||||||
clap = "2.33.0"
|
clap = { version = "4.0.26", features = ["cargo", "env"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0.88"
|
||||||
serde = "1.0"
|
serde = "1.0.147"
|
||||||
serde_derive = "1.0"
|
thiserror = "1.0.37"
|
||||||
thiserror = "1.0"
|
anyhow = "1.0.66"
|
||||||
hyper = { version = "0.14", features = ["stream"] }
|
hyper = { version = "0.14.23", features = ["stream"] }
|
||||||
http = "0.2"
|
http = "0.2.8"
|
||||||
tokio = { version = "1.0", features = ["macros", "rt"] }
|
tokio = { version = "1.22.0", features = ["macros", "rt"] }
|
||||||
prometheus_exporter_base = { version = "1.2", features = ["hyper_server"] }
|
prometheus_exporter_base = { version = "1.3.0", features = ["hyper_server"] }
|
||||||
regex = "1.5.4"
|
regex = "1.7.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
clippy = "0.0.302"
|
||||||
|
|
29
Dockerfile
29
Dockerfile
|
@ -1,9 +1,9 @@
|
||||||
ARG BUILDPLATFORM=linux/amd64
|
ARG BUILDPLATFORM=linux/amd64
|
||||||
|
|
||||||
ARG ALPINE_VERSION=3.12
|
ARG ALPINE_VERSION=3.14
|
||||||
ARG RUST_VERSION=1-slim-bullseye
|
ARG RUST_VERSION=1.69-bullseye
|
||||||
|
|
||||||
FROM --platform=${BUILDPLATFORM} rust:${RUST_VERSION} AS build
|
FROM --platform=${BUILDPLATFORM} rust:${RUST_VERSION} AS base
|
||||||
WORKDIR /usr/src/prometheus_wireguard_exporter
|
WORKDIR /usr/src/prometheus_wireguard_exporter
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
|
@ -80,6 +80,9 @@ RUN rustup target add "$(cat /tmp/rusttarget)"
|
||||||
# Copy .cargo/config for cross build configuration
|
# Copy .cargo/config for cross build configuration
|
||||||
COPY .cargo ./.cargo
|
COPY .cargo ./.cargo
|
||||||
|
|
||||||
|
# Install Clippy for build platform
|
||||||
|
RUN rustup component add clippy
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN echo 'fn main() {}' > src/main.rs && \
|
RUN echo 'fn main() {}' > src/main.rs && \
|
||||||
RUSTFLAGS="$(cat /tmp/rustflags)" \
|
RUSTFLAGS="$(cat /tmp/rustflags)" \
|
||||||
|
@ -90,8 +93,21 @@ RUN rm -r \
|
||||||
target/*-linux-*/release/prometheus_wireguard_exporter* \
|
target/*-linux-*/release/prometheus_wireguard_exporter* \
|
||||||
src/main.rs
|
src/main.rs
|
||||||
|
|
||||||
# Build static binary with musl built-in
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
FROM base AS lint
|
||||||
|
RUN RUSTFLAGS="$(cat /tmp/rustflags)" \
|
||||||
|
CC="$(cat /tmp/musl)-gcc" \
|
||||||
|
cargo clippy --target "$(cat /tmp/rusttarget)"
|
||||||
|
|
||||||
|
FROM base AS test
|
||||||
|
ENTRYPOINT \
|
||||||
|
RUSTFLAGS="$(cat /tmp/rustflags)" \
|
||||||
|
CC="$(cat /tmp/musl)-gcc" \
|
||||||
|
cargo test --target "$(cat /tmp/rusttarget)"
|
||||||
|
|
||||||
|
FROM base AS build
|
||||||
|
# Build static binary with musl built-in
|
||||||
RUN RUSTFLAGS="$(cat /tmp/rustflags)" \
|
RUN RUSTFLAGS="$(cat /tmp/rustflags)" \
|
||||||
CC="$(cat /tmp/musl)-gcc" \
|
CC="$(cat /tmp/musl)-gcc" \
|
||||||
cargo build --target "$(cat /tmp/rusttarget)" --release && \
|
cargo build --target "$(cat /tmp/rusttarget)" --release && \
|
||||||
|
@ -105,12 +121,15 @@ RUN description="$(file /tmp/binary)" && \
|
||||||
FROM alpine:${ALPINE_VERSION}
|
FROM alpine:${ALPINE_VERSION}
|
||||||
EXPOSE 9586/tcp
|
EXPOSE 9586/tcp
|
||||||
WORKDIR /usr/local/bin
|
WORKDIR /usr/local/bin
|
||||||
|
RUN apk add --no-cache --q tini && \
|
||||||
|
rm -rf /var/cache/apk/*
|
||||||
RUN adduser prometheus-wireguard-exporter -s /bin/sh -D -u 1000 1000 && \
|
RUN adduser prometheus-wireguard-exporter -s /bin/sh -D -u 1000 1000 && \
|
||||||
mkdir -p /etc/sudoers.d && \
|
mkdir -p /etc/sudoers.d && \
|
||||||
echo 'prometheus-wireguard-exporter ALL=(root) NOPASSWD:/usr/bin/wg show * dump' > /etc/sudoers.d/prometheus-wireguard-exporter && \
|
echo 'prometheus-wireguard-exporter ALL=(root) NOPASSWD:/usr/bin/wg show * dump' > /etc/sudoers.d/prometheus-wireguard-exporter && \
|
||||||
chmod 0440 /etc/sudoers.d/prometheus-wireguard-exporter
|
chmod 0440 /etc/sudoers.d/prometheus-wireguard-exporter
|
||||||
RUN apk add --update -q --no-cache wireguard-tools-wg sudo
|
RUN apk add --update -q --no-cache wireguard-tools-wg sudo
|
||||||
USER prometheus-wireguard-exporter
|
USER prometheus-wireguard-exporter
|
||||||
ENTRYPOINT [ "/usr/local/bin/prometheus_wireguard_exporter" ]
|
#USER root
|
||||||
|
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/prometheus_wireguard_exporter"]
|
||||||
CMD [ "-a" ]
|
CMD [ "-a" ]
|
||||||
COPY --from=build --chown=prometheus-wireguard-exporter /tmp/binary ./prometheus_wireguard_exporter
|
COPY --from=build --chown=prometheus-wireguard-exporter /tmp/binary ./prometheus_wireguard_exporter
|
||||||
|
|
206
README.md
206
README.md
|
@ -4,24 +4,28 @@
|
||||||
|
|
||||||
[](https://crates.io/crates/prometheus_wireguard_exporter) [](https://crates.io/crates/prometheus_wireguard_exporter) [](https://crates.io/crates/prometheus_wireguard_exporter)
|
[](https://crates.io/crates/prometheus_wireguard_exporter) [](https://crates.io/crates/prometheus_wireguard_exporter) [](https://crates.io/crates/prometheus_wireguard_exporter)
|
||||||
|
|
||||||
[](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.5.1)
|
[](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.6.6)
|
||||||
[](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.5.1)
|
[](https://github.com/MindFlavor/prometheus_wireguard_exporter/tree/3.6.6)
|
||||||
|
|
||||||
[](https://github.com/mindflavor/prometheus_wireguard_exporter/actions?query=workflow%3ARust)
|
[](https://github.com/mindflavor/prometheus_wireguard_exporter/actions?query=workflow%3ARust)
|
||||||
[](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.5.1.svg)
|
[](https://img.shields.io/github/commits-since/mindflavor/prometheus_wireguard_exporter/3.6.6)
|
||||||
|
|
||||||

|
[](https://github.com/qdm12/godevcontainer/actions/workflows/docker.yml)
|
||||||
|
|
||||||
[](https://hub.docker.com/r/mindflavor/prometheus-wireguard-exporter)
|
[](https://hub.docker.com/r/mindflavor/prometheus-wireguard-exporter)
|
||||||
|
|
||||||
## Intro
|
## Intro
|
||||||
|
|
||||||
A Prometheus exporter for [WireGuard](https://www.wireguard.com), written in Rust. This tool exports the `wg show all dump` (or `wg show <interface> dump` if you specify a config file) results in a format that [Prometheus](https://prometheus.io/) can understand. The exporter is very light on your server resources, both in terms of memory and CPU usage.
|
A Prometheus exporter for [WireGuard](https://www.wireguard.com), written in Rust. This tool exports the `wg show all dump` (or `wg show <interface> dump` if you specify a config file) results in a format that [Prometheus](https://prometheus.io/) can understand. The exporter is very light on your server resources, both in terms of memory and CPU usage. It's also built for Docker for the following CPU architectures: `amd64`, `386`, `arm64`, `armv7` and `armv6`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Changelog
|
## 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.
|
* 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.
|
||||||
* From release [3.5.0](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.5.0) the exporter supports the `friendly_json` tag. Entries prepended with the `friendly_json` tag will output all the entries in the specificed json as Prometheus attributes. Thanks to [DrProxyProSupport](https://github.com/iqdoctor) for the idea.
|
* From release [3.5.0](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.5.0) the exporter supports the `friendly_json` tag. Entries prepended with the `friendly_json` tag will output all the entries in the specificed json as Prometheus attributes. Thanks to [DrProxyProSupport](https://github.com/iqdoctor) for the idea.
|
||||||
* From release [3.4.1](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.4.0) the exporter supports prepending `sudo` to the `wg` command. This allows to run the exporter as a non root user (although sudoer without password). Thanks to [Jonas Seydel](https://github.com/Thor77) for the idea.
|
* From release [3.4.1](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.4.0) the exporter supports prepending `sudo` to the `wg` command. This allows to run the exporter as a non root user (although sudoer without password). Thanks to [Jonas Seydel](https://github.com/Thor77) for the idea.
|
||||||
|
@ -31,77 +35,108 @@ A Prometheus exporter for [WireGuard](https://www.wireguard.com), written in Rus
|
||||||
* From release [3.0.0](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.0.0) the exporter allows two label modes: one is to dump every allowed ip in a single label (called `allowed_ips`) along with their subnets. The second one is to create a pair of labels for each allowed ip/subnet pair (called `allowed_ip_0`/`allowed_subnet_0`, `allowed_ip_1`/`allowed_subnet_1` and so on for every allowed ip). The default if the single label mode but you can enable the second mode by specifying the `-s` switch at startup. Thank you [Toon Schoenmakers](https://github.com/schoentoon) for this solution (see issue [#8](https://github.com/MindFlavor/prometheus_wireguard_exporter/issues/8)).
|
* From release [3.0.0](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/3.0.0) the exporter allows two label modes: one is to dump every allowed ip in a single label (called `allowed_ips`) along with their subnets. The second one is to create a pair of labels for each allowed ip/subnet pair (called `allowed_ip_0`/`allowed_subnet_0`, `allowed_ip_1`/`allowed_subnet_1` and so on for every allowed ip). The default if the single label mode but you can enable the second mode by specifying the `-s` switch at startup. Thank you [Toon Schoenmakers](https://github.com/schoentoon) for this solution (see issue [#8](https://github.com/MindFlavor/prometheus_wireguard_exporter/issues/8)).
|
||||||
* Starting from release [2.0.2](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/2.0.2) this exporter supports IPv6 addresses too (thanks to [Maximilian Bosch](https://github.com/Ma27)'s PR [#5](https://github.com/MindFlavor/prometheus_wireguard_exporter/pull/5)).
|
* Starting from release [2.0.2](https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/tag/2.0.2) this exporter supports IPv6 addresses too (thanks to [Maximilian Bosch](https://github.com/Ma27)'s PR [#5](https://github.com/MindFlavor/prometheus_wireguard_exporter/pull/5)).
|
||||||
|
|
||||||
## Prerequisites
|
## Setup
|
||||||
|
|
||||||
* You need [Rust](https://www.rust-lang.org/) to compile this code. Simply follow the instructions on Rust's website to install the toolchain. If you get weird errors while compiling please try and update your Rust version first (I have developed it on `rustc 1.55.0-nightly (798baebde 2021-07-02)`). Alternatively you can build the docker image or use the prebuilt one.
|
### Pre-built binaries
|
||||||
* You need [WireGuard](https://www.wireguard.com) *and* the `wg` CLI in the path. The tool will call `wg show <interface(s)>|all dump` and of course will fail if the `wg` executable is not found. If you want I can add the option of specifying the `wg` path in the command line, just open an issue for it.
|
|
||||||
|
|
||||||
Alternatively, as long as you have Wireguard on your host kernel with some Wireguard interfaces running, you can use Docker. For example:
|
Coming soon, subcribe to [#59](https://github.com/MindFlavor/prometheus_wireguard_exporter/issues/59)
|
||||||
|
|
||||||
```sh
|
### Docker
|
||||||
docker run -it --rm --init --net=host --cap-add=NET_ADMIN mindflavor/prometheus-wireguard-exporter
|
|
||||||
# Check it's up
|
|
||||||
docker run -it --rm alpine:3.12 wget -qO- http://localhost:9586/metrics
|
|
||||||
```
|
|
||||||
|
|
||||||
ℹ️ The Docker image is compatible with `amd64`, `386`, `arm64`, `armv7` and `armv6` CPUs.
|
1. You need Docker installed
|
||||||
|
1. You need [WireGuard](https://www.wireguard.com) installed in your host kernel
|
||||||
|
1. You need some Wireguard interfaces running
|
||||||
|
1. Download and run the container with:
|
||||||
|
|
||||||
To update the image, you can use
|
```sh
|
||||||
|
docker run -d --net=host --cap-add=NET_ADMIN --name wgexporter mindflavor/prometheus-wireguard-exporter
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ If you encounter time issues on your 32 bit operating system, [check this](https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.13.0#time64_requirements)
|
||||||
|
|
||||||
|
1. Check it's up by visiting [http://localhost:9586/metrics](http://localhost:9586/metrics)
|
||||||
|
|
||||||
|
You can then update the image with
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker pull mindflavor/prometheus_wireguard_exporter
|
docker pull mindflavor/prometheus_wireguard_exporter
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also build it with:
|
Or use a [tagged image](https://hub.docker.com/r/mindflavor/prometheus-wireguard-exporter/tags) such as `:3.5.1`.
|
||||||
|
|
||||||
|
If your host has an `amd64` or `686` CPU, you can also build the Docker image from source (you need `git`) with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker build -t mindflavor/prometheus_wireguard_exporter https://github.com/MindFlavor/prometheus_wireguard_exporter.git
|
docker build -t mindflavor/prometheus_wireguard_exporter https://github.com/MindFlavor/prometheus_wireguard_exporter.git#master
|
||||||
```
|
```
|
||||||
|
|
||||||
## Compilation
|
### Build from source
|
||||||
|
|
||||||
To compile the latest master version:
|
1. You need [Rust](https://www.rust-lang.org/tools/install) installed
|
||||||
|
1. You need [WireGuard](https://www.wireguard.com) installed on your host
|
||||||
|
1. You need `wg` accessible in your path. The tool will call `wg show <interface(s)>|all dump` and of course will fail if the `wg` executable is not found.
|
||||||
|
1. You need some Wireguard interfaces running
|
||||||
|
1. You need `git` installed
|
||||||
|
1. Clone the repository with
|
||||||
|
|
||||||
```bash
|
```sh
|
||||||
git clone https://github.com/MindFlavor/prometheus_wireguard_exporter.git
|
git clone https://github.com/MindFlavor/prometheus_wireguard_exporter.git
|
||||||
cd prometheus_wireguard_exporter
|
cd prometheus_wireguard_exporter
|
||||||
cargo install --path .
|
```
|
||||||
```
|
|
||||||
|
|
||||||
If you want the latest release you can simply use:
|
1. Compile the program with
|
||||||
|
|
||||||
```bash
|
```sh
|
||||||
cargo install prometheus_wireguard_exporter
|
cargo install --path .
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also build the Docker image with
|
💁 If you encounter errors, please try updating your rust installation with `rustup update`.
|
||||||
|
The code should compile with any relatively recent, 2018-compliant rustc version.
|
||||||
|
As a frame of reference, the last release was built using the Rust Docker image using `rustc 1.53.0 (53cb7b09b 2021-06-17)`.
|
||||||
|
|
||||||
```sh
|
1. Run the program
|
||||||
docker build -t mindflavor/prometheus-wireguard-exporter .
|
|
||||||
```
|
```sh
|
||||||
|
./prometheus_wireguard_exporter
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Check it's up by visiting [http://localhost:9586/metrics](http://localhost:9586/metrics)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Start the binary with `-h` to get the complete syntax. The parameters are:
|
### Flags available
|
||||||
|
|
||||||
| Parameter | Mandatory | Valid values | Default | Accepts multiple occurrences? | Description |
|
Start the binary with `-h` to get the complete syntax. The parameters are below.
|
||||||
| -- | -- | -- | -- | -- | -- |
|
|
||||||
| `-v` | no | <switch> | | No | Enable verbose mode.
|
❗**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`).
|
||||||
| `-a` | no | <switch> | | No | Prepends sudo to `wg` commands.
|
|
||||||
| `-l` | no | any valid ip address | 0.0.0.0 | No | Specify the service address. This is the address your Prometheus instance should point to.
|
For example, if you want to enable the verbose mode and enable the *prepend sudo* option you would use the following command line:
|
||||||
| `-p` | no | any valid port number | 9586 | No | Specify the service port. This is the port your Prometheus instance should point to.
|
|
||||||
| `-n` | no | path to the wireguard configuration file | | Yes | This flag adds the *friendly_name* attribute or the *friendly_json* attributes to the exported entries. See [Friendly tags](#friendly-tags) for more details. Multiple files are allowed (they will be merged as a single file in memory so avoid duplicates).
|
```bash
|
||||||
| `-s` | no | <switch> | off | No | Enable the allowed ip + subnet split mode for the labels.
|
prometheus_wireguard_exporter -a true -v true <...>
|
||||||
| `-r` | no | <switch> | off | No | Exports peer's remote ip and port as labels (if available).
|
```
|
||||||
| `-i` | no | your interface name(s) | `all` | Yes | Specifies the interface(s) passed to the `wg show <interface> dump` parameter. Multiple parameters are allowed.
|
|
||||||
|
| Parameter | Env | Mandatory | Valid values | Default | Accepts multiple occurrences? | Description |
|
||||||
|
| -- | -- | -- | -- | -- | -- | -- |
|
||||||
|
| `-v` | `PROMETHEUS_WIREGUARD_EXPORTER_VERBOSE_ENABLED` | No | `true` or `false` | `false` | No | Enable verbose mode.
|
||||||
|
| `-a` | `PROMETHEUS_WIREGUARD_EXPORTER_PREPEND_SUDO_ENABLED` | No | `true` or `false` | `false` | No | Prepends sudo to `wg` commands.
|
||||||
|
| `-l` | `PROMETHEUS_WIREGUARD_EXPORTER_ADDRESS` | No | Any valid IP address | `0.0.0.0` | No | Specify the service address. This is the address your Prometheus instance should point to.
|
||||||
|
| `-p` | `PROMETHEUS_WIREGUARD_EXPORTER_PORT` | No | Any valid port number | `9586` | No | Specify the service port. This is the port your Prometheus instance should point to.
|
||||||
|
| `-n` | `PROMETHEUS_WIREGUARD_EXPORTER_CONFIG_FILE_NAMES` | No | Path to the wireguard configuration file | | Yes | This flag adds the *friendly_name* attribute or the *friendly_json* attributes to the exported entries. See [Friendly tags](#friendly-tags) for more details. Multiple files are allowed (they will be merged as a single file in memory so avoid duplicates).
|
||||||
|
| `-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.
|
||||||
|
|
||||||
Once started, the tool will listen on the specified port (or the default one, 9586, if not specified) and return a Prometheus valid response at the url `/metrics`. So to check if the tool is working properly simply browse the `http://localhost:9586/metrics` (or whichever port you choose).
|
Once started, the tool will listen on the specified port (or the default one, 9586, if not specified) and return a Prometheus valid response at the url `/metrics`. So to check if the tool is working properly simply browse the `http://localhost:9586/metrics` (or whichever port you choose).
|
||||||
|
|
||||||
## Friendly Tags
|
### Friendly Tags
|
||||||
|
|
||||||
Starting from version 3.5 you can instruct the exporter to append a *friendly name* or a *friendly_json* to the exported entries. This can make the output more understandable than using the public keys. For example this is the standard output:
|
Starting from version 3.5 you can instruct the exporter to append a *friendly name* or a *friendly_json* to the exported entries. This can make the output more understandable than using the public keys. For example this is the standard output:
|
||||||
|
|
||||||
```
|
```ebnf
|
||||||
# HELP wireguard_sent_bytes_total Bytes sent to the peer
|
# HELP wireguard_sent_bytes_total Bytes sent to the peer
|
||||||
# TYPE wireguard_sent_bytes_total counter
|
# TYPE wireguard_sent_bytes_total counter
|
||||||
wireguard_sent_bytes_total{interface="wg0",public_key="2S7mA0vEMethCNQrJpJKE81/JmhgtB+tHHLYQhgM6kk=",allowed_ips="10.70.0.2/32,10.70.0.66/32"} 3208804
|
wireguard_sent_bytes_total{interface="wg0",public_key="2S7mA0vEMethCNQrJpJKE81/JmhgtB+tHHLYQhgM6kk=",allowed_ips="10.70.0.2/32,10.70.0.66/32"} 3208804
|
||||||
|
@ -133,7 +168,7 @@ wireguard_latest_handshake_seconds{interface="wg0",public_key="wTjv6hS6fKfNK+SzO
|
||||||
|
|
||||||
And this is the one augmented with friendly names:
|
And this is the one augmented with friendly names:
|
||||||
|
|
||||||
```
|
```ebnf
|
||||||
# HELP wireguard_sent_bytes_total Bytes sent to the peer
|
# HELP wireguard_sent_bytes_total Bytes sent to the peer
|
||||||
# TYPE wireguard_sent_bytes_total counter
|
# TYPE wireguard_sent_bytes_total counter
|
||||||
wireguard_sent_bytes_total{interface="wg0",public_key="2S7mA0vEMethCNQrJpJKE81/JmhgtB+tHHLYQhgM6kk=",allowed_ips="10.70.0.2/32,10.70.0.66/32",friendly_name="OnePlus 6T"} 3208804
|
wireguard_sent_bytes_total{interface="wg0",public_key="2S7mA0vEMethCNQrJpJKE81/JmhgtB+tHHLYQhgM6kk=",allowed_ips="10.70.0.2/32,10.70.0.66/32",friendly_name="OnePlus 6T"} 3208804
|
||||||
|
@ -197,7 +232,7 @@ As you can see, all you need to do is to add the friendly name in the comments p
|
||||||
|
|
||||||
This is a sample of the label split mode:
|
This is a sample of the label split mode:
|
||||||
|
|
||||||
```
|
```ebnf
|
||||||
# HELP wireguard_sent_bytes_total Bytes sent to the peer
|
# HELP wireguard_sent_bytes_total Bytes sent to the peer
|
||||||
# TYPE wireguard_sent_bytes_total counter
|
# TYPE wireguard_sent_bytes_total counter
|
||||||
wireguard_sent_bytes_total{interface="wg0",public_key="2S7mA0vEMethCNQrJpJKE81/JmhgtB+tHHLYQhgM6kk=",allowed_ip_0="10.70.0.2",allowed_subnet_0="32",allowed_ip_1="10.70.0.66",allowed_subnet_1="32",friendly_name="OnePlus 6T"} 3208804
|
wireguard_sent_bytes_total{interface="wg0",public_key="2S7mA0vEMethCNQrJpJKE81/JmhgtB+tHHLYQhgM6kk=",allowed_ip_0="10.70.0.2",allowed_subnet_0="32",allowed_ip_1="10.70.0.66",allowed_subnet_1="32",friendly_name="OnePlus 6T"} 3208804
|
||||||
|
@ -229,9 +264,9 @@ wireguard_latest_handshake_seconds{interface="wg0",public_key="wTjv6hS6fKfNK+SzO
|
||||||
|
|
||||||
### Systemd service file
|
### 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]
|
[Unit]
|
||||||
Description=Prometheus WireGuard Exporter
|
Description=Prometheus WireGuard Exporter
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
|
@ -246,3 +281,74 @@ ExecStart=/usr/local/bin/prometheus_wireguard_exporter -n /etc/wireguard/peers.c
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
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
|
||||||
|
|
||||||
|
1. Install [Rust](https://www.rust-lang.org/tools/install)
|
||||||
|
1. Install [Rust Analyzer](https://rust-analyzer.github.io/manual.html#installation) and set it up with your editor
|
||||||
|
1. Install [Clippy](https://github.com/rust-lang/rust-clippy): `rustup clippy`
|
||||||
|
|
||||||
|
You may want to install Docker as well to build and run the Docker image.
|
||||||
|
|
||||||
|
The following commands are available:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Download dependencies
|
||||||
|
cargo fetch
|
||||||
|
# Build the program
|
||||||
|
cargo build
|
||||||
|
# Run tests
|
||||||
|
cargo test
|
||||||
|
# Run clippy to lint
|
||||||
|
cargo clippy
|
||||||
|
# Build the Docker image
|
||||||
|
docker build -t mindflavor/prometheus_wireguard_exporter .
|
||||||
|
```
|
||||||
|
|
||||||
|
### VSCode development container
|
||||||
|
|
||||||
|
This is more of a plug and play solution based on Docker and VSCode.
|
||||||
|
|
||||||
|
See [.devcontainer/README.md](https://github.com/MindFlavor/prometheus_wireguard_exporter/blob/master/.devcontainer/README.md)
|
||||||
|
|
1
clippy.toml
Normal file
1
clippy.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# see https://rust-lang.github.io/rust-clippy/master/index.html
|
|
@ -37,7 +37,7 @@ pub enum ExporterError {
|
||||||
UTF8 { e: std::string::FromUtf8Error },
|
UTF8 { e: std::string::FromUtf8Error },
|
||||||
|
|
||||||
#[error("JSON format error: {}", e)]
|
#[error("JSON format error: {}", e)]
|
||||||
JSON { e: serde_json::error::Error },
|
Json { e: serde_json::error::Error },
|
||||||
|
|
||||||
#[error("IO Error: {}", e)]
|
#[error("IO Error: {}", e)]
|
||||||
IO { e: std::io::Error },
|
IO { e: std::io::Error },
|
||||||
|
@ -84,7 +84,7 @@ impl From<std::string::FromUtf8Error> for ExporterError {
|
||||||
|
|
||||||
impl From<serde_json::error::Error> for ExporterError {
|
impl From<serde_json::error::Error> for ExporterError {
|
||||||
fn from(e: serde_json::error::Error) -> Self {
|
fn from(e: serde_json::error::Error) -> Self {
|
||||||
ExporterError::JSON { e }
|
ExporterError::Json { e }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ impl<'a> TryFrom<(&'a str, &'a str)> for FriendlyDescription<'a> {
|
||||||
|
|
||||||
fn try_from((header_name, value): (&'a str, &'a str)) -> Result<Self, Self::Error> {
|
fn try_from((header_name, value): (&'a str, &'a str)) -> Result<Self, Self::Error> {
|
||||||
Ok(match header_name {
|
Ok(match header_name {
|
||||||
"friendly_name" => FriendlyDescription::Name(value.into()),
|
"friendly_name" => FriendlyDescription::Name(value.replace('\"', "\\\"").into()),
|
||||||
"friendly_json" => {
|
"friendly_json" => {
|
||||||
let ret: HashMap<&str, serde_json::Value> = serde_json::from_str(value)?;
|
let ret: HashMap<&str, serde_json::Value> = serde_json::from_str(value)?;
|
||||||
FriendlyDescription::Json(ret)
|
FriendlyDescription::Json(ret)
|
||||||
|
@ -29,3 +29,23 @@ impl<'a> TryFrom<(&'a str, &'a str)> for FriendlyDescription<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_no_escape_friendly_name() {
|
||||||
|
let fd: FriendlyDescription = ("friendly_name", "no escaping").try_into().unwrap();
|
||||||
|
assert_eq!(fd, FriendlyDescription::Name("no escaping".into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_escape_friendly_name() {
|
||||||
|
const TO_ESCAPE: &str = r#"man this is a quote ""#;
|
||||||
|
const ESCAPED: &str = r#"man this is a quote \""#;
|
||||||
|
let fd: FriendlyDescription = ("friendly_name", TO_ESCAPE).try_into().unwrap();
|
||||||
|
assert_eq!(fd, FriendlyDescription::Name(ESCAPED.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
118
src/main.rs
118
src/main.rs
|
@ -1,7 +1,8 @@
|
||||||
//extern crate serde_json;
|
use anyhow::Context;
|
||||||
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 hyper::{Body, Request};
|
||||||
use log::{debug, info, trace};
|
use log::{debug, info, trace};
|
||||||
|
use prometheus_exporter_base::prelude::{Authorization, ServerOptions};
|
||||||
use std::env;
|
use std::env;
|
||||||
mod options;
|
mod options;
|
||||||
use options::Options;
|
use options::Options;
|
||||||
|
@ -26,6 +27,7 @@ async fn perform_request(
|
||||||
Some(interfaces_str) => interfaces_str.clone(),
|
Some(interfaces_str) => interfaces_str.clone(),
|
||||||
None => vec!["all".to_owned()],
|
None => vec!["all".to_owned()],
|
||||||
};
|
};
|
||||||
|
log::trace!("interfaces_to_handle == {:?}", interfaces_to_handle);
|
||||||
|
|
||||||
let peer_entry_contents = options
|
let peer_entry_contents = options
|
||||||
.extract_names_config_files
|
.extract_names_config_files
|
||||||
|
@ -33,10 +35,11 @@ async fn perform_request(
|
||||||
.map(|files| {
|
.map(|files| {
|
||||||
files // if we have values
|
files // if we have values
|
||||||
.iter() // for each value
|
.iter() // for each value
|
||||||
.map(|file| std::fs::read_to_string(&file as &str)) // read the contents into a String
|
.map(|file| std::fs::read_to_string(file as &str)) // read the contents into a String
|
||||||
.collect::<Result<Vec<String>, std::io::Error>>() // And transform it into a vec (stopping in case of errors)
|
.collect::<Result<Vec<String>, std::io::Error>>() // And transform it into a vec (stopping in case of errors)
|
||||||
})
|
})
|
||||||
.transpose()? // bail out if there was an error
|
.transpose()
|
||||||
|
.with_context(|| "failed to read peer config file")? // bail out if there was an error
|
||||||
.map(|strings| strings.join("\n")); // now join the strings in a new string
|
.map(|strings| strings.join("\n")); // now join the strings in a new string
|
||||||
|
|
||||||
let peer_entry_hashmap = peer_entry_contents
|
let peer_entry_hashmap = peer_entry_contents
|
||||||
|
@ -102,11 +105,7 @@ async fn perform_request(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(wg_accumulator) = wg_accumulator {
|
if let Some(wg_accumulator) = wg_accumulator {
|
||||||
Ok(wg_accumulator.render_with_names(
|
Ok(wg_accumulator.render_with_names(peer_entry_hashmap.as_ref(), &options))
|
||||||
peer_entry_hashmap.as_ref(),
|
|
||||||
options.separate_allowed_ips,
|
|
||||||
options.export_remote_ip_and_port,
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
@ -114,62 +113,89 @@ async fn perform_request(
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let matches = clap::App::new(crate_name!())
|
let matches = clap::Command::new(crate_name!())
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.author(crate_authors!("\n"))
|
.author(crate_authors!("\n"))
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("addr")
|
Arg::new("addr")
|
||||||
.short("l")
|
.short('l')
|
||||||
|
.long("address")
|
||||||
|
.env("PROMETHEUS_WIREGUARD_EXPORTER_ADDRESS")
|
||||||
|
.value_parser(value_parser!(IpAddr))
|
||||||
.help("exporter address")
|
.help("exporter address")
|
||||||
.default_value("0.0.0.0")
|
.default_value("0.0.0.0")
|
||||||
.takes_value(true),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("port")
|
Arg::new("port")
|
||||||
.short("p")
|
.short('p')
|
||||||
|
.long("port")
|
||||||
|
.env("PROMETHEUS_WIREGUARD_EXPORTER_PORT")
|
||||||
|
.value_parser(value_parser!(u16))
|
||||||
.help("exporter port")
|
.help("exporter port")
|
||||||
.default_value("9586")
|
.default_value("9586")
|
||||||
.takes_value(true),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("verbose")
|
Arg::new("verbose")
|
||||||
.short("v")
|
.short('v')
|
||||||
|
.long("verbose")
|
||||||
|
.env("PROMETHEUS_WIREGUARD_EXPORTER_VERBOSE_ENABLED")
|
||||||
|
.value_parser(value_parser!(bool))
|
||||||
.help("verbose logging")
|
.help("verbose logging")
|
||||||
.takes_value(false),
|
.default_value("false")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("prepend_sudo")
|
Arg::new("prepend_sudo")
|
||||||
.short("a")
|
.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")
|
.help("Prepend sudo to the wg show commands")
|
||||||
.takes_value(false),
|
.default_value("false")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("separate_allowed_ips")
|
Arg::new("separate_allowed_ips")
|
||||||
.short("s")
|
.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")
|
.help("separate allowed ips and ports")
|
||||||
.takes_value(false),
|
.default_value("false")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("export_remote_ip_and_port")
|
Arg::new("export_remote_ip_and_port")
|
||||||
.short("r")
|
.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)")
|
.help("exports peer's remote ip and port as labels (if available)")
|
||||||
.takes_value(false),
|
.default_value("false")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("extract_names_config_files")
|
Arg::new("extract_names_config_files")
|
||||||
.short("n")
|
.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.")
|
.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(true)
|
.use_value_delimiter(false))
|
||||||
.number_of_values(1)
|
|
||||||
.takes_value(true))
|
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("interfaces")
|
Arg::new("interfaces")
|
||||||
.short("i")
|
.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.")
|
.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(true)
|
.use_value_delimiter(false))
|
||||||
.number_of_values(1)
|
.arg(
|
||||||
.takes_value(true))
|
Arg::new("export_latest_handshake_delay")
|
||||||
.get_matches();
|
.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);
|
let options = Options::from_claps(&matches);
|
||||||
|
|
||||||
|
@ -193,14 +219,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
);
|
);
|
||||||
info!("using options: {:?}", options);
|
info!("using options: {:?}", options);
|
||||||
|
|
||||||
let bind = matches.value_of("port").unwrap();
|
let bind: u16 = *matches.get_one("port").unwrap();
|
||||||
let bind = u16::from_str_radix(&bind, 10).expect("port must be a valid number");
|
let ip: IpAddr = *matches.get_one("addr").unwrap();
|
||||||
let ip = matches.value_of("addr").unwrap().parse::<IpAddr>().unwrap();
|
let addr: std::net::SocketAddr = (ip, bind).into();
|
||||||
let addr = (ip, bind).into();
|
|
||||||
|
|
||||||
info!("starting exporter on http://{}/metrics", addr);
|
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))
|
Box::pin(perform_request(request, options))
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use clap::parser::ValuesRef;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Options {
|
pub(crate) struct Options {
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
|
@ -6,21 +8,27 @@ pub(crate) struct Options {
|
||||||
pub extract_names_config_files: Option<Vec<String>>,
|
pub extract_names_config_files: Option<Vec<String>>,
|
||||||
pub interfaces: Option<Vec<String>>,
|
pub interfaces: Option<Vec<String>>,
|
||||||
pub export_remote_ip_and_port: bool,
|
pub export_remote_ip_and_port: bool,
|
||||||
|
pub export_latest_handshake_delay: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Options {
|
impl Options {
|
||||||
pub fn from_claps(matches: &clap::ArgMatches<'_>) -> Options {
|
pub fn from_claps(matches: &clap::ArgMatches) -> Options {
|
||||||
let options = Options {
|
let options = Options {
|
||||||
verbose: matches.is_present("verbose"),
|
verbose: *matches.get_one("verbose").unwrap_or(&false),
|
||||||
prepend_sudo: matches.is_present("prepend_sudo"),
|
prepend_sudo: *matches.get_one("prepend_sudo").unwrap_or(&false),
|
||||||
separate_allowed_ips: matches.is_present("separate_allowed_ips"),
|
separate_allowed_ips: *matches.get_one("separate_allowed_ips").unwrap_or(&false),
|
||||||
extract_names_config_files: matches
|
extract_names_config_files: matches
|
||||||
.values_of("extract_names_config_files")
|
.get_many("extract_names_config_files")
|
||||||
.map(|e| e.into_iter().map(|e| e.to_owned()).collect()),
|
.map(|e: ValuesRef<'_, String>| e.into_iter().map(|a| a.to_owned()).collect()),
|
||||||
interfaces: matches
|
interfaces: matches
|
||||||
.values_of("interfaces")
|
.get_many("interfaces")
|
||||||
.map(|e| e.into_iter().map(|a| a.to_owned()).collect()),
|
.map(|e: ValuesRef<'_, String>| e.into_iter().map(|a| a.to_string()).collect()),
|
||||||
export_remote_ip_and_port: matches.is_present("export_remote_ip_and_port"),
|
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
|
options
|
||||||
|
|
148
src/wireguard.rs
148
src/wireguard.rs
|
@ -1,4 +1,5 @@
|
||||||
use crate::exporter_error::ExporterError;
|
use crate::exporter_error::ExporterError;
|
||||||
|
use crate::options::Options;
|
||||||
use crate::wireguard_config::PeerEntryHashMap;
|
use crate::wireguard_config::PeerEntryHashMap;
|
||||||
use crate::FriendlyDescription;
|
use crate::FriendlyDescription;
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
|
@ -8,6 +9,7 @@ use std::collections::HashMap;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
const EMPTY: &str = "(none)";
|
const EMPTY: &str = "(none)";
|
||||||
|
|
||||||
|
@ -34,6 +36,7 @@ impl From<&str> for SecureString {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub(crate) struct LocalEndpoint {
|
pub(crate) struct LocalEndpoint {
|
||||||
pub public_key: String,
|
pub public_key: String,
|
||||||
|
@ -51,6 +54,7 @@ pub(crate) struct RemoteEndpoint {
|
||||||
pub latest_handshake: u64,
|
pub latest_handshake: u64,
|
||||||
pub sent_bytes: u128,
|
pub sent_bytes: u128,
|
||||||
pub received_bytes: u128,
|
pub received_bytes: u128,
|
||||||
|
#[allow(dead_code)]
|
||||||
pub persistent_keepalive: bool,
|
pub persistent_keepalive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,8 +143,7 @@ impl TryFrom<&str> for WireGuard {
|
||||||
if let Some(endpoints) = wg.interfaces.get_mut(v[0]) {
|
if let Some(endpoints) = wg.interfaces.get_mut(v[0]) {
|
||||||
endpoints.push(endpoint);
|
endpoints.push(endpoint);
|
||||||
} else {
|
} else {
|
||||||
let mut new_vec = Vec::new();
|
let new_vec = vec![endpoint];
|
||||||
new_vec.push(endpoint);
|
|
||||||
wg.interfaces.insert(v[0].to_owned(), new_vec);
|
wg.interfaces.insert(v[0].to_owned(), new_vec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,11 +156,11 @@ impl TryFrom<&str> for WireGuard {
|
||||||
impl WireGuard {
|
impl WireGuard {
|
||||||
pub fn merge(&mut self, merge_from: &WireGuard) {
|
pub fn merge(&mut self, merge_from: &WireGuard) {
|
||||||
for (interface_name, endpoints_to_merge) in merge_from.interfaces.iter() {
|
for (interface_name, endpoints_to_merge) in merge_from.interfaces.iter() {
|
||||||
if let Some(endpoints) = self.interfaces.get_mut(&interface_name as &str) {
|
if let Some(endpoints) = self.interfaces.get_mut(interface_name as &str) {
|
||||||
endpoints.extend_from_slice(&endpoints_to_merge);
|
endpoints.extend_from_slice(endpoints_to_merge);
|
||||||
} else {
|
} else {
|
||||||
let mut new_vec = Vec::new();
|
let mut new_vec = Vec::new();
|
||||||
new_vec.extend_from_slice(&endpoints_to_merge);
|
new_vec.extend_from_slice(endpoints_to_merge);
|
||||||
self.interfaces.insert(interface_name.to_owned(), new_vec);
|
self.interfaces.insert(interface_name.to_owned(), new_vec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,10 +169,12 @@ impl WireGuard {
|
||||||
pub(crate) fn render_with_names(
|
pub(crate) fn render_with_names(
|
||||||
&self,
|
&self,
|
||||||
pehm: Option<&PeerEntryHashMap>,
|
pehm: Option<&PeerEntryHashMap>,
|
||||||
split_allowed_ips: bool,
|
options: &Options,
|
||||||
export_remote_ip_and_port: bool,
|
|
||||||
) -> String {
|
) -> 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
|
// these are the exported counters
|
||||||
let mut pc_sent_bytes_total = PrometheusMetric::build()
|
let mut pc_sent_bytes_total = PrometheusMetric::build()
|
||||||
|
@ -185,8 +190,19 @@ impl WireGuard {
|
||||||
let mut pc_latest_handshake = PrometheusMetric::build()
|
let mut pc_latest_handshake = PrometheusMetric::build()
|
||||||
.with_name("wireguard_latest_handshake_seconds")
|
.with_name("wireguard_latest_handshake_seconds")
|
||||||
.with_metric_type(MetricType::Gauge)
|
.with_metric_type(MetricType::Gauge)
|
||||||
.with_help("Seconds from the last handshake")
|
.with_help("UNIX timestamp seconds of the last handshake")
|
||||||
.build();
|
.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
|
// Here we make sure we process the interfaces in the
|
||||||
// lexicographical order.
|
// lexicographical order.
|
||||||
|
@ -212,12 +228,10 @@ impl WireGuard {
|
||||||
// store in attibutes their references. attributes_owned is onyl
|
// store in attibutes their references. attributes_owned is onyl
|
||||||
// needed for separate ip+subnet
|
// needed for separate ip+subnet
|
||||||
let mut attributes_owned: Vec<(String, String)> = Vec::new();
|
let mut attributes_owned: Vec<(String, String)> = Vec::new();
|
||||||
let mut attributes: Vec<(&str, &str)> = Vec::new();
|
let mut attributes: Vec<(&str, &str)> =
|
||||||
|
vec![("interface", interface), ("public_key", &ep.public_key)];
|
||||||
|
|
||||||
attributes.push(("interface", interface));
|
if options.separate_allowed_ips {
|
||||||
attributes.push(("public_key", &ep.public_key));
|
|
||||||
|
|
||||||
if split_allowed_ips {
|
|
||||||
let v_ip_and_subnet: Vec<(&str, &str)> = ep
|
let v_ip_and_subnet: Vec<(&str, &str)> = ep
|
||||||
.allowed_ips
|
.allowed_ips
|
||||||
.split(',')
|
.split(',')
|
||||||
|
@ -289,9 +303,9 @@ impl WireGuard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if export_remote_ip_and_port {
|
if options.export_remote_ip_and_port {
|
||||||
if let Some(r_ip) = &ep.remote_ip {
|
if let Some(r_ip) = &ep.remote_ip {
|
||||||
attributes.push(("remote_ip", &r_ip));
|
attributes.push(("remote_ip", r_ip));
|
||||||
}
|
}
|
||||||
if let Some(r_port) = &ep.remote_port {
|
if let Some(r_port) = &ep.remote_port {
|
||||||
attributes_owned.push(("remote_port".to_string(), r_port.to_string()));
|
attributes_owned.push(("remote_port".to_string(), r_port.to_string()));
|
||||||
|
@ -307,6 +321,18 @@ impl WireGuard {
|
||||||
instance = instance.with_label(h, v);
|
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
|
pc_sent_bytes_total
|
||||||
.render_and_append_instance(&instance.clone().with_value(ep.sent_bytes))
|
.render_and_append_instance(&instance.clone().with_value(ep.sent_bytes))
|
||||||
.render();
|
.render();
|
||||||
|
@ -323,10 +349,15 @@ impl WireGuard {
|
||||||
}
|
}
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"{}\n{}\n{}",
|
"{}\n{}\n{}{}",
|
||||||
pc_sent_bytes_total.render(),
|
pc_sent_bytes_total.render(),
|
||||||
pc_received_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())
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,7 +431,17 @@ wg0\tsUsR6xufQQ8Tf0FuyY9tfEeYdhVMeFelr4ZMUrj+B0E=\t(none)\t10.211.123.128:51820\
|
||||||
|
|
||||||
let pe = PeerEntryHashMap::new();
|
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);
|
println!("{}", s);
|
||||||
|
|
||||||
let s_ok = "# HELP wireguard_sent_bytes_total Bytes sent to the peer
|
let s_ok = "# HELP wireguard_sent_bytes_total Bytes sent to the peer
|
||||||
|
@ -443,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=\"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
|
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
|
# 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=\"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
|
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
|
||||||
|
@ -490,13 +531,24 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_and_serialize() {
|
fn test_parse_and_serialize() {
|
||||||
let a = WireGuard::try_from(TEXT).unwrap();
|
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);
|
println!("{}", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_render_to_prometheus_simple() {
|
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 {
|
let re = Endpoint::Remote(RemoteEndpoint {
|
||||||
public_key: "test".to_owned(),
|
public_key: "test".to_owned(),
|
||||||
|
@ -512,11 +564,20 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
|
||||||
interfaces: HashMap::new(),
|
interfaces: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut v = Vec::new();
|
let v = vec![re];
|
||||||
v.push(re);
|
|
||||||
wg.interfaces.insert("Pippo".to_owned(), v);
|
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);
|
assert_eq!(prometheus, REF);
|
||||||
}
|
}
|
||||||
|
@ -525,13 +586,13 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
|
||||||
fn test_render_to_prometheus_complex() {
|
fn test_render_to_prometheus_complex() {
|
||||||
use crate::wireguard_config::PeerEntry;
|
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 {
|
let re1 = Endpoint::Remote(RemoteEndpoint {
|
||||||
public_key: "test".to_owned(),
|
public_key: "test".to_owned(),
|
||||||
|
@ -558,9 +619,7 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
|
||||||
interfaces: HashMap::new(),
|
interfaces: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut v = Vec::new();
|
let v = vec![re1, re2];
|
||||||
v.push(re1);
|
|
||||||
v.push(re2);
|
|
||||||
wg.interfaces.insert("Pippo".to_owned(), v);
|
wg.interfaces.insert("Pippo".to_owned(), v);
|
||||||
|
|
||||||
let mut pehm = PeerEntryHashMap::new();
|
let mut pehm = PeerEntryHashMap::new();
|
||||||
|
@ -573,13 +632,27 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
|
||||||
};
|
};
|
||||||
pehm.insert(pe.public_key, pe.clone());
|
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);
|
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);
|
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);
|
assert_eq!(prometheus, REF_SPLIT_NO_REMOTE);
|
||||||
|
|
||||||
// second test
|
// second test
|
||||||
|
@ -607,7 +680,10 @@ wireguard_latest_handshake_seconds{interface=\"wg0\",public_key=\"sUsR6xufQQ8Tf0
|
||||||
};
|
};
|
||||||
pehm.insert(pe.public_key, pe.clone());
|
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);
|
assert_eq!(prometheus, REF_JSON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,14 @@ use std::convert::TryInto;
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub(crate) struct PeerEntry<'a> {
|
pub(crate) struct PeerEntry<'a> {
|
||||||
pub public_key: &'a str,
|
pub public_key: &'a str,
|
||||||
|
#[allow(dead_code)]
|
||||||
pub allowed_ips: &'a str,
|
pub allowed_ips: &'a str,
|
||||||
pub friendly_description: Option<FriendlyDescription<'a>>,
|
pub friendly_description: Option<FriendlyDescription<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after_char(s: &str, c_split: char) -> &str {
|
fn after_char(s: &str, c_split: char) -> &str {
|
||||||
let mut p: usize = 0;
|
let mut p: usize = 0;
|
||||||
for c in s.chars().into_iter() {
|
for c in s.chars() {
|
||||||
if c == c_split {
|
if c == c_split {
|
||||||
return &s[p + 1..];
|
return &s[p + 1..];
|
||||||
} else {
|
} else {
|
||||||
|
@ -28,7 +29,7 @@ fn after_char_strip_comment(s: &str, c_split: char) -> &str {
|
||||||
let s = after_char(s, c_split);
|
let s = after_char(s, c_split);
|
||||||
|
|
||||||
if let Some(idx) = s.find('#') {
|
if let Some(idx) = s.find('#') {
|
||||||
&s[..idx].trim()
|
s[..idx].trim()
|
||||||
} else {
|
} else {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
@ -116,7 +117,7 @@ pub(crate) fn peer_entry_hashmap_try_from(
|
||||||
let mut v_blocks = Vec::new();
|
let mut v_blocks = Vec::new();
|
||||||
let mut cur_block: Option<Vec<&str>> = None;
|
let mut cur_block: Option<Vec<&str>> = None;
|
||||||
|
|
||||||
for line in txt.lines().into_iter() {
|
for line in txt.lines() {
|
||||||
if line.starts_with('[') {
|
if line.starts_with('[') {
|
||||||
if let Some(inner_cur_block) = cur_block {
|
if let Some(inner_cur_block) = cur_block {
|
||||||
// close the block
|
// close the block
|
||||||
|
@ -124,7 +125,7 @@ pub(crate) fn peer_entry_hashmap_try_from(
|
||||||
cur_block = None;
|
cur_block = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if line == "[Peer]" {
|
if line == "[Peer]" || line == "[WireGuardPeer]" {
|
||||||
// start a new block
|
// start a new block
|
||||||
cur_block = Some(Vec::new());
|
cur_block = Some(Vec::new());
|
||||||
}
|
}
|
||||||
|
@ -146,7 +147,7 @@ pub(crate) fn peer_entry_hashmap_try_from(
|
||||||
debug!("peer_entry_hashmap_try_from v_blocks == {:?}", v_blocks);
|
debug!("peer_entry_hashmap_try_from v_blocks == {:?}", v_blocks);
|
||||||
|
|
||||||
for block in &v_blocks {
|
for block in &v_blocks {
|
||||||
let p: PeerEntry = PeerEntry::try_from(&block as &[&str])?;
|
let p: PeerEntry = PeerEntry::try_from(block as &[&str])?;
|
||||||
hm.insert(p.public_key, p);
|
hm.insert(p.public_key, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +161,7 @@ mod tests {
|
||||||
use super::FriendlyDescription;
|
use super::FriendlyDescription;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const TEXT: &'static str = "
|
const TEXT: &str = "
|
||||||
ListenPort = 51820
|
ListenPort = 51820
|
||||||
PrivateKey = my_super_secret_private_key
|
PrivateKey = my_super_secret_private_key
|
||||||
# PreUp = iptables -t nat -A POSTROUTING -s 10.70.0.0/24 -o enp7s0 -j MASQUERADE
|
# PreUp = iptables -t nat -A POSTROUTING -s 10.70.0.0/24 -o enp7s0 -j MASQUERADE
|
||||||
|
@ -204,7 +205,7 @@ PublicKey = 928vO9Lf4+Mo84cWu4k1oRyzf0AR7FTGoPKHGoTMSHk=
|
||||||
AllowedIPs = 10.70.0.80/32
|
AllowedIPs = 10.70.0.80/32
|
||||||
";
|
";
|
||||||
|
|
||||||
const TEXT_JSON: &'static str = "
|
const TEXT_JSON: &str = "
|
||||||
ListenPort = 51820
|
ListenPort = 51820
|
||||||
PrivateKey = my_super_secret_private_key
|
PrivateKey = my_super_secret_private_key
|
||||||
# PreUp = iptables -t nat -A POSTROUTING -s 10.70.0.0/24 -o enp7s0 -j MASQUERADE
|
# PreUp = iptables -t nat -A POSTROUTING -s 10.70.0.0/24 -o enp7s0 -j MASQUERADE
|
||||||
|
@ -248,7 +249,7 @@ PublicKey = 928vO9Lf4+Mo84cWu4k1oRyzf0AR7FTGoPKHGoTMSHk=
|
||||||
AllowedIPs = 10.70.0.80/32
|
AllowedIPs = 10.70.0.80/32
|
||||||
";
|
";
|
||||||
|
|
||||||
const TEXT_NOPK: &'static str = "
|
const TEXT_NOPK: &str = "
|
||||||
ListenPort = 51820
|
ListenPort = 51820
|
||||||
PrivateKey = my_super_secret_private_key
|
PrivateKey = my_super_secret_private_key
|
||||||
# PreUp = iptables -t nat -A POSTROUTING -s 10.70.0.0/24 -o enp7s0 -j MASQUERADE
|
# PreUp = iptables -t nat -A POSTROUTING -s 10.70.0.0/24 -o enp7s0 -j MASQUERADE
|
||||||
|
@ -269,7 +270,7 @@ PublicKey = L2UoJZN7RmEKsMmqaJgKG0m1S2Zs2wd2ptAf+kb3008=
|
||||||
AllowedIPs = 10.70.0.4/32
|
AllowedIPs = 10.70.0.4/32
|
||||||
";
|
";
|
||||||
|
|
||||||
const TEXT_AIP: &'static str = "
|
const TEXT_AIP: &str = "
|
||||||
ListenPort = 51820
|
ListenPort = 51820
|
||||||
PrivateKey = my_super_secret_private_key
|
PrivateKey = my_super_secret_private_key
|
||||||
# PreUp = iptables -t nat -A POSTROUTING -s 10.70.0.0/24 -o enp7s0 -j MASQUERADE
|
# PreUp = iptables -t nat -A POSTROUTING -s 10.70.0.0/24 -o enp7s0 -j MASQUERADE
|
||||||
|
|
Loading…
Add table
Reference in a new issue