This commit is contained in:
crusader 2017-09-22 18:20:07 +09:00
parent 5a9359c3af
commit 6fb6bc66d8
16 changed files with 317 additions and 216 deletions

View File

@ -2,27 +2,24 @@ package auth
import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"path"
"time"
lfcc "git.loafle.net/commons_go/config"
"git.loafle.net/commons_go/logging"
"git.loafle.net/overflow/overflow_probes/central/api/module"
"git.loafle.net/overflow/overflow_probes/central/client"
"git.loafle.net/overflow/overflow_probes/commons"
"git.loafle.net/overflow/overflow_probes/config"
opuu "git.loafle.net/overflow/overflow_probes/util/url"
)
const (
noAuthConfigFileName = "noauth.json"
noAuthHeaderNoAuthID = "overFlow-NoAuth-ID"
noAuthHeaderNoAuthRegist = "overFlow-NoAuth-Regist"
noAuthHeaderSetNoAuthID = "overFlow-Set-NoAuth-ID"
probeConfigFileName = "probe.json"
noAuthEntryPoint = "/auth"
)
type AuthHandler interface {
@ -30,100 +27,127 @@ type AuthHandler interface {
}
type authHandlers struct {
configDir string
c client.Client
entryURL string
configDir string
noAuthConfigPath string
noAuthConfig config.NoAuthProbeConfig
entryURL string
c client.Client
probeConfigPath string
probeConfig config.ProbeConfig
probeConfigPath string
probeConfig config.ProbeConfig
shutdownChan chan bool
acceptedChan chan bool
deniedChan chan error
}
type NoAuthProbe struct {
APIKey string `json:"apiKey"`
Description string `json:"description"`
}
type NoAuthDescription struct {
Host Host `json:"host"`
Network Network `json:"network"`
}
func New(configDir string) AuthHandler {
h := &authHandlers{
configDir: configDir,
}
func New(configDir string) (AuthHandler, error) {
var err error
var centralURL *url.URL
var noAuthEntryPoint string
var ok bool
if centralURL, err = url.Parse(config.Config.Central.URL); nil != err {
logging.Logger.Error(fmt.Sprintf("Auth: Central URL[%s] is not valid error[%v]", config.Config.Central.URL, err))
return nil
h := &authHandlers{
configDir: configDir,
shutdownChan: make(chan bool),
acceptedChan: make(chan bool),
deniedChan: make(chan error),
}
if noAuthEntryPoint, ok = config.Config.Central.EntryPoints["noauth"]; !ok {
logging.Logger.Error("Auth: NoAuth entry point of Central is not exist")
return nil
if h.entryURL, err = opuu.Join(config.Config.Central.URL, noAuthEntryPoint); nil != err {
return nil, err
}
centralURL.Path = path.Join(centralURL.Path, noAuthEntryPoint)
h.entryURL = centralURL.String()
h.noAuthConfigPath = path.Join(configDir, noAuthConfigFileName)
h.probeConfigPath = path.Join(configDir, probeConfigFileName)
h.noAuthConfigPath = path.Join(configDir, config.NoAuthProbeConfigFileName)
h.probeConfigPath = path.Join(configDir, config.ProbeConfigFileName)
conf := lfcc.New()
if lfcc.Exists(h.noAuthConfigPath) {
if err = conf.Load(&h.noAuthConfig, h.noAuthConfigPath); nil != err {
logging.Logger.Error(fmt.Sprintf("Auth: Loading of NoAuth config file[%s] failed error[%v]", h.noAuthConfigPath, err))
return nil, fmt.Errorf("Auth: Loading of NoAuth config file[%s] failed error[%v]", h.noAuthConfigPath, err)
}
} else {
if err = lfcc.Save(h.noAuthConfig, h.noAuthConfigPath, true); nil != err {
logging.Logger.Error(fmt.Sprintf("Auth: Saving of NoAuth config file[%s] failed error[%v]", h.noAuthConfigPath, err))
return nil, fmt.Errorf("Auth: Saving of NoAuth config file[%s] failed error[%v]", h.noAuthConfigPath, err)
}
}
return h
return h, nil
}
func (h *authHandlers) Listen() error {
var err error
isRegist := true
func (h *authHandlers) Serve() error {
if nil != h.noAuthConfig.DenyDate {
return fmt.Errorf("Cannot start because this probe have been denied from overFlow[%s]", h.noAuthConfig.DenyDate.String())
}
h.c = client.New()
h.c.OnNotify("NoAuthProbeService.accept", h.onNoAuthProbeAccept)
h.c.OnNotify("NoAuthProbeService.deny", h.onNoAuthProbeDeny)
h.c.OnNotify(module.NoAuthProbeService_AcceptNoAuthProbe, h.onNoAuthProbeAccept)
h.c.OnNotify(module.NoAuthProbeService_DenyNoauthProbe, h.onNoAuthProbeDeny)
header := http.Header{}
if "" != h.noAuthConfig.TempKey {
isRegist = false
header[noAuthHeaderNoAuthID] = []string{h.noAuthConfig.TempKey}
var err error
if nil != h.noAuthConfig.TempKey && "" != *h.noAuthConfig.TempKey {
err = h.serveConnect(*h.noAuthConfig.TempKey)
} else {
var enc string
if enc, err = h.getRegistHeader(); nil != err {
err = h.serveRegistration()
}
if nil != err {
return err
}
ListenLoop:
for {
select {
case <-h.shutdownChan:
return errors.New("Shutting down")
case <-h.acceptedChan:
break ListenLoop
case err := <-h.deniedChan:
return err
}
header[noAuthHeaderNoAuthRegist] = []string{enc}
}
return nil
}
func (h *authHandlers) Shutdown(ctx context.Context) error {
h.shutdownChan <- true
return nil
}
func (h *authHandlers) serveRegistration() error {
var err error
header := http.Header{}
var enc string
if enc, err = getRegistHeader(); nil != err {
return err
}
header[module.NoAuthProbeHeader_NoAuthRegist] = []string{enc}
var res *http.Response
if res, err = h.c.Dial(h.entryURL, header, 4096, 4096); nil != err {
return err
}
if isRegist {
h.noAuthConfig.TempKey = res.Header.Get(noAuthHeaderSetNoAuthID)
if err = lfcc.Save(h.noAuthConfig, h.noAuthConfigPath, true); nil != err {
return err
}
tempKey := res.Header.Get(module.NoAuthProbeHeader_SetNoAuthID)
h.noAuthConfig.TempKey = &tempKey
if err = lfcc.Save(h.noAuthConfig, h.noAuthConfigPath, true); nil != err {
return err
}
for {
return nil
}
func (h *authHandlers) serveConnect(noAuthTempKey string) error {
var err error
header := http.Header{}
header[module.NoAuthProbeHeader_NoAuthID] = []string{noAuthTempKey}
var res *http.Response
if res, err = h.c.Dial(h.entryURL, header, 4096, 4096); nil != err {
return err
}
logging.Logger.Debug(fmt.Sprintf("Auth: Connect HTTP Status[%s]", res.Status))
return nil
}
@ -138,59 +162,20 @@ func (h *authHandlers) onNoAuthProbeAccept(method string, params interface{}) {
}
}
h.probeConfig.ID = probeID
h.probeConfig.ID = &probeID
if err = lfcc.Save(h.probeConfig, h.probeConfigPath, true); nil != err {
logging.Logger.Error(fmt.Sprintf("Auth: Saving of Probe config file[%s] failed error[%v]", h.probeConfigPath, err))
}
h.acceptedChan <- true
}
func (h *authHandlers) onNoAuthProbeDeny(method string, params interface{}) {
h.noAuthConfig.DenyDate = time.Now()
n := time.Now()
h.noAuthConfig.DenyDate = &n
if err := lfcc.Save(h.noAuthConfig, h.noAuthConfigPath, true); nil != err {
logging.Logger.Error(fmt.Sprintf("Auth: Saving of NoAuth config file[%s] failed error[%v]", h.noAuthConfigPath, err))
}
}
func (h *authHandlers) getRegistHeader() (string, error) {
var err error
nap := NoAuthProbe{
APIKey: config.Config.Domain.APIKey,
}
nad := NoAuthDescription{}
if err = getHost(&nad.Host); nil != err {
return "", err
}
if err = getNetwork(&nad.Network); nil != err {
return "", err
}
var buf []byte
if buf, err = json.Marshal(nad); nil != err {
return "", err
}
nap.Description = string(buf)
if buf, err = json.Marshal(nap); nil != err {
return "", err
}
logging.Logger.Debug(fmt.Sprintf("%s", string(buf)))
enc := base64.StdEncoding.EncodeToString(buf)
return enc, nil
}
func (h *authHandlers) listen() {
// 1. regist
// 2. wait for accept auth
}
func (h *authHandlers) Shutdown(ctx context.Context) error {
return nil
h.deniedChan <- fmt.Errorf("This probe have been denied from overFlow")
}

View File

@ -1,30 +0,0 @@
package auth
import (
"github.com/shirou/gopsutil/host"
)
type Host struct {
Name string `json:"name"`
OS string `json:"os"`
Platform string `json:"paltform"`
PlatformFamily string `json:"platformFamily"`
PlatformVersion string `json:"platformVersion"`
KernelVersion string `json:"kernelVersion"`
HostID string `json:"hostID"`
}
func getHost(h *Host) error {
if i, err := host.Info(); nil == err {
h.Name = i.Hostname
h.OS = i.OS
h.Platform = i.Platform
h.PlatformFamily = i.PlatformFamily
h.KernelVersion = i.KernelVersion
h.HostID = i.HostID
} else {
return err
}
return nil
}

View File

@ -1,64 +0,0 @@
package auth
import (
"bytes"
"errors"
"net"
"git.loafle.net/commons_go/util/net/gateway"
)
type Network struct {
Name string `json:"name"`
Address string `json:"address"`
Gateway string `json:"gateway"`
MacAddress string `json:"macAddress"`
}
func getNetwork(n *Network) error {
var ip net.IP
var iface string
var err error
if ip, iface, err = gateway.DiscoverGateway(); nil != err {
return err
}
interfaces, err := net.Interfaces()
if err != nil {
return err
}
idx := -1
for _idx, i := range interfaces {
if i.Name == iface {
idx = _idx
break
}
}
if -1 == idx {
return errors.New("Interface of gateway is not exist")
}
i := interfaces[idx]
n.Name = i.Name
n.MacAddress = i.HardwareAddr.String()
n.Gateway = ip.String()
if addrs, err := i.Addrs(); nil == err {
var buffer bytes.Buffer
for _idx, a := range addrs {
if 0 < _idx {
buffer.WriteString("|")
}
buffer.WriteString(a.String())
}
n.Address = buffer.String()
} else {
return err
}
return nil
}

116
auth/registration.go Normal file
View File

@ -0,0 +1,116 @@
package auth
import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"net"
"git.loafle.net/commons_go/util/net/gateway"
"git.loafle.net/overflow/overflow_probes/central/api/module"
"git.loafle.net/overflow/overflow_probes/config"
"github.com/shirou/gopsutil/host"
)
func getRegistHeader() (string, error) {
var err error
nap := module.NoAuthProbe{
APIKey: config.Config.Domain.APIKey,
}
var nad *module.NoAuthProbeDescription
if nad, err = getDescription(); nil != err {
return "", err
}
var buf []byte
if buf, err = json.Marshal(nad); nil != err {
return "", err
}
nap.Description = string(buf)
if buf, err = json.Marshal(nap); nil != err {
return "", err
}
enc := base64.StdEncoding.EncodeToString(buf)
return enc, nil
}
func getDescription() (*module.NoAuthProbeDescription, error) {
nad := &module.NoAuthProbeDescription{}
if err := getHost(&nad.Host); nil != err {
return nil, err
}
if err := getNetwork(&nad.Network); nil != err {
return nil, err
}
return nad, nil
}
func getHost(h *module.NoAuthProbeDescriptionHost) error {
if i, err := host.Info(); nil == err {
h.Name = i.Hostname
h.OS = i.OS
h.Platform = i.Platform
h.PlatformFamily = i.PlatformFamily
h.KernelVersion = i.KernelVersion
h.HostID = i.HostID
} else {
return err
}
return nil
}
func getNetwork(n *module.NoAuthProbeDescriptionNetwork) error {
var ip net.IP
var iface string
var err error
if ip, iface, err = gateway.DiscoverGateway(); nil != err {
return err
}
interfaces, err := net.Interfaces()
if err != nil {
return err
}
idx := -1
for _idx, i := range interfaces {
if i.Name == iface {
idx = _idx
break
}
}
if -1 == idx {
return errors.New("Interface of gateway is not exist")
}
i := interfaces[idx]
n.Name = i.Name
n.MacAddress = i.HardwareAddr.String()
n.Gateway = ip.String()
if addrs, err := i.Addrs(); nil == err {
var buffer bytes.Buffer
for _idx, a := range addrs {
if 0 < _idx {
buffer.WriteString("|")
}
buffer.WriteString(a.String())
}
n.Address = buffer.String()
} else {
return err
}
return nil
}

View File

@ -0,0 +1,45 @@
package module
import "time"
const (
NoAuthProbeHeader_NoAuthID = "overFlow-NoAuth-ID"
NoAuthProbeHeader_NoAuthRegist = "overFlow-NoAuth-Regist"
NoAuthProbeHeader_SetNoAuthID = "overFlow-Set-NoAuth-ID"
)
type NoAuthProbe struct {
ID uint64 `json:"id"`
Description string `json:"description"`
TempProbeKey string `json:"tempProbeKey"`
CreateDate time.Time `json:"createDate"`
APIKey string `json:"apiKey"`
}
const (
NoAuthProbeService_Regist = "NoAuthProbeService.regist"
NoAuthProbeService_AcceptNoAuthProbe = "NoAuthProbeService.acceptNoAuthProbe"
NoAuthProbeService_DenyNoauthProbe = "NoAuthProbeService.denyNoauthProbe"
)
type NoAuthProbeDescription struct {
Host NoAuthProbeDescriptionHost `json:"host"`
Network NoAuthProbeDescriptionNetwork `json:"network"`
}
type NoAuthProbeDescriptionHost struct {
Name string `json:"name"`
OS string `json:"os"`
Platform string `json:"paltform"`
PlatformFamily string `json:"platformFamily"`
PlatformVersion string `json:"platformVersion"`
KernelVersion string `json:"kernelVersion"`
HostID string `json:"hostID"`
}
type NoAuthProbeDescriptionNetwork struct {
Name string `json:"name"`
Address string `json:"address"`
Gateway string `json:"gateway"`
MacAddress string `json:"macAddress"`
}

View File

@ -20,6 +20,7 @@ const (
type (
OnNotifyFunc func(method string, params interface{})
OnCloseFunc func(code int, text string)
)
type ServerError string
@ -54,6 +55,7 @@ type Client interface {
Call(method string, args interface{}, result interface{}) error
Notify(method string, args interface{}) error
OnNotify(method string, cb OnNotifyFunc)
OnClose(cb OnCloseFunc)
Shutdown(ctx context.Context) error
}
@ -68,6 +70,7 @@ type client struct {
closing bool // user has called Close
shutdown bool // server has told us to stop
onNotifyHandlers map[string][]OnNotifyFunc
onCloseHandlers []OnCloseFunc
}
func New() Client {
@ -75,6 +78,7 @@ func New() Client {
requestID: 0,
pending: make(map[uint64]*Call),
onNotifyHandlers: make(map[string][]OnNotifyFunc),
onCloseHandlers: make([]OnCloseFunc, 1),
}
return c
@ -93,6 +97,8 @@ func (c *client) Dial(url string, header http.Header, readBufSize int, writeBufS
return nil, err
}
c.conn.SetCloseHandler(c.connCloseHandler)
go c.input()
return res, nil
@ -128,6 +134,10 @@ func (c *client) OnNotify(method string, cb OnNotifyFunc) {
hs = append(hs, cb)
}
func (c *client) OnClose(cb OnCloseFunc) {
c.onCloseHandlers = append(c.onCloseHandlers, cb)
}
func (c *client) Shutdown(ctx context.Context) error {
c.mutex.Lock()
if c.closing {
@ -292,3 +302,11 @@ func (c *client) onNotification(noti protocol.Notification) error {
return err
}
func (c *client) connCloseHandler(code int, text string) error {
for _, h := range c.onCloseHandlers {
h(code, text)
}
return nil
}

View File

@ -3,6 +3,6 @@ package commons
import "context"
type Handler interface {
Listen() error
Serve() error
Shutdown(ctx context.Context) error
}

View File

@ -3,10 +3,6 @@
"apikey": "52abd6fd57e511e7ac52080027658d13"
},
"central": {
"url": "ws://127.0.0.1:19190",
"entryPoints": {
"noauth": "/auth",
"probe": "/probe"
}
"url": "ws://127.0.0.1:19190"
}
}

View File

@ -1,5 +1,9 @@
package config
const (
ConfigFileName = "config.json"
)
var Config AllConfig
type AllConfig struct {

View File

@ -2,7 +2,11 @@ package config
import "time"
const (
NoAuthProbeConfigFileName = "noauthprobe.json"
)
type NoAuthProbeConfig struct {
TempKey string `json:"tempKey" yaml:"tempKey" toml:"tempKey"`
DenyDate time.Time `json:"denyDate" yaml:"denyDate" toml:"denyDate"`
TempKey *string `json:"tempKey,omitempty" yaml:"tempKey" toml:"tempKey"`
DenyDate *time.Time `json:"denyDate,omitempty" yaml:"denyDate" toml:"denyDate"`
}

View File

@ -1,5 +1,9 @@
package config
const (
ProbeConfigFileName = "probe.json"
)
type ProbeConfig struct {
ID string `json:"id" yaml:"id" toml:"id"`
ID *string `json:"id,omitempty" yaml:"id" toml:"id"`
}

View File

@ -150,16 +150,19 @@ func main() {
os.Exit(0)
}
handler = auth.New(confDir)
if handler, err = auth.New(confDir); nil != err {
logging.Logger.Error(fmt.Sprintf("Auth: error: %v", err))
os.Exit(1)
}
go func() {
if err := handler.Listen(); err != nil {
if err := handler.Serve(); err != nil {
logging.Logger.Error(fmt.Sprintf("Probe: Authenticator error: %v", err))
return
}
handler = probe.New(confDir)
if err := handler.Listen(); err != nil {
if err := handler.Serve(); err != nil {
logging.Logger.Error(fmt.Sprintf("Probe: error: %v", err))
return
}

View File

@ -1 +0,0 @@
{"tempID":""}

1
noauthprobe.json Normal file
View File

@ -0,0 +1 @@
{"tempKey":"3ca894e0-373a-47d9-a1dd-e4fbd4e214a7"}

View File

@ -22,7 +22,7 @@ type probe struct {
configDir string
}
func (p *probe) Listen() error {
func (p *probe) Serve() error {
return nil
}

20
util/url/url.go Normal file
View File

@ -0,0 +1,20 @@
package util
import (
"net/url"
"path"
)
// Join is concat URL string and path
// ex) http://127.0.0.1/ and /entry
func Join(u string, p string) (string, error) {
var err error
var rURL *url.URL
if rURL, err = url.Parse(u); nil != err {
return "", err
}
rURL.Path = path.Join(rURL.Path, p)
return rURL.String(), nil
}