Added custom plugin option.

This commit is contained in:
Ignacio Gómez 2018-01-05 15:58:43 -03:00
parent aecaa5524e
commit 2f91f43998
3 changed files with 261 additions and 77 deletions

View File

@ -12,6 +12,8 @@ import (
b64 "encoding/base64"
"plugin"
goredis "github.com/go-redis/redis"
bes "github.com/iegomez/mosquitto-go-auth/backends"
)
@ -33,6 +35,12 @@ type CommonData struct {
Http bes.HTTP
Sqlite bes.Sqlite
Mongo bes.Mongo
Plugin *plugin.Plugin
PInit func(map[string]string, log.Level) error
PGetName func() string
PGetUser func(username, password string) bool
PGetSuperuser func(username string) bool
PCheckAcl func(username, topic, clientid string, acc int) bool
Superusers []string
AclCacheSeconds int64
AuthCacheSeconds int64
@ -60,6 +68,7 @@ var allowedBackends = map[string]bool{
"mysql": true,
"sqlite": true,
"mongo": true,
"plugin": true,
}
var backends []string
var authOpts map[string]string
@ -141,6 +150,87 @@ func AuthPluginInit(keys []string, values []string, authOptsNum int) {
var beIface Backend
var bErr error
if bename == "plugin" {
plug, plErr := plugin.Open(authOpts["plugin_path"])
if plErr != nil {
log.Errorf("Could not init custom plugin: %s", plErr)
commonData.Plugin = nil
} else {
commonData.Plugin = plug
plInit, piErr := commonData.Plugin.Lookup("Init")
if piErr != nil {
log.Errorf("Couldn't find func Init in plugin: %s", plErr)
commonData.Plugin = nil
continue
}
initFunc := plInit.(func(authOpts map[string]string, logLevel log.Level) error)
ipErr := initFunc(authOpts, commonData.LogLevel)
if ipErr != nil {
log.Errorf("Couldn't init plugin: %s", ipErr)
commonData.Plugin = nil
continue
}
commonData.PInit = initFunc
plName, gErr := commonData.Plugin.Lookup("GetName")
if gErr != nil {
log.Errorf("Couldn't find func GetName in plugin: %s", gErr)
commonData.Plugin = nil
continue
}
nameFunc := plName.(func() string)
commonData.PGetName = nameFunc
plGetUser, pgErr := commonData.Plugin.Lookup("GetUser")
if pgErr != nil {
log.Errorf("Couldn't find func GetUser in plugin: %s", pgErr)
commonData.Plugin = nil
continue
}
getUserFunc := plGetUser.(func(username, password string) bool)
commonData.PGetUser = getUserFunc
if pgErr != nil {
log.Errorf("Couldn't find func GetUser in plugin: %s", pgErr)
commonData.Plugin = nil
continue
}
plGetSuperuser, psErr := commonData.Plugin.Lookup("GetSuperuser")
if psErr != nil {
log.Errorf("Couldn't find func GetSuperuser in plugin: %s", psErr)
commonData.Plugin = nil
continue
}
getSuperuserFunc := plGetSuperuser.(func(username string) bool)
commonData.PGetSuperuser = getSuperuserFunc
plCheckAcl, pcErr := commonData.Plugin.Lookup("CheckAcl")
if pcErr != nil {
log.Errorf("Couldn't find func CheckAcl in plugin: %s", pcErr)
commonData.Plugin = nil
continue
}
checkAclFunc := plCheckAcl.(func(username, topic, clientid string, acc int) bool)
commonData.PCheckAcl = checkAclFunc
log.Infof("Backend registered: %s\n", commonData.PGetName())
}
} else {
if bename == "postgres" {
beIface, bErr = bes.NewPostgres(authOpts, commonData.LogLevel)
commonData.Postgres = beIface.(bes.Postgres)
@ -172,6 +262,7 @@ func AuthPluginInit(keys []string, values []string, authOptsNum int) {
} else {
log.Infof("Backend registered: %s\n", beIface.GetName())
}
}
}
@ -287,6 +378,10 @@ func AuthUnpwdCheck(username, password string) bool {
validPrefix, bename := CheckPrefix(username)
if validPrefix {
if bename == "plugin" {
authenticated = CheckPluginAuth(username, password)
} else {
var backend Backend
if bename == "postgres" {
@ -311,12 +406,23 @@ func AuthUnpwdCheck(username, password string) bool {
authenticated = true
log.Debugf("user %s authenticated with backend %s\n", username, backend.GetName())
}
}
} else {
//If there's no valid prefix, check all backends.
authenticated = CheckBackendsAuth(username, password)
//If not authenticated, check for a present plugin
if !authenticated {
authenticated = CheckPluginAuth(username, password)
}
}
} else {
authenticated = CheckBackendsAuth(username, password)
//If not authenticated, check for a present plugin
if !authenticated {
authenticated = CheckPluginAuth(username, password)
}
}
if commonData.UseCache {
@ -352,6 +458,11 @@ func AuthAclCheck(clientid, username, topic string, acc int) bool {
validPrefix, bename := CheckPrefix(username)
if validPrefix {
if bename == "plugin" {
aclCheck = CheckPluginAcl(username, topic, clientid, acc)
} else {
var backend Backend
if bename == "postgres" {
@ -386,13 +497,22 @@ func AuthAclCheck(clientid, username, topic string, acc int) bool {
aclCheck = true
}
}
}
} else {
//If there's no valid prefix, check all backends.
aclCheck = CheckBackendsAcl(username, topic, clientid, acc)
//If acl hasn't passed, check for plugin.
if !aclCheck {
aclCheck = CheckPluginAcl(username, topic, clientid, acc)
}
}
} else {
aclCheck = CheckBackendsAcl(username, topic, clientid, acc)
//If acl hasn't passed, check for plugin.
if !aclCheck {
aclCheck = CheckPluginAcl(username, topic, clientid, acc)
}
}
if commonData.UseCache {
@ -485,6 +605,10 @@ func CheckBackendsAuth(username, password string) bool {
for _, bename := range backends {
if bename == "plugin" {
continue
}
var backend Backend
if bename == "postgres" {
@ -524,6 +648,10 @@ func CheckBackendsAcl(username, topic, clientid string, acc int) bool {
for _, bename := range backends {
if bename == "plugin" {
continue
}
var backend Backend
if bename == "postgres" {
@ -555,6 +683,10 @@ func CheckBackendsAcl(username, topic, clientid string, acc int) bool {
if !aclCheck {
for _, bename := range backends {
if bename == "plugin" {
continue
}
var backend Backend
if bename == "postgres" {
@ -588,4 +720,23 @@ func CheckBackendsAcl(username, topic, clientid string, acc int) bool {
}
//CheckPluginAuth checks that the plugin is not nil and returns the plugins auth response.
func CheckPluginAuth(username, password string) bool {
if commonData.Plugin != nil {
return commonData.PGetUser(username, password)
}
return false
}
//CheckPluginAcl checks that the plugin is not nil and returns the superuser/acl response.
func CheckPluginAcl(username, topic, clientid string, acc int) bool {
if commonData.Plugin != nil {
aclCheck := commonData.PGetSuperuser(username)
if !aclCheck {
aclCheck = commonData.PCheckAcl(username, topic, clientid, acc)
}
}
return false
}
func main() {}

2
plugin/Makefile Normal file
View File

@ -0,0 +1,2 @@
all:
go build -buildmode=plugin

31
plugin/main.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
log "github.com/sirupsen/logrus"
)
func Init(authOpts map[string]string, logLevel log.Level) error {
//Initialize your plugin with the necessary options
log.Infof("Plugin initialized!")
log.Infof("Received %d options.", len(authOpts))
return nil
}
func GetUser(username, password string) bool {
log.Infof("Checking get user with custom plugin.")
return false
}
func GetSuperuser(username string) bool {
log.Infof("Checking get superuser with custom plugin.")
return false
}
func CheckAcl(username, topic, clientid string, acc int) bool {
log.Infof("Checking acl with custom plugin.")
return false
}
func GetName() string {
return "Custom plugin"
}