#36 attempt to fix api login auth issue (#38)

* #36 attempt to fix api login auth issue
* update release version number
This commit is contained in:
Steve Brunton 2019-07-02 20:46:19 -04:00 committed by GitHub
parent dcaef1a51e
commit 8e1ece22dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 10 deletions

View File

@ -2,7 +2,7 @@ version: 2
jobs:
build:
docker:
- image: circleci/golang:1.10.4-stretch
- image: circleci/golang:1.12.4-stretch
working_directory: /go/src/github.com/nshttpd/mikrotik-exporter
branches:
only:
@ -11,5 +11,5 @@ jobs:
steps:
- checkout
- setup_remote_docker:
version: 18.05.0-ce
version: 18.06.0-ce
- run: make dockerhub

1
.gitignore vendored
View File

@ -20,3 +20,4 @@
debug
mikrotik-exporter
test-config.yml

View File

@ -1 +1 @@
1.0.7-DEVEL
1.0.7

View File

@ -1,7 +1,13 @@
package collector
import (
"crypto/md5"
"crypto/tls"
"encoding/hex"
"errors"
"fmt"
"io"
"net"
"sync"
"time"
@ -206,12 +212,71 @@ func (c *collector) connectAndCollect(d *config.Device, ch chan<- prometheus.Met
}
func (c *collector) connect(d *config.Device) (*routeros.Client, error) {
var conn net.Conn
var err error
log.WithField("device", d.Name).Debug("trying to Dial")
if !c.enableTLS {
return routeros.DialTimeout(d.Address+apiPort, d.User, d.Password, c.timeout)
conn, err = net.Dial("tcp", d.Address+apiPort)
if err != nil {
return nil, err
}
// return routeros.DialTimeout(d.Address+apiPort, d.User, d.Password, c.timeout)
} else {
tlsCfg := &tls.Config{
InsecureSkipVerify: c.insecureTLS,
}
conn, err = tls.Dial("tcp", d.Address+apiPortTLS, tlsCfg)
if err != nil {
return nil, err
}
}
log.WithField("device", d.Name).Debug("done dialing")
client, err := routeros.NewClient(conn)
if err != nil {
return nil, err
}
log.WithField("device", d.Name).Debug("got client")
log.WithField("device", d.Name).Debug("trying to login")
r, err := client.Run("/login", "=name="+d.User, "=password="+d.Password)
if err != nil {
return nil, err
}
ret, ok := r.Done.Map["ret"]
if !ok {
// Login method post-6.43 one stage, cleartext and no challenge
if r.Done != nil {
return client, nil
}
return nil, errors.New("RouterOS: /login: no ret (challenge) received")
}
tls := &tls.Config{
InsecureSkipVerify: c.insecureTLS,
// Login method pre-6.43 two stages, challenge
b, err := hex.DecodeString(ret)
if err != nil {
return nil, fmt.Errorf("RouterOS: /login: invalid ret (challenge) hex string received: %s", err)
}
return routeros.DialTLSTimeout(d.Address+apiPortTLS, d.User, d.Password, tls, c.timeout)
r, err = client.Run("/login", "=name="+d.User, "=response="+challengeResponse(b, d.Password))
if err != nil {
return nil, err
}
log.WithField("device", d.Name).Debug("done wth login")
return client, nil
//tlsCfg := &tls.Config{
// InsecureSkipVerify: c.insecureTLS,
//}
// return routeros.DialTLSTimeout(d.Address+apiPortTLS, d.User, d.Password, tlsCfg, c.timeout)
}
func challengeResponse(cha []byte, password string) string {
h := md5.New()
h.Write([]byte{0})
_, _ = io.WriteString(h, password)
h.Write(cha)
return fmt.Sprintf("00%x", h.Sum(nil))
}

View File

@ -36,7 +36,7 @@ var (
withOptics = flag.Bool("with-optics", false, "retrieves optical diagnostic metrics")
withWlanSTA = flag.Bool("with-wlansta", false, "retrieves connected wlan station metrics")
withWlanIF = flag.Bool("with-wlanif", false, "retrieves wlan interface metrics")
timeout = flag.Duration("timeout", collector.DefaultTimeout, "timeout when connecting to routers")
timeout = flag.Duration("timeout", collector.DefaultTimeout, "timeout when connecting to devices")
tls = flag.Bool("tls", false, "use tls to connect to routers")
insecure = flag.Bool("insecure", false, "skips verification of server certificate when using TLS (not recommended)")
cfg *config.Config
@ -118,11 +118,11 @@ func startServer() {
http.Handle(*metricsPath, h)
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
_, _ = w.Write([]byte("ok"))
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`<html>
_, _ = w.Write([]byte(`<html>
<head><title>Mikrotik Exporter</title></head>
<body>
<h1>Mikrotik Exporter</h1>