Added jwt http timeout (#285)
* Added jwt http timeout Co-authored-by: Alessandro Peretti <alessandro.peretti@spindox.it>
This commit is contained in:
parent
a271ad1e70
commit
807e8f25e3
|
@ -864,6 +864,7 @@ The following options are supported by the `jwt` backend when remote is set to t
|
||||||
| --------------------------- | --------- | :-------: | ------------------------------------------------------------- |
|
| --------------------------- | --------- | :-------: | ------------------------------------------------------------- |
|
||||||
| auth_opt_jwt_host | | Y/N | API server host name or ip |
|
| auth_opt_jwt_host | | Y/N | API server host name or ip |
|
||||||
| auth_opt_jwt_port | | Y | TCP port number |
|
| auth_opt_jwt_port | | Y | TCP port number |
|
||||||
|
| auth_opt_jwt_http_timeout | 5 | N | Timeout in seconds for http client |
|
||||||
| auth_opt_jwt_getuser_uri | | Y | URI for check username/password |
|
| auth_opt_jwt_getuser_uri | | Y | URI for check username/password |
|
||||||
| auth_opt_jwt_superuser_uri | | N | URI for check superuser |
|
| auth_opt_jwt_superuser_uri | | N | URI for check superuser |
|
||||||
| auth_opt_jwt_aclcheck_uri | | Y | URI for check acl |
|
| auth_opt_jwt_aclcheck_uri | | Y | URI for check acl |
|
||||||
|
|
|
@ -27,10 +27,10 @@ type remoteJWTChecker struct {
|
||||||
hostWhitelist []string
|
hostWhitelist []string
|
||||||
withTLS bool
|
withTLS bool
|
||||||
verifyPeer bool
|
verifyPeer bool
|
||||||
|
paramsMode string
|
||||||
paramsMode string
|
httpMethod string
|
||||||
httpMethod string
|
responseMode string
|
||||||
responseMode string
|
timeout int
|
||||||
|
|
||||||
options tokenOptions
|
options tokenOptions
|
||||||
|
|
||||||
|
@ -152,7 +152,16 @@ func NewRemoteJWTChecker(authOpts map[string]string, options tokenOptions, versi
|
||||||
return nil, errors.Errorf("JWT backend error: missing remote options: %s", missingOpts)
|
return nil, errors.Errorf("JWT backend error: missing remote options: %s", missingOpts)
|
||||||
}
|
}
|
||||||
|
|
||||||
checker.client = &h.Client{Timeout: 5 * time.Second}
|
checker.timeout = 5
|
||||||
|
if timeoutString, ok := authOpts["jwt_http_timeout"]; ok {
|
||||||
|
if timeout, err := strconv.Atoi(timeoutString); err == nil {
|
||||||
|
checker.timeout = timeout
|
||||||
|
} else {
|
||||||
|
log.Errorf("unable to parse timeout: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checker.client = &h.Client{Timeout: time.Duration(checker.timeout) * time.Second}
|
||||||
|
|
||||||
if !checker.verifyPeer {
|
if !checker.verifyPeer {
|
||||||
tr := &h.Transport{
|
tr := &h.Transport{
|
||||||
|
|
|
@ -1654,3 +1654,88 @@ func TestJWTFormTextResponseServer(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJWTHttpTimeout(t *testing.T) {
|
||||||
|
|
||||||
|
topic := "test/topic"
|
||||||
|
var acc = int64(1)
|
||||||
|
clientID := "test_client"
|
||||||
|
token, _ := jwtToken.SignedString([]byte(jwtSecret))
|
||||||
|
|
||||||
|
version := "2.0.0"
|
||||||
|
|
||||||
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var params = r.Form
|
||||||
|
|
||||||
|
gToken := r.Header.Get("Authorization")
|
||||||
|
gToken = strings.TrimPrefix(gToken, "Bearer ")
|
||||||
|
|
||||||
|
if token != gToken {
|
||||||
|
w.Write([]byte("Wrong credentials."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.URL.Path {
|
||||||
|
case "/user", "/superuser":
|
||||||
|
w.Write([]byte("ok"))
|
||||||
|
case "/acl":
|
||||||
|
time.Sleep(time.Duration(1200) * time.Millisecond)
|
||||||
|
paramsAcc, _ := strconv.ParseInt(params["acc"][0], 10, 64)
|
||||||
|
if params["topic"][0] == topic && params["clientid"][0] == clientID && paramsAcc <= acc {
|
||||||
|
w.Write([]byte("ok"))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
w.Write([]byte("Acl check failed."))
|
||||||
|
}
|
||||||
|
|
||||||
|
}))
|
||||||
|
|
||||||
|
defer mockServer.Close()
|
||||||
|
|
||||||
|
authOpts := make(map[string]string)
|
||||||
|
authOpts["jwt_mode"] = "remote"
|
||||||
|
authOpts["jwt_params_mode"] = "form"
|
||||||
|
authOpts["jwt_response_mode"] = "text"
|
||||||
|
authOpts["jwt_host"] = strings.Replace(mockServer.URL, "http://", "", -1)
|
||||||
|
authOpts["jwt_port"] = ""
|
||||||
|
authOpts["jwt_getuser_uri"] = "/user"
|
||||||
|
authOpts["jwt_superuser_uri"] = "/superuser"
|
||||||
|
authOpts["jwt_aclcheck_uri"] = "/acl"
|
||||||
|
authOpts["jwt_http_timeout"] = "1"
|
||||||
|
|
||||||
|
Convey("Given correct options an http backend instance should be returned", t, func() {
|
||||||
|
hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("JWT remote test timeout parameter: YES TIMEOUT", func() {
|
||||||
|
_, err := hb.CheckAcl(token, topic, clientID, MOSQ_ACL_READ)
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
So(err.Error(), ShouldContainSubstring, "acl")
|
||||||
|
})
|
||||||
|
|
||||||
|
hb.Halt()
|
||||||
|
})
|
||||||
|
|
||||||
|
authOpts["jwt_http_timeout"] = "2"
|
||||||
|
|
||||||
|
Convey("Given correct options an http backend instance should be returned", t, func() {
|
||||||
|
hb, err := NewJWT(authOpts, log.DebugLevel, hashing.NewHasher(authOpts, ""), version)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("JWT remote test timeout parameter: NO TIMEOUT", func() {
|
||||||
|
_, err := hb.CheckAcl(token, topic, clientID, MOSQ_ACL_READ)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
})
|
||||||
|
|
||||||
|
hb.Halt()
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue