From 0b40e5de82324a4bd5ffb36470699f745878ac8a Mon Sep 17 00:00:00 2001 From: Hector Date: Sat, 6 Feb 2021 11:45:46 +0000 Subject: [PATCH] feat: connect to fail2ban db and extract total bad ips Add dependencies on `sqlite` to allow connecting to the fail2ban database. Add a new `db` module to handle all the database connections and data queries used to generate metrics. Export a new metric for the total number of bad IPs stored in the fail2ban database. --- db/db.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ exporter.go | 32 ++++++++++++++++++++++++++------ go.mod | 5 ++++- go.sum | 2 ++ 4 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 db/db.go diff --git a/db/db.go b/db/db.go new file mode 100644 index 0000000..86a29fe --- /dev/null +++ b/db/db.go @@ -0,0 +1,50 @@ +package db + +import ( + "database/sql" + "log" + "strconv" +) + +const queryCountTotalBadIps = "SELECT COUNT(1) FROM bips" + +type Fail2BanDB struct { + DatabasePath string + sqliteDB *sql.DB +} + +func MustConnectToDb(databasePath string) *Fail2BanDB { + db, err := sql.Open("sqlite3", databasePath) + if err != nil { + log.Fatal(err) + } + return &Fail2BanDB{ + DatabasePath: databasePath, + sqliteDB: db, + } +} + +func (db *Fail2BanDB) CountTotalBadIps() (int, error) { + stmt, err := db.sqliteDB.Prepare(queryCountTotalBadIps) + defer db.mustCloseStatement(stmt) + + if err != nil { + return -1, err + } + + result := "" + err = stmt.QueryRow().Scan(&result) + + if err != nil { + return -1, err + } + + return strconv.Atoi(result) +} + +func (db *Fail2BanDB) mustCloseStatement(stmt *sql.Stmt) { + err := stmt.Close() + if err != nil { + log.Fatal(err) + } +} diff --git a/exporter.go b/exporter.go index 19e3d2e..6cf2221 100644 --- a/exporter.go +++ b/exporter.go @@ -1,6 +1,8 @@ package main import ( + fail2banDb "fail2ban-prometheus-exporter/db" + _ "github.com/mattn/go-sqlite3" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "log" @@ -9,23 +11,41 @@ import ( const namespace = "fail2ban" -var up = prometheus.NewDesc( - prometheus.BuildFQName(namespace, "", "up"), - "Was the last fail2ban query successful.", - nil, nil, +var ( + db = fail2banDb.MustConnectToDb("fail2ban.sqlite3") + metricUp = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "up"), + "Was the last fail2ban query successful.", + nil, nil, + ) + metricBadIpTotal = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "badip_total"), + "Total number of bad IPs stored in the database.", + nil, nil, + ) ) type Exporter struct { } func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { - ch <- up + ch <- metricUp + ch <- metricBadIpTotal } func (e *Exporter) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( - up, prometheus.GaugeValue, 1, + metricUp, prometheus.GaugeValue, 1, ) + ch <- *collectTotalBadIpMetric() +} + +func collectTotalBadIpMetric() *prometheus.Metric { + count, _ := db.CountTotalBadIps() + metric := prometheus.MustNewConstMetric( + metricBadIpTotal, prometheus.GaugeValue, float64(count), + ) + return &metric } func main() { diff --git a/go.mod b/go.mod index 63dc5e1..2df78ea 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module fail2ban-prometheus-exporter go 1.15 -require github.com/prometheus/client_golang v1.9.0 +require ( + github.com/mattn/go-sqlite3 v1.14.6 + github.com/prometheus/client_golang v1.9.0 +) diff --git a/go.sum b/go.sum index 94b6a13..7de5c32 100644 --- a/go.sum +++ b/go.sum @@ -150,6 +150,8 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=