Skip to content

Commit 16d7f48

Browse files
authored
Merge pull request #536 from tableau/hxi
Update Evaluate endpoint to respond to auth first even when adhoc execution is disabled
2 parents b4f4014 + f20aef7 commit 16d7f48

File tree

2 files changed

+108
-10
lines changed

2 files changed

+108
-10
lines changed

Diff for: tabpy/tabpy_server/handlers/evaluation_plane_handler.py

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ def initialize(self, executor, app):
4040

4141
@gen.coroutine
4242
def post(self):
43+
if self.should_fail_with_auth_error() != AuthErrorStates.NONE:
44+
self.fail_with_auth_error()
45+
return
4346
self.error_out(404, "Ad-hoc scripts have been disabled on this analytics extension, please contact your "
4447
"administrator.")
4548

Diff for: tests/unit/server_tests/test_evaluation_plane_handler.py

+105-10
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
from tabpy.tabpy_server.handlers.util import hash_password
99

1010

11-
class TestEvaluationPlainHandlerWithAuth(AsyncHTTPTestCase):
11+
class TestEvaluationPlaneHandlerWithAuth(AsyncHTTPTestCase):
1212
@classmethod
1313
def setUpClass(cls):
14-
prefix = "__TestEvaluationPlainHandlerWithAuth_"
14+
prefix = "__TestEvaluationPlaneHandlerWithAuth_"
1515
# create password file
1616
cls.pwd_file = tempfile.NamedTemporaryFile(
1717
mode="w+t", prefix=prefix, suffix=".txt", delete=False
@@ -205,10 +205,10 @@ def test_script_returns_none(self):
205205
self.assertEqual(b'null', response.body)
206206

207207

208-
class TestEvaluationPlainHandlerWithoutAuth(AsyncHTTPTestCase):
208+
class TestEvaluationPlaneHandlerWithoutAuth(AsyncHTTPTestCase):
209209
@classmethod
210210
def setUpClass(cls):
211-
prefix = "__TestEvaluationPlainHandlerWithoutAuth_"
211+
prefix = "__TestEvaluationPlaneHandlerWithoutAuth_"
212212

213213
# create state.ini dir and file
214214
cls.state_dir = tempfile.mkdtemp(prefix=prefix)
@@ -288,10 +288,10 @@ def test_creds_no_auth_fails(self):
288288
self.assertEqual(406, response.code)
289289

290290

291-
class TestEvaluationPlainHandlerDisabled(AsyncHTTPTestCase):
291+
class TestEvaluationPlaneHandlerDisabledWithoutAuth(AsyncHTTPTestCase):
292292
@classmethod
293293
def setUpClass(cls):
294-
prefix = "__TestEvaluationPlainHandlerDisabled_"
294+
prefix = "__TestEvaluationPlaneHandlerDisabledWithoutAuth_"
295295

296296
# create config file
297297
cls.config_file = tempfile.NamedTemporaryFile(
@@ -326,10 +326,105 @@ def test_evaluation_disabled_fails(self):
326326
self.assertEqual(404, response.code)
327327

328328

329-
class TestEvaluationPlainHandlerEnabled(AsyncHTTPTestCase):
329+
class TestEvaluationPlaneHandlerDisabledWithAuth(AsyncHTTPTestCase):
330330
@classmethod
331331
def setUpClass(cls):
332-
prefix = "__TestEvaluationPlainHandlerEnabled_"
332+
prefix = "__TestEvaluationPlaneHandlerDisabledWithAuth_"
333+
334+
# create password file
335+
cls.pwd_file = tempfile.NamedTemporaryFile(
336+
mode="w+t", prefix=prefix, suffix=".txt", delete=False
337+
)
338+
username = "username"
339+
password = "password"
340+
cls.pwd_file.write(f"{username} {hash_password(username, password)}\n")
341+
cls.pwd_file.close()
342+
343+
# create state.ini dir and file
344+
cls.state_dir = tempfile.mkdtemp(prefix=prefix)
345+
cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+")
346+
cls.state_file.write(
347+
"[Service Info]\n"
348+
"Name = TabPy Serve\n"
349+
"Description = \n"
350+
"Creation Time = 0\n"
351+
"Access-Control-Allow-Origin = \n"
352+
"Access-Control-Allow-Headers = \n"
353+
"Access-Control-Allow-Methods = \n"
354+
"\n"
355+
"[Query Objects Service Versions]\n"
356+
"\n"
357+
"[Query Objects Docstrings]\n"
358+
"\n"
359+
"[Meta]\n"
360+
"Revision Number = 1\n"
361+
)
362+
cls.state_file.close()
363+
364+
# create config file
365+
cls.config_file = tempfile.NamedTemporaryFile(
366+
mode="w+t", prefix=prefix, suffix=".conf", delete=False
367+
)
368+
cls.config_file.write(
369+
"[TabPy]\n"
370+
f"TABPY_PWD_FILE = {cls.pwd_file.name}\n"
371+
f"TABPY_STATE_PATH = {cls.state_dir}\n"
372+
f"TABPY_EVALUATE_ENABLE = false"
373+
)
374+
cls.config_file.close()
375+
376+
cls.script = (
377+
'{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'
378+
'"script":"res=[]\\nfor i in range(len(_arg1)):\\n '
379+
'res.append(_arg1[i] * _arg2[i])\\nreturn res"}'
380+
)
381+
382+
@classmethod
383+
def tearDownClass(cls):
384+
os.remove(cls.pwd_file.name)
385+
os.remove(cls.state_file.name)
386+
os.remove(cls.config_file.name)
387+
os.rmdir(cls.state_dir)
388+
389+
def get_app(self):
390+
self.app = TabPyApp(self.config_file.name)
391+
return self.app._create_tornado_web_app()
392+
393+
def test_evaluation_disabled_fails_with_invalid_creds(self):
394+
response = self.fetch(
395+
"/evaluate",
396+
method="POST",
397+
body=self.script,
398+
headers={
399+
"Authorization": "Basic {}".format(
400+
base64.b64encode("user:wrong_password".encode("utf-8")).decode(
401+
"utf-8"
402+
)
403+
)
404+
},
405+
)
406+
self.assertEqual(401, response.code)
407+
408+
def test_evaluation_disabled_fails_with_valid_creds(self):
409+
response = self.fetch(
410+
"/evaluate",
411+
method="POST",
412+
body=self.script,
413+
headers={
414+
"Authorization": "Basic {}".format(
415+
base64.b64encode("username:password".encode("utf-8")).decode(
416+
"utf-8"
417+
)
418+
)
419+
},
420+
)
421+
self.assertEqual(404, response.code)
422+
423+
424+
class TestEvaluationPlaneHandlerEnabled(AsyncHTTPTestCase):
425+
@classmethod
426+
def setUpClass(cls):
427+
prefix = "__TestEvaluationPlaneHandlerEnabled_"
333428

334429
# create config file
335430
cls.config_file = tempfile.NamedTemporaryFile(
@@ -364,10 +459,10 @@ def test_evaluation_enabled(self):
364459
self.assertEqual(200, response.code)
365460

366461

367-
class TestEvaluationPlainHandlerDefault(AsyncHTTPTestCase):
462+
class TestEvaluationPlaneHandlerDefault(AsyncHTTPTestCase):
368463
@classmethod
369464
def setUpClass(cls):
370-
prefix = "__TestEvaluationPlainHandlerDefault_"
465+
prefix = "__TestEvaluationPlaneHandlerDefault_"
371466

372467
# create config file
373468
cls.config_file = tempfile.NamedTemporaryFile(

0 commit comments

Comments
 (0)