Add reauth feature, remove errors library.

This commit is contained in:
David Newhall II 2019-08-25 01:54:19 -07:00
parent 5b838948d8
commit 10d17b4a31
10 changed files with 69 additions and 42 deletions

9
Gopkg.lock generated
View File

@ -21,14 +21,6 @@
pruneopts = "UT" pruneopts = "UT"
revision = "fc22c7df067eefd070157f157893fbce961d6359" revision = "fc22c7df067eefd070157f157893fbce961d6359"
[[projects]]
digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = "UT"
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
version = "v0.8.1"
[[projects]] [[projects]]
digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2" digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2"
name = "github.com/spf13/pflag" name = "github.com/spf13/pflag"
@ -59,7 +51,6 @@
input-imports = [ input-imports = [
"github.com/BurntSushi/toml", "github.com/BurntSushi/toml",
"github.com/influxdata/influxdb1-client/v2", "github.com/influxdata/influxdb1-client/v2",
"github.com/pkg/errors",
"github.com/spf13/pflag", "github.com/spf13/pflag",
"golift.io/unifi", "golift.io/unifi",
"gopkg.in/yaml.v2", "gopkg.in/yaml.v2",

View File

@ -65,7 +65,7 @@ is provided so the application can be easily adapted to any environment.
`Config File Parameters` `Config File Parameters`
sites default: ["all"] sites default: ["all"]
This list of strings should represent the names of sites on the UniFi This list of strings should represent the names of sites on the UniFi
controller that will be polled for data. Pass `all` in the list to controller that will be polled for data. Pass `all` in the list to
poll all sites. On startup, the application prints out all site names poll all sites. On startup, the application prints out all site names
@ -73,20 +73,20 @@ is provided so the application can be easily adapted to any environment.
next to them. The cryptic names go into the config file `sites` list. next to them. The cryptic names go into the config file `sites` list.
The controller's first site is not cryptic and is named `default`. The controller's first site is not cryptic and is named `default`.
interval default: 30s interval default: 30s
How often to poll the controller for updated client and device data. How often to poll the controller for updated client and device data.
The UniFi Controller only updates traffic stats about every 30 seconds. The UniFi Controller only updates traffic stats about every 30 seconds.
debug default: false debug default: false
This turns on time stamps and line numbers in logs, outputs a few extra This turns on time stamps and line numbers in logs, outputs a few extra
lines of information while processing. lines of information while processing.
quiet default: false quiet default: false
Setting this to true will turn off per-device and per-interval logs. Only Setting this to true will turn off per-device and per-interval logs. Only
errors will be logged. Using this with debug=true adds line numbers to errors will be logged. Using this with debug=true adds line numbers to
any error logs. any error logs.
mode default: "influx" mode default: "influx"
* Value: influx * Value: influx
This default mode runs this application as a daemon. It will poll This default mode runs this application as a daemon. It will poll
the controller at the configured interval. Providing an invalid value the controller at the configured interval. Providing an invalid value
@ -101,7 +101,7 @@ is provided so the application can be easily adapted to any environment.
This mode can also be combined with a "test database" in InfluxDB to This mode can also be combined with a "test database" in InfluxDB to
give yourself a "test config file" you may run ad-hoc to test changes. give yourself a "test config file" you may run ad-hoc to test changes.
max_errors default: 0 max_errors default: 0
If you restart the UniFI controller, the poller will lose access until If you restart the UniFI controller, the poller will lose access until
it is restarted. Specifying a number greater than -1 for max_errors will it is restarted. Specifying a number greater than -1 for max_errors will
cause the poller to exit when it reaches the error count specified. cause the poller to exit when it reaches the error count specified.
@ -113,16 +113,16 @@ is provided so the application can be easily adapted to any environment.
docker or launchd. The default setting of 0 will cause an exit after docker or launchd. The default setting of 0 will cause an exit after
just 1 error. Recommended values are 0-5. just 1 error. Recommended values are 0-5.
influx_url default: http://127.0.0.1:8086 influx_url default: http://127.0.0.1:8086
This is the URL where the Influx web server is available. This is the URL where the Influx web server is available.
influx_user default: unifi influx_user default: unifi
Username used to authenticate with InfluxDB. Username used to authenticate with InfluxDB.
influx_pass default: unifi influx_pass default: unifi
Password used to authenticate with InfluxDB. Password used to authenticate with InfluxDB.
influx_db default: unifi influx_db default: unifi
Custom database created in InfluxDB to use with this application. Custom database created in InfluxDB to use with this application.
On first setup, log into InfluxDB and create access: On first setup, log into InfluxDB and create access:
$ influx -host localhost -port 8086 $ influx -host localhost -port 8086
@ -130,24 +130,30 @@ is provided so the application can be easily adapted to any environment.
CREATE USER unifi WITH PASSWORD 'unifi' WITH ALL PRIVILEGES CREATE USER unifi WITH PASSWORD 'unifi' WITH ALL PRIVILEGES
GRANT ALL ON unifi TO unifi GRANT ALL ON unifi TO unifi
unifi_url default: https://127.0.0.1:8443 unifi_url default: https://127.0.0.1:8443
This is the URL where the UniFi Controller is available. This is the URL where the UniFi Controller is available.
unifi_user default: influxdb unifi_user default: influxdb
Username used to authenticate with UniFi controller. This should be a Username used to authenticate with UniFi controller. This should be a
special service account created on the control with read-only access. special service account created on the control with read-only access.
unifi_user no default ENV: UNIFI_PASSWORD unifi_user no default ENV: UNIFI_PASSWORD
Password used to authenticate with UniFi controller. This can also be Password used to authenticate with UniFi controller. This can also be
set in an environment variable instead of a configuration file. set in an environment variable instead of a configuration file.
collect_ids default: false collect_ids default: false
Setting this parameter to true will enable collection of Intrusion Setting this parameter to true will enable collection of Intrusion
Detection System data. IDS and IPS are the same data set. This is off Detection System data. IDS and IPS are the same data set. This is off
by default because most controllers do not have this enabled. It also by default because most controllers do not have this enabled. It also
creates a lot of new metrics from controllers with a lot of IDS entries. creates a lot of new metrics from controllers with a lot of IDS entries.
verify_ssl default: false reauthenticate default: false
Setting this parameter to true will make UniFi Poller send a new login
request on every interval. This generates a new cookie. Some controller
or reverse proxy configurations require this. Do not enable it unless
your configuration causes the poller to be logged out after some time.
verify_ssl default: false
If your UniFi controller has a valid SSL certificate, you can enable If your UniFi controller has a valid SSL certificate, you can enable
this option to validate it. Otherwise, any SSL certificate is valid. this option to validate it. Otherwise, any SSL certificate is valid.

View File

@ -54,7 +54,14 @@ unifi_pass = "4BB9345C-2341-48D7-99F5-E01B583FF77F"
# Only useful if IDS or IPS are enabled on one of the sites. # Only useful if IDS or IPS are enabled on one of the sites.
#collect_ids = false #collect_ids = false
# If your UniFi controller has a valid SSL certificate, you can enable # Some controllers or reverse proxy configurations do not allow cookies to be
# this option to validate it. Otherwise, any SSL certificate is valid. # re-user on every request (every interval). This setting provides a workaround
# If you don't know if you have a valid SSL cert, then you don't have one. # That causes the poller to re-auth (login) to the controller on every interval.
# Only enable this if you get login errors after 30 seconds. This will generate
# a few more requests to your controller every interval.
#reauthenticate = false
# If your UniFi controller has a valid SSL certificate (like lets encrypt),
# you can enable this option to validate it. Otherwise, any SSL certificate is
# valid. If you don't know if you have a valid SSL cert, then you don't have one.
#verify_ssl = false #verify_ssl = false

View File

@ -13,5 +13,6 @@
"unifi_pass": "", "unifi_pass": "",
"unifi_url": "https://127.0.0.1:8443", "unifi_url": "https://127.0.0.1:8443",
"collect_ids": false, "collect_ids": false,
"reauthenticate": false,
"verify_ssl": false "verify_ssl": false
} }

View File

@ -77,6 +77,14 @@
--> -->
<collect_ids>false</collect_ids> <collect_ids>false</collect_ids>
<!-- <!--
# Some controllers or reverse proxy configurations do not allow cookies to be
# re-user on every request (every interval). This setting provides a workaround
# That causes the poller to re-auth (login) to the controller on every interval.
# Only enable this if you get login errors after 30 seconds. This will generate
# a few more requests to your controller every interval.
-->
<reauthenticate>false</reauthenticate>
<!--
# If your UniFi controller has a valid SSL certificate, you can enable # If your UniFi controller has a valid SSL certificate, you can enable
# this option to validate it. Otherwise, any SSL certificate is valid. # this option to validate it. Otherwise, any SSL certificate is valid.
--> -->

View File

@ -54,6 +54,13 @@ unifi_url: "https://127.0.0.1:8443"
# Only useful if IDS or IPS are enabled on one of the sites. # Only useful if IDS or IPS are enabled on one of the sites.
collect_ids: false collect_ids: false
# Some controllers or reverse proxy configurations do not allow cookies to be
# re-user on every request (every interval). This setting provides a workaround
# That causes the poller to re-auth (login) to the controller on every interval.
# Only enable this if you get login errors after 30 seconds. This will generate
# a few more requests to your controller every interval.
reauthenticate: false
# If your UniFi controller has a valid SSL certificate, you can enable # If your UniFi controller has a valid SSL certificate, you can enable
# this option to validate it. Otherwise, any SSL certificate is valid. # this option to validate it. Otherwise, any SSL certificate is valid.
verify_ssl: false verify_ssl: false

View File

@ -60,6 +60,7 @@ type Config struct {
Quiet bool `json:"quiet,_omitempty" toml:"quiet,_omitempty" xml:"quiet" yaml:"quiet"` Quiet bool `json:"quiet,_omitempty" toml:"quiet,_omitempty" xml:"quiet" yaml:"quiet"`
VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"` VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"`
CollectIDS bool `json:"collect_ids" toml:"collect_ids" xml:"collect_ids" yaml:"collect_ids"` CollectIDS bool `json:"collect_ids" toml:"collect_ids" xml:"collect_ids" yaml:"collect_ids"`
ReAuth bool `json:"reauthenticate" toml:"reauthenticate" xml:"reauthenticate" yaml:"reauthenticate"`
Mode string `json:"mode" toml:"mode" xml:"mode" yaml:"mode"` Mode string `json:"mode" toml:"mode" xml:"mode" yaml:"mode"`
InfluxURL string `json:"influx_url,_omitempty" toml:"influx_url,_omitempty" xml:"influx_url" yaml:"influx_url"` InfluxURL string `json:"influx_url,_omitempty" toml:"influx_url,_omitempty" xml:"influx_url" yaml:"influx_url"`
InfluxUser string `json:"influx_user,_omitempty" toml:"influx_user,_omitempty" xml:"influx_user" yaml:"influx_user"` InfluxUser string `json:"influx_user,_omitempty" toml:"influx_user,_omitempty" xml:"influx_user" yaml:"influx_user"`

View File

@ -5,7 +5,6 @@ import (
"os" "os"
"strings" "strings"
"github.com/pkg/errors"
"golift.io/unifi" "golift.io/unifi"
) )
@ -35,7 +34,7 @@ func (u *UnifiPoller) DumpJSONPayload() (err error) {
_, _ = fmt.Fprintf(os.Stderr, "[INFO] Dumping Path '%s':\n", apiPath) _, _ = fmt.Fprintf(os.Stderr, "[INFO] Dumping Path '%s':\n", apiPath)
return u.PrintRawAPIJSON(apiPath) return u.PrintRawAPIJSON(apiPath)
default: default:
return errors.New("must provide filter: devices, clients, other") return fmt.Errorf("must provide filter: devices, clients, other")
} }
} }

View File

@ -12,10 +12,9 @@ import (
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
influx "github.com/influxdata/influxdb1-client/v2" influx "github.com/influxdata/influxdb1-client/v2"
"github.com/pkg/errors" "github.com/spf13/pflag"
flag "github.com/spf13/pflag"
"golift.io/unifi" "golift.io/unifi"
yaml "gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
// Start begins the application from a CLI. // Start begins the application from a CLI.
@ -36,7 +35,7 @@ func Start() error {
// ParseFlags runs the parser. // ParseFlags runs the parser.
func (u *UnifiPoller) ParseFlags(args []string) { func (u *UnifiPoller) ParseFlags(args []string) {
u.Flag = flag.NewFlagSet("unifi-poller", flag.ExitOnError) u.Flag = pflag.NewFlagSet("unifi-poller", pflag.ExitOnError)
u.Flag.Usage = func() { u.Flag.Usage = func() {
fmt.Println("Usage: unifi-poller [--config=filepath] [--version]") fmt.Println("Usage: unifi-poller [--config=filepath] [--version]")
u.Flag.PrintDefaults() u.Flag.PrintDefaults()
@ -91,9 +90,11 @@ func (u *UnifiPoller) Run() (err error) {
if err = u.GetUnifi(); err != nil { if err = u.GetUnifi(); err != nil {
return err return err
} }
u.Logf("Polling UniFi Controller at %s v%s as user %s. Sites: %v", u.UnifiBase, u.ServerVersion, u.UnifiUser, u.Sites)
if err = u.GetInfluxDB(); err != nil { if err = u.GetInfluxDB(); err != nil {
return err return err
} }
u.Logf("Logging Measurements to InfluxDB at %s as user %s", u.InfluxURL, u.InfluxUser)
switch strings.ToLower(u.Mode) { switch strings.ToLower(u.Mode) {
case "influxlambda", "lambdainflux", "lambda_influx", "influx_lambda": case "influxlambda", "lambdainflux", "lambda_influx", "influx_lambda":
u.LogDebugf("Lambda Mode Enabled") u.LogDebugf("Lambda Mode Enabled")
@ -112,9 +113,8 @@ func (u *UnifiPoller) GetInfluxDB() (err error) {
Password: u.InfluxPass, Password: u.InfluxPass,
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "influxdb") return fmt.Errorf("influxdb: %v", err)
} }
u.Logf("Logging Measurements to InfluxDB at %s as user %s", u.InfluxURL, u.InfluxUser)
return nil return nil
} }
@ -123,14 +123,12 @@ func (u *UnifiPoller) GetUnifi() (err error) {
// Create an authenticated session to the Unifi Controller. // Create an authenticated session to the Unifi Controller.
u.Unifi, err = unifi.NewUnifi(u.UnifiUser, u.UnifiPass, u.UnifiBase, u.VerifySSL) u.Unifi, err = unifi.NewUnifi(u.UnifiUser, u.UnifiPass, u.UnifiBase, u.VerifySSL)
if err != nil { if err != nil {
return errors.Wrap(err, "unifi controller") return fmt.Errorf("unifi controller: %v", err)
} }
u.Unifi.ErrorLog = u.LogErrorf // Log all errors. u.Unifi.ErrorLog = u.LogErrorf // Log all errors.
u.Unifi.DebugLog = u.LogDebugf // Log debug messages. u.Unifi.DebugLog = u.LogDebugf // Log debug messages.
u.Logf("Authenticated to UniFi Controller at %s version %s as user %s", u.UnifiBase, u.ServerVersion, u.UnifiUser)
if err := u.CheckSites(); err != nil { if err := u.CheckSites(); err != nil {
return err return err
} }
u.Logf("Polling UniFi Controller Sites: %v", u.Sites)
return nil return nil
} }

View File

@ -7,7 +7,6 @@ import (
"time" "time"
influx "github.com/influxdata/influxdb1-client/v2" influx "github.com/influxdata/influxdb1-client/v2"
"github.com/pkg/errors"
"golift.io/unifi" "golift.io/unifi"
) )
@ -49,9 +48,19 @@ func (u *UnifiPoller) PollController() error {
log.Println("[INFO] Everything checks out! Poller started, interval:", u.Interval.Round(time.Second)) log.Println("[INFO] Everything checks out! Poller started, interval:", u.Interval.Round(time.Second))
ticker := time.NewTicker(u.Interval.Round(time.Second)) ticker := time.NewTicker(u.Interval.Round(time.Second))
for u.LastCheck = range ticker.C { for u.LastCheck = range ticker.C {
_ = u.CollectAndReport() var err error
if u.ReAuth {
// Some users need to re-auth every interval because the cookie times out.
if err = u.GetUnifi(); err != nil {
u.LogError(err, "re-authenticating")
}
}
if err == nil {
// Only run this if the authentication procedure didn't return error.
_ = u.CollectAndReport()
}
if u.MaxErrors >= 0 && u.errorCount > u.MaxErrors { if u.MaxErrors >= 0 && u.errorCount > u.MaxErrors {
return errors.Errorf("reached maximum error count, stopping poller (%d > %d)", u.errorCount, u.MaxErrors) return fmt.Errorf("reached maximum error count, stopping poller (%d > %d)", u.errorCount, u.MaxErrors)
} }
} }
return nil return nil
@ -131,7 +140,7 @@ func (u *UnifiPoller) ReportMetrics(metrics *Metrics) error {
} }
err := u.Write(metrics.BatchPoints) err := u.Write(metrics.BatchPoints)
if err != nil { if err != nil {
return errors.Wrap(err, "influxdb.Write(points)") return fmt.Errorf("influxdb.Write(points): %v", err)
} }
var fields, points int var fields, points int
for _, p := range metrics.Points() { for _, p := range metrics.Points() {