Kaynağa Gözat

Solve review issues and add retries for http call

j8
Andrei Bora 4 yıl önce
ebeveyn
işleme
b765adca75

+ 18
- 16
resources/prosody-plugins/mod_auth_token.lua Dosyayı Görüntüle

@@ -74,27 +74,26 @@ function provider.delete_user(username)
74 74
 	return nil;
75 75
 end
76 76
 
77
-local function validate_result(session, res, error, reason)
78
-    if res == false then
79
-        log("warn",
80
-            "Error verifying token err:%s, reason:%s", error, reason);
81
-        session.auth_token = nil;
82
-        return res, error, reason;
83
-    end
84
-end
85
-
86 77
 function provider.get_sasl_handler(session)
87 78
 
88 79
 	local function get_username_from_token(self, message)
89 80
 
90 81
         -- retrieve custom public key from server and save it on the session
91
-        local event_result = prosody.events.fire_event("pre-jitsi-authentication-fetch-key", session);
92
-        if event_result ~= nil then
93
-            validate_result(session,event_result.res, event_result.error, event_result.reason)
82
+        local pre_event_result = prosody.events.fire_event("pre-jitsi-authentication-fetch-key", session);
83
+        if pre_event_result ~= nil and pre_event_result.res == false then
84
+            log("warn",
85
+                "Error verifying token on pre authentication stage:%s, reason:%s", pre_event_result.error, pre_event_result.reason);
86
+            session.auth_token = nil;
87
+            return pre_event_result.res, pre_event_result.error, pre_event_result.reason;
94 88
         end
95 89
 
96 90
         local res, error, reason = token_util:process_and_verify_token(session);
97
-        validate_result(session, res, error, reason);
91
+        if res == false then
92
+            log("warn",
93
+                "Error verifying token err:%s, reason:%s", error, reason);
94
+            session.auth_token = nil;
95
+            return res, error, reason;
96
+        end
98 97
 
99 98
         local customUsername
100 99
             = prosody.events.fire_event("pre-jitsi-authentication", session);
@@ -112,9 +111,12 @@ function provider.get_sasl_handler(session)
112 111
             self.username = message;
113 112
         end
114 113
 
115
-        local event_result = prosody.events.fire_event("post-jitsi-authentication", session);
116
-        if event_result ~= nil then
117
-            validate_result(session,event_result.res, event_result.error, event_result.reason)
114
+        local post_event_result = prosody.events.fire_event("post-jitsi-authentication", session);
115
+        if post_event_result ~= nil and post_event_result.res == false then
116
+            log("warn",
117
+                "Error verifying token on post authentication stage :%s, reason:%s", post_event_result.error, post_event_result.reason);
118
+            session.auth_token = nil;
119
+            return post_event_result.res, post_event_result.error, post_event_result.reason;
118 120
         end
119 121
 
120 122
         return res;

+ 6
- 57
resources/prosody-plugins/token/util.lib.lua Dosyayı Görüntüle

@@ -5,17 +5,13 @@ local basexx = require "basexx";
5 5
 local have_async, async = pcall(require, "util.async");
6 6
 local hex = require "util.hex";
7 7
 local jwt = require "luajwtjitsi";
8
-local http = require "net.http";
9 8
 local jid = require "util.jid";
10 9
 local json_safe = require "cjson.safe";
11 10
 local path = require "util.paths";
12 11
 local sha256 = require "util.hashes".sha256;
13
-local timer = require "util.timer";
12
+local http_get_with_retry = module:require "util".http_get_with_retry;
14 13
 
15
-local http_timeout = 30;
16
-local http_headers = {
17
-    ["User-Agent"] = "Prosody ("..prosody.version.."; "..prosody.platform..")"
18
-};
14
+local nr_retries = 3;
19 15
 
20 16
 -- TODO: Figure out a less arbitrary default cache size.
21 17
 local cacheSize = module:get_option_number("jwt_pubkey_cache_size", 128);
@@ -131,65 +127,18 @@ function Util:get_public_key(keyId)
131 127
     if content == nil then
132 128
         -- If the key is not found in the cache.
133 129
         module:log("debug", "Cache miss for key: "..keyId);
134
-        local code;
135
-        local timeout_occurred;
136
-        local wait, done = async.waiter();
137
-
138 130
         local keyurl = path.join(self.asapKeyServer, hex.to(sha256(keyId))..'.pem');
139
-
140
-        local function cb(content_, code_, response_, request_)
141
-            if timeout_occurred == nil then
142
-                content, code = content_, code_;
143
-                if code == 200 or code == 204 then
144
-                    self.cache:set(keyId, content);
145
-                else
146
-                    module:log("warn", "Error on public key request: Code %s, Content %s",
147
-                    code_, content_);
148
-                end
149
-                done();
150
-            else
151
-                module:log("warn", "public key reply delivered after timeout from: %s",keyurl);
152
-            end
153
-        end
154
-
155
-        -- TODO: Is the done() call racey? Can we cancel this if the request
156
-        --       succeedes?
157
-        local function cancel()
158
-            -- TODO: This check is racey. Not likely to be a problem, but we should
159
-            --       still stick a mutex on content / code at some point.
160
-            if code == nil then
161
-                timeout_occurred = true;
162
-                module:log("warn", "Timeout %s seconds fetching public key from: %s",http_timeout,keyurl);
163
-                if http.destroy_request ~= nil then
164
-                    http.destroy_request(request);
165
-                end
166
-                done();
167
-            end
168
-        end
169
-
170 131
         module:log("debug", "Fetching public key from: "..keyurl);
171
-
172
-        -- We hash the key ID to work around some legacy behavior and make
173
-        -- deployment easier. It also helps prevent directory
174
-        -- traversal attacks (although path cleaning could have done this too).
175
-        local request = http.request(keyurl, {
176
-            headers = http_headers or {},
177
-            method = "GET"
178
-        }, cb);
179
-
180
-        timer.add_task(http_timeout, cancel);
181
-        wait();
182
-
183
-        if code == 200 or code == 204 then
184
-            return content;
132
+        content = http_get_with_retry(keyurl, nr_retries);
133
+        if content ~= nil then
134
+            self.cache:set(keyId, content);
185 135
         end
136
+        return content;
186 137
     else
187 138
         -- If the key is in the cache, use it.
188 139
         module:log("debug", "Cache hit for key: "..keyId);
189 140
         return content;
190 141
     end
191
-
192
-    return nil;
193 142
 end
194 143
 
195 144
 --- Verifies issuer part of token

+ 71
- 0
resources/prosody-plugins/util.lib.lua Dosyayı Görüntüle

@@ -1,5 +1,13 @@
1 1
 local jid = require "util.jid";
2
+local timer = require "util.timer";
3
+local http = require "net.http";
4
+
5
+local http_timeout = 30;
2 6
 local have_async, async = pcall(require, "util.async");
7
+local http_headers = {
8
+    ["User-Agent"] = "Prosody ("..prosody.version.."; "..prosody.platform..")"
9
+};
10
+
3 11
 local muc_domain_prefix
4 12
     = module:get_option_string("muc_mapper_domain_prefix", "conference");
5 13
 
@@ -208,6 +216,68 @@ function is_healthcheck_room(room_jid)
208 216
     return false;
209 217
 end
210 218
 
219
+-- Utility function to make an http get request and
220
+-- retry @param retry number of times
221
+-- @param url endpoint to be called
222
+-- @param retry nr of retries, if retry is
223
+-- nil there will be no retries
224
+-- @returns result of the http call or nil if
225
+-- the external call failed after the last retry
226
+function http_get_with_retry(url, retry)
227
+    local content, code;
228
+    local wait, done = async.waiter();
229
+    local function cb(content_, code_, response_, request_)
230
+        code = code_;
231
+        if code == 200 or code == 204 then
232
+            module:log("debug", "External call was successful, content %s", content_);
233
+            content = content_
234
+        else
235
+            module:log("warn", "Error on public key request: Code %s, Content %s",
236
+                code_, content_);
237
+        end
238
+        done();
239
+    end
240
+
241
+    local function call_http()
242
+        return http.request(url, {
243
+            headers = http_headers or {},
244
+            method = "GET"
245
+        }, cb);
246
+    end
247
+
248
+    local request = call_http();
249
+
250
+    local function cancel()
251
+        -- TODO: This check is racey. Not likely to be a problem, but we should
252
+        --       still stick a mutex on content / code at some point.
253
+        if code == nil then
254
+            -- no longer present in prosody 0.11, so check before calling
255
+            if http.destroy_request ~= nil then
256
+                http.destroy_request(request);
257
+            end
258
+            if retry == nil then
259
+                module:log("debug", "External call failed and retry policy is not set");
260
+                done();
261
+            elseif retry ~= nil and retry < 1 then
262
+                module:log("debug", "External call failed after retry")
263
+                done();
264
+            else
265
+                module:log("debug", "External call failed, retry nr %s", retry)
266
+                retry = retry - 1;
267
+                request = call_http()
268
+                return http_timeout;
269
+            end
270
+        end
271
+    end
272
+    timer.add_task(http_timeout, cancel);
273
+    wait();
274
+
275
+    if code == 200 or code == 204 then
276
+        return content;
277
+    end
278
+    return nil;
279
+end
280
+
211 281
 return {
212 282
     is_feature_allowed = is_feature_allowed;
213 283
     is_healthcheck_room = is_healthcheck_room;
@@ -217,4 +287,5 @@ return {
217 287
     room_jid_split_subdomain = room_jid_split_subdomain;
218 288
     internal_room_jid_match_rewrite = internal_room_jid_match_rewrite;
219 289
     update_presence_identity = update_presence_identity;
290
+    http_get_with_retry = http_get_with_retry;
220 291
 };

Loading…
İptal
Kaydet