Unifi login

This commit is contained in:
Ian Gulliver
2020-07-26 17:16:08 +00:00
parent 08d3cff905
commit c1f41b038b
4 changed files with 181 additions and 1 deletions

1
go.mod
View File

@@ -7,4 +7,5 @@ require (
github.com/mdlayher/lldp v0.0.0-20150915211757-afd9f83164c5 github.com/mdlayher/lldp v0.0.0-20150915211757-afd9f83164c5
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065
github.com/vishvananda/netlink v1.1.0 github.com/vishvananda/netlink v1.1.0
gopkg.in/yaml.v2 v2.3.0
) )

3
go.sum
View File

@@ -21,3 +21,6 @@ golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 h1:/d2cWp6PSamH4jDPFLyO150psQdqvtoNX8Zjg3AQ31g= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 h1:/d2cWp6PSamH4jDPFLyO150psQdqvtoNX8Zjg3AQ31g=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

14
main.go
View File

@@ -31,11 +31,23 @@ func main() {
} }
log.Printf("UniFi API URL: %s", api) log.Printf("UniFi API URL: %s", api)
/*
upstream, err := getUpstream(link.Attrs().Name) upstream, err := getUpstream(link.Attrs().Name)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
log.Printf("Connected to %s [%s] on %s", upstream.device, upstream.addr, upstream.port) log.Printf("Connected to %s [%s] on %s", upstream.device, upstream.addr, upstream.port)
*/
unifi, err := NewClient(api)
if err != nil {
log.Fatal(err)
}
err = unifi.Login()
if err != nil {
log.Fatal(err)
}
} }
type upstream struct { type upstream struct {
@@ -137,7 +149,7 @@ func findApis(start_ip, end_ip uint32) ([]string, error) {
defer cancel() defer cancel()
url := fmt.Sprintf( url := fmt.Sprintf(
"https://%d.%d.%d.%d/", "https://%d.%d.%d.%d",
ip >> 24 & 0xff, ip >> 24 & 0xff,
ip >> 16 & 0xff, ip >> 16 & 0xff,
ip >> 8 & 0xff, ip >> 8 & 0xff,

164
unifi.go Normal file
View File

@@ -0,0 +1,164 @@
package main
import (
"bufio"
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"log"
"net/http"
"net/http/cookiejar"
"os"
"path"
"strings"
"time"
"gopkg.in/yaml.v2"
)
type Client struct {
http_client *http.Client
base_url string
}
func NewClient(base_url string) (*Client, error) {
jar, err := cookiejar.New(nil)
if err != nil {
return nil, err
}
return &Client{
http_client: &http.Client{
Timeout: 5 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
Jar: jar,
},
base_url: base_url,
}, nil
}
type Creds struct {
Username string `json:"username"`
Password string `json:"password"`
}
type ErrorResp struct {
Errors []string
}
func (c *Client) Login() error {
needSave := false
creds, err := loadCreds()
if err != nil {
creds, err = promptCreds()
if err != nil {
return err
}
needSave = true
}
body, err := json.Marshal(creds)
if err != nil {
return err
}
req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/auth/login", c.base_url), bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
resp, err := c.http_client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
dec := json.NewDecoder(resp.Body)
error_resp := ErrorResp{}
err = dec.Decode(&error_resp)
if err != nil {
return err
}
return fmt.Errorf("Failed to log into UniFi with saved credentials (\"%s\"). Delete %s to prompt again.", error_resp.Errors[0], credPath())
}
log.Printf("Logged into UniFi as %s", creds.Username)
if needSave {
err = creds.Save()
if err != nil {
return err
}
}
return nil
}
func loadCreds() (*Creds, error) {
fh, err := os.OpenFile(credPath(), os.O_RDONLY, 0)
if err != nil {
return nil, err
}
defer fh.Close()
dec := yaml.NewDecoder(fh)
ret := &Creds{}
err = dec.Decode(ret)
if err != nil {
return nil, err
}
return ret, nil
}
func promptCreds() (*Creds, error) {
reader := bufio.NewReader(os.Stdin)
fmt.Print("UniFi username: ")
username, err := reader.ReadString('\n')
if err != nil {
return nil, err
}
fmt.Print("UniFi password: ")
password, err := reader.ReadString('\n')
if err != nil {
return nil, err
}
return &Creds{
Username: strings.TrimSuffix(username, "\n"),
Password: strings.TrimSuffix(password, "\n"),
}, nil
}
func (c *Creds) Save() error {
fh, err := os.OpenFile(credPath(), os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return err
}
defer fh.Close()
enc := yaml.NewEncoder(fh)
defer enc.Close()
err = enc.Encode(c)
if err != nil {
return err
}
log.Printf("Saved credentials to %s", credPath())
return nil
}
func credPath() string {
return path.Join(os.Getenv("HOME"), ".netperfect.creds")
}