diff --git a/README.md b/README.md index 65cedd0..331d4e4 100644 --- a/README.md +++ b/README.md @@ -855,32 +855,32 @@ There are no requirements, as the tests create (and later delete) the DB and tab The `jwt` backend is for auth with a JWT remote API, a local DB, a JavaScript VM interpreter or an ACL file. Global otions for JWT are: -| Option | default | Mandatory | Meaning | -| ------------------------- | ----------------- | :---------: | ------------------------------------------------------- | -| jwt_mode | | Y | local, remote, js, files | -| jwt_parse_token | false | N | Parse token in remote/js modes | -| jwt_secret | | Y/N | JWT secret, required for local mode, optional otherwise | -| jwt_userfield | | N | When `Username`, expect `username` as part of claims | -| jwt_skip_user_expiration | false | N | Skip token expiration in user/superuser checks | -| jwt_skip_acl_expiration | false | N | Skip token expiration in ACL checks | - +| Option | default | Mandatory | Meaning | +| ------------------------ | --------- | :-------: | ------------------------------------------------------- | +| jwt_mode | | Y | local, remote, js, files | +| jwt_parse_token | false | N | Parse token in remote/js modes | +| jwt_secret | | Y/N | JWT secret, required for local mode, optional otherwise | +| jwt_userfield | | N | When `Username`, expect `username` as part of claims | +| jwt_skip_user_expiration | false | N | Skip token expiration in user/superuser checks | +| jwt_skip_acl_expiration | false | N | Skip token expiration in ACL checks | +| jwt_user_agent | mosquitto | N | User agent for requests | #### Remote mode The following `auth_opt_` options are supported by the `jwt` backend when remote is set to true: -| Option | default | Mandatory | Meaning | -| ------------------------- | ----------------- | :---------: | ------------------------------------------- | -| jwt_host | | Y | API server host name or ip | -| jwt_port | | Y | TCP port number | -| jwt_getuser_uri | | Y | URI for check username/password | -| jwt_superuser_uri | | N | URI for check superuser | -| jwt_aclcheck_uri | | Y | URI for check acl | -| jwt_with_tls | false | N | Use TLS on connect | -| jwt_verify_peer | false | N | Whether to verify peer for tls | -| jwt_response_mode | status | N | Response type (status, json, text) | -| jwt_params_mode | json | N | Data type (json, form) | - +| Option | default | Mandatory | Meaning | +| ----------------- | --------- | :-------: | ---------------------------------- | +| jwt_host | | Y | API server host name or ip | +| jwt_port | | Y | TCP port number | +| jwt_getuser_uri | | Y | URI for check username/password | +| jwt_superuser_uri | | N | URI for check superuser | +| jwt_aclcheck_uri | | Y | URI for check acl | +| jwt_with_tls | false | N | Use TLS on connect | +| jwt_verify_peer | false | N | Whether to verify peer for tls | +| jwt_response_mode | status | N | Response type (status, json, text) | +| jwt_params_mode | json | N | Data type (json, form) | +| jwt_user_agent | mosquitto | N | User agent for requests | URIs (like jwt_getuser_uri) are expected to be in the form `/path`. For example, if jwt_with_tls is `false`, jwt_host is `localhost`, jwt_port `3000` and jwt_getuser_uri is `/user`, mosquitto will send a POST request to `http://localhost:3000/user` to get a response to check against. How data is sent (either json encoded or as form values) and received (as a simple http status code, a json encoded response or plain text), is given by options jwt_response_mode and jwt_params_mode. @@ -1120,20 +1120,19 @@ The `http` backend is very similar to the JWT one, but instead of a jwt token it The following `auth_opt_` options are supported: - -| Option | default | Mandatory | Meaning | -| ------------------ | ----------------- | :---------: | ---------- | -| http_host | | Y | IP address,will skip dns lookup | -| http_port | | Y | TCP port number | -| http_getuser_uri | | Y | URI for check username/password | -| http_superuser_uri | | N | URI for check superuser | -| http_aclcheck_uri | | Y | URI for check acl | -| http_with_tls | false | N | Use TLS on connect | -| http_verify_peer | false | N | Whether to verify peer for tls | -| http_response_mode | status | N | Response type (status, json, text)| -| http_params_mode | json | N | Data type (json, form) | -| http_timeout | 5 | N | Timeout in seconds | - +| Option | default | Mandatory | Meaning | +| ------------------ | --------- | :-------: | ---------------------------------- | +| http_host | | Y | IP address,will skip dns lookup | +| http_port | | Y | TCP port number | +| http_getuser_uri | | Y | URI for check username/password | +| http_superuser_uri | | N | URI for check superuser | +| http_aclcheck_uri | | Y | URI for check acl | +| http_with_tls | false | N | Use TLS on connect | +| http_verify_peer | false | N | Whether to verify peer for tls | +| http_response_mode | status | N | Response type (status, json, text) | +| http_params_mode | json | N | Data type (json, form) | +| http_timeout | 5 | N | Timeout in seconds | +| http_user_agent | mosquitto | N | User Agent to use in requests | #### Response mode diff --git a/auth-plugin.c b/auth-plugin.c index 78f8030..a1c23ce 100644 --- a/auth-plugin.c +++ b/auth-plugin.c @@ -52,7 +52,12 @@ int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_auth_opt *auth GoSlice keysSlice = {keys, auth_opt_count, auth_opt_count}; GoSlice valuesSlice = {values, auth_opt_count, auth_opt_count}; - AuthPluginInit(keysSlice, valuesSlice, opts_count); + char versionArray[10]; + sprintf(versionArray, "%i.%i.%i", LIBMOSQUITTO_MAJOR, LIBMOSQUITTO_MINOR, LIBMOSQUITTO_REVISION); + + GoString version = {versionArray, strlen(versionArray)}; + + AuthPluginInit(keysSlice, valuesSlice, opts_count, version); return MOSQ_ERR_SUCCESS; } diff --git a/backends/backends.go b/backends/backends.go index a746f1a..b47292d 100644 --- a/backends/backends.go +++ b/backends/backends.go @@ -48,6 +48,9 @@ const ( aclCheck = "acl" userCheck = "user" superuserCheck = "superuser" + + // other constants + defaultUserAgent = "mosquitto" ) // AllowedBackendsOptsPrefix serves as a check for allowed backends and a map from backend to expected opts prefix. @@ -66,7 +69,7 @@ var allowedBackendsOptsPrefix = map[string]string{ } // Initialize sets general options, tries to build the backends and register their checkers. -func Initialize(authOpts map[string]string, logLevel log.Level) (*Backends, error) { +func Initialize(authOpts map[string]string, logLevel log.Level, version string) (*Backends, error) { b := &Backends{ backends: make(map[string]Backend), @@ -99,7 +102,7 @@ func Initialize(authOpts map[string]string, logLevel log.Level) (*Backends, erro } } - err := b.addBackends(authOpts, logLevel, backends) + err := b.addBackends(authOpts, logLevel, backends, version) if err != nil { return nil, err } @@ -114,7 +117,7 @@ func Initialize(authOpts map[string]string, logLevel log.Level) (*Backends, erro return b, nil } -func (b *Backends) addBackends(authOpts map[string]string, logLevel log.Level, backends []string) error { +func (b *Backends) addBackends(authOpts map[string]string, logLevel log.Level, backends []string, version string) error { for _, bename := range backends { var beIface Backend var err error @@ -130,7 +133,7 @@ func (b *Backends) addBackends(authOpts map[string]string, logLevel log.Level, b b.backends[postgresBackend] = beIface.(Postgres) } case jwtBackend: - beIface, err = NewJWT(authOpts, logLevel, hasher) + beIface, err = NewJWT(authOpts, logLevel, hasher, version) if err != nil { log.Fatalf("Backend register error: couldn't initialize %s backend with error %s.", bename, err) } else { @@ -162,7 +165,7 @@ func (b *Backends) addBackends(authOpts map[string]string, logLevel log.Level, b b.backends[mysqlBackend] = beIface.(Mysql) } case httpBackend: - beIface, err = NewHTTP(authOpts, logLevel) + beIface, err = NewHTTP(authOpts, logLevel, version) if err != nil { log.Fatalf("Backend register error: couldn't initialize %s backend with error %s.", bename, err) } else { diff --git a/backends/backends_test.go b/backends/backends_test.go index d638490..f1117dd 100644 --- a/backends/backends_test.go +++ b/backends/backends_test.go @@ -43,16 +43,18 @@ func TestBackends(t *testing.T) { passwordHash := "PBKDF2$sha512$100000$2WQHK5rjNN+oOT+TZAsWAw==$TDf4Y6J+9BdnjucFQ0ZUWlTwzncTjOOeE00W4Qm8lfPQyPCZACCjgfdK353jdGFwJjAf6vPAYaba9+z4GWK7Gg==" clientid := "clientid" + version := "2.0.0" + Convey("Missing or empty backends option should result in an error", t, func() { authOpts["backends"] = "" - _, err := Initialize(authOpts, log.DebugLevel) + _, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "missing or blank option backends") delete(authOpts, "backends") - _, err = Initialize(authOpts, log.DebugLevel) + _, err = Initialize(authOpts, log.DebugLevel, version) So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "missing or blank option backends") }) @@ -60,7 +62,7 @@ func TestBackends(t *testing.T) { Convey("An unknown backend should result in an error", t, func() { authOpts["backends"] = "unknown" - _, err := Initialize(authOpts, log.DebugLevel) + _, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "unknown backend unknown") }) @@ -70,7 +72,7 @@ func TestBackends(t *testing.T) { authOpts["files_register"] = "user" authOpts["redis_register"] = "unknown" - _, err := Initialize(authOpts, log.DebugLevel) + _, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldNotBeNil) So(err.Error(), ShouldEqual, "unsupported check unknown found for backend redis") }) @@ -89,7 +91,7 @@ func TestBackends(t *testing.T) { username = "test1" redis.conn.Set(ctx, username, passwordHash, 0) - b, err := Initialize(authOpts, log.DebugLevel) + b, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) // Redis only contains test1, while files has a bunch of more users. @@ -140,7 +142,7 @@ func TestBackends(t *testing.T) { // Insert a user to test auth redis.conn.Set(ctx, username, passwordHash, 0) - b, err := Initialize(authOpts, log.DebugLevel) + b, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) tt1, err1 := b.AuthUnpwdCheck(username, password, clientid) @@ -197,7 +199,7 @@ func TestBackends(t *testing.T) { // Set it as superuser. redis.conn.Set(ctx, fmt.Sprintf("%s:su", username), "true", 0) - b, err := Initialize(authOpts, log.DebugLevel) + b, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) tt1, err1 := b.AuthUnpwdCheck(username, password, clientid) @@ -242,7 +244,7 @@ func TestBackends(t *testing.T) { redis.conn.Set(ctx, username, passwordHash, 0) redis.conn.Set(ctx, fmt.Sprintf("%s:su", username), "true", 0) - b, err := Initialize(authOpts, log.DebugLevel) + b, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) tt1, err1 := b.AuthUnpwdCheck(username, password, clientid) @@ -287,7 +289,7 @@ func TestBackends(t *testing.T) { redis.conn.Set(ctx, username, passwordHash, 0) redis.conn.Set(ctx, fmt.Sprintf("%s:su", username), "true", 0) - b, err := Initialize(authOpts, log.DebugLevel) + b, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) tt1, err1 := b.AuthUnpwdCheck(username, password, clientid) @@ -331,7 +333,7 @@ func TestBackends(t *testing.T) { // Set it as superuser. redis.conn.Set(ctx, fmt.Sprintf("%s:su", username), "true", 0) - b, err := Initialize(authOpts, log.DebugLevel) + b, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) tt1, err1 := b.AuthUnpwdCheck(username, password, clientid) @@ -376,7 +378,7 @@ func TestBackends(t *testing.T) { redis.conn.Set(ctx, username, passwordHash, 0) redis.conn.Set(ctx, fmt.Sprintf("%s:su", username), "true", 0) - b, err := Initialize(authOpts, log.DebugLevel) + b, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) tt1, err1 := b.AuthUnpwdCheck(username, password, clientid) @@ -421,7 +423,7 @@ func TestBackends(t *testing.T) { redis.conn.Set(ctx, username, passwordHash, 0) redis.conn.Set(ctx, fmt.Sprintf("%s:su", username), "true", 0) - b, err := Initialize(authOpts, log.DebugLevel) + b, err := Initialize(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) tt1, err1 := b.AuthUnpwdCheck(username, password, clientid) diff --git a/backends/http.go b/backends/http.go index 01635fa..e5b21fa 100644 --- a/backends/http.go +++ b/backends/http.go @@ -19,6 +19,7 @@ type HTTP struct { UserUri string SuperuserUri string AclUri string + UserAgent string Host string Port string WithTLS bool @@ -34,7 +35,7 @@ type HTTPResponse struct { Error string `json:"error"` } -func NewHTTP(authOpts map[string]string, logLevel log.Level) (HTTP, error) { +func NewHTTP(authOpts map[string]string, logLevel log.Level, version string) (HTTP, error) { log.SetLevel(logLevel) @@ -79,6 +80,11 @@ func NewHTTP(authOpts map[string]string, logLevel log.Level) (HTTP, error) { missingOpts += " http_aclcheck_uri" } + http.UserAgent = fmt.Sprintf("%s-%s", defaultUserAgent, version) + if userAgent, ok := authOpts["http_user_agent"]; ok { + http.UserAgent = userAgent + } + if host, ok := authOpts["http_host"]; ok { http.Host = host } else { @@ -224,6 +230,7 @@ func (o HTTP) httpRequest(uri, username string, dataMap map[string]interface{}, } req.Header.Set("Content-Type", "application/json") + req.Header.Set("User-Agent", o.UserAgent) resp, err = o.Client.Do(req) } diff --git a/backends/http_test.go b/backends/http_test.go index b39180e..e007e0d 100644 --- a/backends/http_test.go +++ b/backends/http_test.go @@ -22,6 +22,8 @@ func TestHTTPAllJsonServer(t *testing.T) { var acc = int64(1) clientId := "test_client" + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { httpResponse := &HTTPResponse{ @@ -98,8 +100,23 @@ func TestHTTPAllJsonServer(t *testing.T) { authOpts["http_timeout"] = "5" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewHTTP(authOpts, log.DebugLevel) + hb, err := NewHTTP(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) + So(hb.UserAgent, ShouldEqual, "mosquitto-2.0.0") + + Convey("Given custom user agent, it should override default one", func() { + customAuthOpts := make(map[string]string) + + for k, v := range authOpts { + customAuthOpts[k] = v + } + + customAuthOpts["http_user_agent"] = "custom-user-agent" + + customHb, err := NewHTTP(customAuthOpts, log.DebugLevel, version) + So(err, ShouldBeNil) + So(customHb.UserAgent, ShouldEqual, "custom-user-agent") + }) Convey("Given correct password/username, get user should return true", func() { @@ -186,6 +203,8 @@ func TestHTTPJsonStatusOnlyServer(t *testing.T) { var acc = int64(1) clientId := "test_client" + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data interface{} @@ -241,7 +260,7 @@ func TestHTTPJsonStatusOnlyServer(t *testing.T) { authOpts["http_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewHTTP(authOpts, log.DebugLevel) + hb, err := NewHTTP(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -329,6 +348,8 @@ func TestHTTPJsonTextResponseServer(t *testing.T) { var acc = int64(1) clientId := "test_client" + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data interface{} @@ -388,7 +409,7 @@ func TestHTTPJsonTextResponseServer(t *testing.T) { authOpts["http_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewHTTP(authOpts, log.DebugLevel) + hb, err := NewHTTP(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -476,6 +497,8 @@ func TestHTTPFormJsonResponseServer(t *testing.T) { var acc = int64(1) clientId := "test_client" + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { httpResponse := &HTTPResponse{ @@ -544,7 +567,7 @@ func TestHTTPFormJsonResponseServer(t *testing.T) { authOpts["http_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewHTTP(authOpts, log.DebugLevel) + hb, err := NewHTTP(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -632,6 +655,8 @@ func TestHTTPFormStatusOnlyServer(t *testing.T) { var acc = int64(1) clientId := "test_client" + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() @@ -678,7 +703,7 @@ func TestHTTPFormStatusOnlyServer(t *testing.T) { authOpts["http_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewHTTP(authOpts, log.DebugLevel) + hb, err := NewHTTP(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -766,6 +791,8 @@ func TestHTTPFormTextResponseServer(t *testing.T) { var acc = int64(1) clientId := "test_client" + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) @@ -817,7 +844,7 @@ func TestHTTPFormTextResponseServer(t *testing.T) { authOpts["http_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewHTTP(authOpts, log.DebugLevel) + hb, err := NewHTTP(authOpts, log.DebugLevel, version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { diff --git a/backends/jwt.go b/backends/jwt.go index 8ebb2f6..01ac92a 100644 --- a/backends/jwt.go +++ b/backends/jwt.go @@ -42,7 +42,7 @@ const ( filesMode = "files" ) -func NewJWT(authOpts map[string]string, logLevel log.Level, hasher hashing.HashComparer) (*JWT, error) { +func NewJWT(authOpts map[string]string, logLevel log.Level, hasher hashing.HashComparer, version string) (*JWT, error) { log.SetLevel(logLevel) jwt := &JWT{} @@ -83,7 +83,7 @@ func NewJWT(authOpts map[string]string, logLevel log.Level, hasher hashing.HashC checker, err = NewLocalJWTChecker(authOpts, logLevel, hasher, options) case remoteMode: jwt.mode = remoteMode - checker, err = NewRemoteJWTChecker(authOpts, options) + checker, err = NewRemoteJWTChecker(authOpts, options, version) case filesMode: jwt.mode = filesMode checker, err = NewFilesJWTChecker(authOpts, logLevel, hasher, options) diff --git a/backends/jwt_remote.go b/backends/jwt_remote.go index 41f423b..744c3a2 100644 --- a/backends/jwt_remote.go +++ b/backends/jwt_remote.go @@ -20,6 +20,7 @@ type remoteJWTChecker struct { userUri string superuserUri string aclUri string + userAgent string host string port string withTLS bool @@ -38,7 +39,7 @@ type Response struct { Error string `json:"error"` } -func NewRemoteJWTChecker(authOpts map[string]string, options tokenOptions) (jwtChecker, error) { +func NewRemoteJWTChecker(authOpts map[string]string, options tokenOptions, version string) (jwtChecker, error) { var checker = &remoteJWTChecker{ withTLS: false, verifyPeer: false, @@ -80,6 +81,11 @@ func NewRemoteJWTChecker(authOpts map[string]string, options tokenOptions) (jwtC missingOpts += " jwt_aclcheck_uri" } + checker.userAgent = fmt.Sprintf("%s-%s", defaultUserAgent, version) + if userAgent, ok := authOpts["jwt_user_agent"]; ok { + checker.userAgent = userAgent + } + if hostname, ok := authOpts["jwt_host"]; ok { checker.host = hostname } else { @@ -240,10 +246,12 @@ func (o *remoteJWTChecker) jwtRequest(host, uri, token string, dataMap map[strin return false, err } req.Header.Set("Content-Type", "application/json") + req.Header.Set("User-Agent", o.userAgent) default: req, err = h.NewRequest("POST", fullURI, strings.NewReader(urlValues.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Content-Length", strconv.Itoa(len(urlValues.Encode()))) + req.Header.Set("User-Agent", o.userAgent) if err != nil { log.Errorf("req error: %s", err) diff --git a/backends/jwt_test.go b/backends/jwt_test.go index c7929af..b5bf497 100644 --- a/backends/jwt_test.go +++ b/backends/jwt_test.go @@ -646,6 +646,8 @@ func TestJWTAllJsonServer(t *testing.T) { var acc = int64(1) clientID := "test_client" + version := "2.0.0" + token, _ := jwtToken.SignedString([]byte(jwtSecret)) wrongToken, _ := wrongJwtToken.SignedString([]byte(jwtSecret)) @@ -722,7 +724,7 @@ func TestJWTAllJsonServer(t *testing.T) { authOpts["jwt_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -749,7 +751,7 @@ func TestJWTAllJsonServer(t *testing.T) { Convey("But disabling superusers by removing superuri should now return false", func() { authOpts["jwt_superuser_uri"] = "" - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) superuser, err := hb.GetSuperuser(username) @@ -813,6 +815,8 @@ func TestJWTJsonStatusOnlyServer(t *testing.T) { token, _ := jwtToken.SignedString([]byte(jwtSecret)) wrongToken, _ := wrongJwtToken.SignedString([]byte(jwtSecret)) + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data interface{} @@ -863,7 +867,7 @@ func TestJWTJsonStatusOnlyServer(t *testing.T) { authOpts["jwt_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -890,7 +894,7 @@ func TestJWTJsonStatusOnlyServer(t *testing.T) { Convey("But disabling superusers by removing superuri should now return false", func() { authOpts["jwt_superuser_uri"] = "" - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) superuser, err := hb.GetSuperuser(username) @@ -954,6 +958,8 @@ func TestJWTJsonTextResponseServer(t *testing.T) { token, _ := jwtToken.SignedString([]byte(jwtSecret)) wrongToken, _ := wrongJwtToken.SignedString([]byte(jwtSecret)) + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data interface{} @@ -1006,7 +1012,7 @@ func TestJWTJsonTextResponseServer(t *testing.T) { authOpts["jwt_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -1033,7 +1039,7 @@ func TestJWTJsonTextResponseServer(t *testing.T) { Convey("But disabling superusers by removing superuri should now return false", func() { authOpts["jwt_superuser_uri"] = "" - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) superuser, err := hb.GetSuperuser(username) @@ -1097,6 +1103,8 @@ func TestJWTFormJsonResponseServer(t *testing.T) { token, _ := jwtToken.SignedString([]byte(jwtSecret)) wrongToken, _ := wrongJwtToken.SignedString([]byte(jwtSecret)) + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { httpResponse := &HTTPResponse{ @@ -1159,7 +1167,7 @@ func TestJWTFormJsonResponseServer(t *testing.T) { authOpts["jwt_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -1186,7 +1194,7 @@ func TestJWTFormJsonResponseServer(t *testing.T) { Convey("But disabling superusers by removing superuri should now return false", func() { authOpts["jwt_superuser_uri"] = "" - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) superuser, err := hb.GetSuperuser(username) @@ -1250,6 +1258,8 @@ func TestJWTFormStatusOnlyServer(t *testing.T) { token, _ := jwtToken.SignedString([]byte(jwtSecret)) wrongToken, _ := wrongJwtToken.SignedString([]byte(jwtSecret)) + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() @@ -1294,7 +1304,7 @@ func TestJWTFormStatusOnlyServer(t *testing.T) { authOpts["jwt_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -1321,7 +1331,7 @@ func TestJWTFormStatusOnlyServer(t *testing.T) { Convey("But disabling superusers by removing superuri should now return false", func() { authOpts["jwt_superuser_uri"] = "" - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) superuser, err := hb.GetSuperuser(username) @@ -1385,6 +1395,8 @@ func TestJWTFormTextResponseServer(t *testing.T) { token, _ := jwtToken.SignedString([]byte(jwtSecret)) wrongToken, _ := wrongJwtToken.SignedString([]byte(jwtSecret)) + version := "2.0.0" + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) @@ -1432,7 +1444,7 @@ func TestJWTFormTextResponseServer(t *testing.T) { authOpts["jwt_aclcheck_uri"] = "/acl" Convey("Given correct options an http backend instance should be returned", t, func() { - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) Convey("Given correct password/username, get user should return true", func() { @@ -1459,7 +1471,7 @@ func TestJWTFormTextResponseServer(t *testing.T) { Convey("But disabling superusers by removing superuri should now return false", func() { authOpts["jwt_superuser_uri"] = "" - hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, "")) + hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version) So(err, ShouldBeNil) superuser, err := hb.GetSuperuser(username) diff --git a/go-auth.go b/go-auth.go index 7e03bde..2768528 100644 --- a/go-auth.go +++ b/go-auth.go @@ -38,7 +38,7 @@ var authOpts map[string]string //Options passed by mosquitto. var authPlugin AuthPlugin //General struct with options and conf. //export AuthPluginInit -func AuthPluginInit(keys []string, values []string, authOptsNum int) { +func AuthPluginInit(keys []string, values []string, authOptsNum int, version string) { log.SetFormatter(&log.TextFormatter{ FullTimestamp: true, }) @@ -104,7 +104,7 @@ func AuthPluginInit(keys []string, values []string, authOptsNum int) { var err error - authPlugin.backends, err = bes.Initialize(authOpts, authPlugin.logLevel) + authPlugin.backends, err = bes.Initialize(authOpts, authPlugin.logLevel, version) if err != nil { log.Fatalf("error initializing backends: %s", err) }