feat: export number of banned ips

Export the number of banned IPs stored in the fail2ban database as well
as the number of bad IPs.
Update the queries used to collect data to better handle cases where the
database table for bad/banned IPs is empty. The new query always lists all
jails, even when the count is zero.
This commit is contained in:
Hector 2021-02-06 12:24:31 +00:00
parent 4b965017d2
commit 91cba8080c
2 changed files with 31 additions and 2 deletions

View file

@ -5,7 +5,8 @@ import (
"log" "log"
) )
const queryBadIpsPerJail = "SELECT jail, COUNT(1) FROM bips GROUP BY jail" const queryBadIpsPerJail = "SELECT j.name, (SELECT COUNT(1) FROM bips b WHERE j.name = b.jail) FROM jails j"
const queryBannedIpsPerJail = "SELECT j.name, (SELECT COUNT(1) FROM bans b WHERE j.name = b.jail) FROM jails j"
type Fail2BanDB struct { type Fail2BanDB struct {
DatabasePath string DatabasePath string
@ -23,8 +24,16 @@ func MustConnectToDb(databasePath string) *Fail2BanDB {
} }
} }
func (db *Fail2BanDB) CountBannedIpsPerJail() (map[string]int, error) {
return db.RunJailNameToCountQuery(queryBannedIpsPerJail)
}
func (db *Fail2BanDB) CountBadIpsPerJail() (map[string]int, error) { func (db *Fail2BanDB) CountBadIpsPerJail() (map[string]int, error) {
stmt, err := db.sqliteDB.Prepare(queryBadIpsPerJail) return db.RunJailNameToCountQuery(queryBadIpsPerJail)
}
func (db *Fail2BanDB) RunJailNameToCountQuery(query string) (map[string]int, error) {
stmt, err := db.sqliteDB.Prepare(query)
defer db.mustCloseStatement(stmt) defer db.mustCloseStatement(stmt)
if err != nil { if err != nil {

View file

@ -18,6 +18,11 @@ var (
"Was the last fail2ban query successful.", "Was the last fail2ban query successful.",
nil, nil, nil, nil,
) )
metricBannedIpsPerJail = prometheus.NewDesc(
prometheus.BuildFQName(namespace, "", "banned_ips"),
"Number of banned IPs stored in the database (per jail).",
[]string{"jail"}, nil,
)
metricBadIpsPerJail = prometheus.NewDesc( metricBadIpsPerJail = prometheus.NewDesc(
prometheus.BuildFQName(namespace, "", "bad_ips"), prometheus.BuildFQName(namespace, "", "bad_ips"),
"Number of bad IPs stored in the database (per jail).", "Number of bad IPs stored in the database (per jail).",
@ -31,6 +36,7 @@ type Exporter struct {
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
ch <- metricUp ch <- metricUp
ch <- metricBadIpsPerJail ch <- metricBadIpsPerJail
ch <- metricBannedIpsPerJail
} }
func (e *Exporter) Collect(ch chan<- prometheus.Metric) { func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
@ -38,6 +44,7 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
metricUp, prometheus.GaugeValue, 1, metricUp, prometheus.GaugeValue, 1,
) )
collectBadIpsPerJailMetrics(ch) collectBadIpsPerJailMetrics(ch)
collectBannedIpsPerJailMetrics(ch)
} }
func collectBadIpsPerJailMetrics(ch chan<- prometheus.Metric) { func collectBadIpsPerJailMetrics(ch chan<- prometheus.Metric) {
@ -53,6 +60,19 @@ func collectBadIpsPerJailMetrics(ch chan<- prometheus.Metric) {
} }
} }
func collectBannedIpsPerJailMetrics(ch chan<- prometheus.Metric) {
jailNameToCountMap, err := db.CountBannedIpsPerJail()
if err != nil {
log.Print(err)
}
for jailName, count := range jailNameToCountMap {
ch <- prometheus.MustNewConstMetric(
metricBannedIpsPerJail, prometheus.GaugeValue, float64(count), jailName,
)
}
}
func main() { func main() {
log.Print("starting fail2ban exporter") log.Print("starting fail2ban exporter")