diff --git a/README.md b/README.md index 2c00cf21..4f1dbe61 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,19 @@ auth_opt_backends files, postgres, jwt Set all other plugin options below in the same file. +#### Using clientid as username + +You may choose to override chedk against `username` to be done against `clientid` by setting this option: + +``` +auth_opt_use_clientid_as_username true +``` + +Notice this will effectively change `username` to be the same as `clientid` at the top level, so every check, +including cached ones, will drop Mosquitto's passed `username` and use `clientid` instead. + +This option default to false if not given or anything but `true` is set to its value. + #### Cache There are 2 types of caches supported: an in memory one using [go-cache](https://github.com/patrickmn/go-cache), or a Redis backed one. diff --git a/cache/cache.go b/cache/cache.go index e195b416..259f77d4 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -182,7 +182,7 @@ func (s *goStore) CheckAuthRecord(ctx context.Context, username, password string return s.checkRecord(ctx, record, expirationWithJitter(s.authExpiration, s.authJitter)) } -//CheckAclCache checks if the username/topic/clientid/acc mix is present in the cache. Return if it's present and, if so, if it was granted privileges. +// CheckAclCache checks if the username/topic/clientid/acc mix is present in the cache. Return if it's present and, if so, if it was granted privileges. func (s *goStore) CheckACLRecord(ctx context.Context, username, topic, clientid string, acc int) (bool, bool) { record := toACLRecord(username, topic, clientid, acc, s.h) return s.checkRecord(ctx, record, expirationWithJitter(s.aclExpiration, s.aclJitter)) @@ -211,7 +211,7 @@ func (s *redisStore) CheckAuthRecord(ctx context.Context, username, password str return s.checkRecord(ctx, record, s.authExpiration) } -//CheckAclCache checks if the username/topic/clientid/acc mix is present in the cache. Return if it's present and, if so, if it was granted privileges. +// CheckAclCache checks if the username/topic/clientid/acc mix is present in the cache. Return if it's present and, if so, if it was granted privileges. func (s *redisStore) CheckACLRecord(ctx context.Context, username, topic, clientid string, acc int) (bool, bool) { record := toACLRecord(username, topic, clientid, acc, s.h) return s.checkRecord(ctx, record, s.aclExpiration) @@ -266,7 +266,7 @@ func (s *goStore) SetAuthRecord(ctx context.Context, username, password string, return nil } -//SetAclCache sets a mix, granted option and expiration time. +// SetAclCache sets a mix, granted option and expiration time. func (s *goStore) SetACLRecord(ctx context.Context, username, topic, clientid string, acc int, granted string) error { record := toACLRecord(username, topic, clientid, acc, s.h) s.client.Set(record, granted, expirationWithJitter(s.aclExpiration, s.aclJitter)) @@ -280,7 +280,7 @@ func (s *redisStore) SetAuthRecord(ctx context.Context, username, password strin return s.setRecord(ctx, record, granted, expirationWithJitter(s.authExpiration, s.authJitter)) } -//SetAclCache sets a mix, granted option and expiration time. +// SetAclCache sets a mix, granted option and expiration time. func (s *redisStore) SetACLRecord(ctx context.Context, username, topic, clientid string, acc int, granted string) error { record := toACLRecord(username, topic, clientid, acc, s.h) return s.setRecord(ctx, record, granted, expirationWithJitter(s.aclExpiration, s.aclJitter)) diff --git a/go-auth.go b/go-auth.go index 32bac7c2..2c87ab83 100644 --- a/go-auth.go +++ b/go-auth.go @@ -16,15 +16,16 @@ import ( ) type AuthPlugin struct { - backends *bes.Backends - useCache bool - logLevel log.Level - logDest string - logFile string - ctx context.Context - cache cache.Store - hasher hashing.HashComparer - retryCount int + backends *bes.Backends + useCache bool + logLevel log.Level + logDest string + logFile string + ctx context.Context + cache cache.Store + hasher hashing.HashComparer + retryCount int + useClientidAsUsername bool } // errors to signal mosquitto @@ -63,6 +64,13 @@ func AuthPluginInit(keys []*C.char, values []*C.char, authOptsNum int, version * } } + if useClientidAsUsername, ok := authOpts["use_clientid_as_username"]; ok && strings.Replace(useClientidAsUsername, " ", "", -1) == "true" { + log.Info("clientid will be used as username on checks") + authPlugin.useClientidAsUsername = true + } else { + authPlugin.useClientidAsUsername = false + } + //Check if log level is given. Set level if any valid option is given. if logLevel, ok := authOpts["log_level"]; ok { logLevel = strings.Replace(logLevel, " ", "", -1) @@ -304,6 +312,9 @@ func authUnpwdCheck(username, password, clientid string) (bool, error) { var cached bool var granted bool var err error + + username = setUsername(username, clientid) + if authPlugin.useCache { log.Debugf("checking auth cache for %s", username) cached, granted = authPlugin.cache.CheckAuthRecord(authPlugin.ctx, username, password) @@ -358,6 +369,9 @@ func authAclCheck(clientid, username, topic string, acc int) (bool, error) { var cached bool var granted bool var err error + + username = setUsername(username, clientid) + if authPlugin.useCache { log.Debugf("checking acl cache for %s", username) cached, granted = authPlugin.cache.CheckACLRecord(authPlugin.ctx, username, topic, clientid, acc) @@ -401,4 +415,12 @@ func AuthPluginCleanup() { authPlugin.backends.Halt() } +func setUsername(username, clientid string) string { + if authPlugin.useClientidAsUsername { + return clientid + } + + return username +} + func main() {}