feat: rewrite cli flags and environment variables

Replace existing CLI flags to make them more consistent and follow a more
standard format.
Remove CLI flags and environment variables that are no longer relevant.
Add short `-v` option for version flag.
Update README with new documentation.

BREAKING CHANGE: Replace `--socket` flag with `--collector.f2b.socket`.
BREAKING CHANGE: Merge `--port` flag and `--web.listen-address` into a single flag.
BREAKING CHANGE: Remove `--collector.textfile` flag, its value is now derived from `--collector.textfile.directory`.
BREAKING CHANGE: Remove `F2B_COLLECTOR_TEXT` and `F2B_WEB_PORT` environment variables.
This commit is contained in:
Hector 2022-02-19 17:01:49 +00:00
parent 7515698ec8
commit 6e575aa0fd
4 changed files with 36 additions and 65 deletions

View File

@ -13,7 +13,7 @@ This exporter collects metrics from a running fail2ban instance.
Once the exporter is running, metrics are available at `localhost:9191/metrics`. Once the exporter is running, metrics are available at `localhost:9191/metrics`.
(The default port is `9191` but can be modified with the `--port` flag) (The default port is `9191` but can be modified with the `--web.listen-address` flag)
The exporter communicates with the fail2ban server over its socket. The exporter communicates with the fail2ban server over its socket.
This allows the data collected by the exporter to always align with the output of the `fail2ban-client`. This allows the data collected by the exporter to always align with the output of the `fail2ban-client`.
@ -38,22 +38,21 @@ See the [releases page](https://gitlab.com/hectorjsmith/fail2ban-prometheus-expo
**CLI Usage** **CLI Usage**
``` ```
$ fail2ban-prometheus-exporter -h $ fail2ban-prometheus-exporter -h
usage: exporter [<flags>] usage: fail2ban-prometheus-exporter [<flags>]
Flags: Flags:
-h, --help Show context-sensitive help (also try --help-long and --help-man). -h, --help Show context-sensitive help (also try --help-long and --help-man).
--version show version info and exit -v, --version show version info and exit
--port=9191 port to use for the metrics server --collector.f2b.socket="/var/run/fail2ban/fail2ban.sock"
--web.listen-address="0.0.0.0" path to the fail2ban server socket
address to use for the metrics server --collector.textfile.directory=""
--socket="" path to the fail2ban server socket directory to read text files with metrics from
--collector.textfile enable the textfile collector --web.listen-address=":9191"
--collector.textfile.directory="" address to use for the metrics server
directory to read text files with metrics from --web.basic-auth.username=""
--web.basic-auth.username="" username to use to protect endpoints with basic auth
username to use to protect endpoints with basic auth --web.basic-auth.password=""
--web.basic-auth.password="" password to use to protect endpoints with basic auth
password to use to protect endpoints with basic auth
``` ```
**Environment variables** **Environment variables**
@ -62,9 +61,7 @@ The tool can also be configured using environment variables. Each CLI parameter
``` ```
F2B_COLLECTOR_SOCKET F2B_COLLECTOR_SOCKET
F2B_COLLECTOR_TEXT
F2B_COLLECTOR_TEXT_PATH F2B_COLLECTOR_TEXT_PATH
F2B_WEB_PORT
F2B_WEB_LISTEN_ADDRESS F2B_WEB_LISTEN_ADDRESS
F2B_WEB_BASICAUTH_USER F2B_WEB_BASICAUTH_USER
F2B_WEB_BASICAUTH_PASS F2B_WEB_BASICAUTH_PASS
@ -73,7 +70,7 @@ F2B_WEB_BASICAUTH_PASS
**Example** **Example**
``` ```
fail2ban-prometheus-exporter --socket /var/run/fail2ban/fail2ban.sock --port 9191 fail2ban-prometheus-exporter --collector.f2b.socket=/var/run/fail2ban/fail2ban.sock --web.listen-address=":9191"
``` ```
Note that the exporter will need read access to the fail2ban socket. Note that the exporter will need read access to the fail2ban socket.
@ -232,9 +229,7 @@ Status for the jail: sshd|- Filter
For more flexibility the exporter also allows exporting metrics collected from a text file. For more flexibility the exporter also allows exporting metrics collected from a text file.
To enable textfile metrics: To enable textfile metrics provide the directory to read files from with the `--collector.textfile.directory` flag.
1. Enable the collector with `--collector.textfile=true`
2. Provide the directory to read files from with the `--collector.textfile.directory` flag
Metrics collected from these files will be exposed directly alongside the other metrics without any additional processing. Metrics collected from these files will be exposed directly alongside the other metrics without any additional processing.
This means that it is the responsibility of the file creator to ensure the format is correct. This means that it is the responsibility of the file creator to ensure the format is correct.
@ -252,8 +247,8 @@ textfile_error{path="file.prom"} 0
**Running in Docker** **Running in Docker**
To collect textfile metrics inside a docker container, a couple of things need to be done: To collect textfile metrics inside a docker container, a couple of things need to be done:
1. Mount the folder with the metrics 1. Mount the folder with the metrics files
2. Set the relevant environment variables 2. Set the `F2B_COLLECTOR_TEXT_PATH` environment variable
*For example:* *For example:*
``` ```
@ -261,7 +256,6 @@ docker run -d \
--name "fail2ban-exporter" \ --name "fail2ban-exporter" \
-v /var/run/fail2ban:/var/run/fail2ban:ro \ -v /var/run/fail2ban:/var/run/fail2ban:ro \
-v /path/to/metrics:/app/metrics/:ro \ -v /path/to/metrics:/app/metrics/:ro \
-e F2B_COLLECTOR_TEXT=true \
-e F2B_COLLECTOR_TEXT_PATH=/app/metrics \ -e F2B_COLLECTOR_TEXT_PATH=/app/metrics \
-p "9191:9191" \ -p "9191:9191" \
registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest

View File

@ -7,25 +7,19 @@ import (
) )
const ( const (
minServerPort = 1000 socketEnvName = "F2B_COLLECTOR_SOCKET"
maxServerPort = 65535 fileCollectorPathEnvName = "F2B_COLLECTOR_TEXT_PATH"
socketEnvName = "F2B_COLLECTOR_SOCKET" addressEnvName = "F2B_WEB_LISTEN_ADDRESS"
fileCollectorEnabledEnvName = "F2B_COLLECTOR_TEXT" basicAuthUserEnvName = "F2B_WEB_BASICAUTH_USER"
fileCollectorPathEnvName = "F2B_COLLECTOR_TEXT_PATH" basicAuthPassEnvName = "F2B_WEB_BASICAUTH_PASS"
portEnvName = "F2B_WEB_PORT"
addressEnvName = "F2B_WEB_LISTEN_ADDRESS"
basicAuthUserEnvName = "F2B_WEB_BASICAUTH_USER"
basicAuthPassEnvName = "F2B_WEB_BASICAUTH_PASS"
) )
type AppSettings struct { type AppSettings struct {
VersionMode bool VersionMode bool
MetricsAddress string MetricsAddress string
MetricsPort int Fail2BanSocketPath string
Fail2BanSocketPath string FileCollectorPath string
FileCollectorPath string BasicAuthProvider *hashedBasicAuth
FileCollectorEnabled bool
BasicAuthProvider *hashedBasicAuth
} }
func init() { func init() {
@ -42,31 +36,22 @@ func Parse() *AppSettings {
func readParamsFromCli(settings *AppSettings) { func readParamsFromCli(settings *AppSettings) {
versionMode := kingpin. versionMode := kingpin.
Flag("version", "show version info and exit"). Flag("version", "show version info and exit").
Short('v').
Default("false"). Default("false").
Bool() Bool()
socketPath := kingpin. socketPath := kingpin.
Flag("socket", "path to the fail2ban server socket"). Flag("collector.f2b.socket", "path to the fail2ban server socket").
Default("/var/run/fail2ban/fail2ban.sock"). Default("/var/run/fail2ban/fail2ban.sock").
Envar(socketEnvName). Envar(socketEnvName).
String() String()
fileCollectorEnabled := kingpin.
Flag("collector.textfile", "enable the textfile collector").
Default("false").
Envar(fileCollectorEnabledEnvName).
Bool()
fileCollectorPath := kingpin. fileCollectorPath := kingpin.
Flag("collector.textfile.directory", "directory to read text files with metrics from"). Flag("collector.textfile.directory", "directory to read text files with metrics from").
Default(""). Default("").
Envar(fileCollectorPathEnvName). Envar(fileCollectorPathEnvName).
String() String()
port := kingpin.
Flag("port", "port to use for the metrics server").
Default("9191").
Envar(portEnvName).
Int()
address := kingpin. address := kingpin.
Flag("web.listen-address", "address to use for the metrics server"). Flag("web.listen-address", "address to use for the metrics server").
Default("0.0.0.0"). Default(":9191").
Envar(addressEnvName). Envar(addressEnvName).
String() String()
rawBasicAuthUsername := kingpin. rawBasicAuthUsername := kingpin.
@ -83,10 +68,8 @@ func readParamsFromCli(settings *AppSettings) {
kingpin.Parse() kingpin.Parse()
settings.VersionMode = *versionMode settings.VersionMode = *versionMode
settings.MetricsPort = *port
settings.MetricsAddress = *address settings.MetricsAddress = *address
settings.Fail2BanSocketPath = *socketPath settings.Fail2BanSocketPath = *socketPath
settings.FileCollectorEnabled = *fileCollectorEnabled
settings.FileCollectorPath = *fileCollectorPath settings.FileCollectorPath = *fileCollectorPath
settings.setBasicAuthValues(*rawBasicAuthUsername, *rawBasicAuthPassword) settings.setBasicAuthValues(*rawBasicAuthUsername, *rawBasicAuthPassword)
} }
@ -102,13 +85,8 @@ func (settings *AppSettings) validateFlags() {
fmt.Println("error: fail2ban socket path must not be blank") fmt.Println("error: fail2ban socket path must not be blank")
flagsValid = false flagsValid = false
} }
if settings.MetricsPort < minServerPort || settings.MetricsPort > maxServerPort { if settings.MetricsAddress == "" {
fmt.Printf("error: invalid server port, must be within %d and %d (found %d)\n", fmt.Println("error: invalid server address, must not be blank")
minServerPort, maxServerPort, settings.MetricsPort)
flagsValid = false
}
if settings.FileCollectorEnabled && settings.FileCollectorPath == "" {
fmt.Println("error: file collector directory path must not be empty if collector enabled")
flagsValid = false flagsValid = false
} }
if (len(settings.BasicAuthProvider.username) > 0) != (len(settings.BasicAuthProvider.password) > 0) { if (len(settings.BasicAuthProvider.username) > 0) != (len(settings.BasicAuthProvider.password) > 0) {

View File

@ -20,7 +20,7 @@ type fileData struct {
func NewCollector(appSettings *cfg.AppSettings) *Collector { func NewCollector(appSettings *cfg.AppSettings) *Collector {
collector := &Collector{ collector := &Collector{
enabled: appSettings.FileCollectorEnabled, enabled: appSettings.FileCollectorPath != "",
folderPath: appSettings.FileCollectorPath, folderPath: appSettings.FileCollectorPath,
fileMap: make(map[string]*fileData), fileMap: make(map[string]*fileData),
} }

View File

@ -54,9 +54,8 @@ func main() {
if appSettings.VersionMode { if appSettings.VersionMode {
printAppVersion() printAppVersion()
} else { } else {
addr := fmt.Sprintf("%s:%d", appSettings.MetricsAddress, appSettings.MetricsPort)
log.Printf("fail2ban exporter version %s", version) log.Printf("fail2ban exporter version %s", version)
log.Printf("starting server at %s", addr) log.Printf("starting server at %s", appSettings.MetricsAddress)
f2bCollector := f2b.NewExporter(appSettings, version) f2bCollector := f2b.NewExporter(appSettings, version)
prometheus.MustRegister(f2bCollector) prometheus.MustRegister(f2bCollector)
@ -78,7 +77,7 @@ func main() {
svrErr := make(chan error) svrErr := make(chan error)
go func() { go func() {
svrErr <- http.ListenAndServe(addr, nil) svrErr <- http.ListenAndServe(appSettings.MetricsAddress, nil)
}() }()
log.Print("ready") log.Print("ready")