Merge pull request #23 from denismakogon/issue/22
Issue #22: Make public route execution validation more strict
This commit is contained in:
commit
6f6a5e6f46
@ -18,6 +18,7 @@ from aioservice.http import controller
|
||||
from aioservice.http import requests
|
||||
|
||||
from ...common import config
|
||||
from ...models import app as app_model
|
||||
|
||||
|
||||
class RunnableMixin(object):
|
||||
@ -88,9 +89,29 @@ class PublicRunnableV1Controller(controller.ServiceController,
|
||||
description: successful operation. Return "runnable" JSON
|
||||
"404":
|
||||
description: App does not exist
|
||||
"404":
|
||||
description: App route does not exist
|
||||
"403":
|
||||
description: Unable to execute private route
|
||||
"""
|
||||
app = request.match_info.get('app')
|
||||
path = request.match_info.get('route')
|
||||
routes = await app_model.Routes.find_by(app_name=app, path=path)
|
||||
|
||||
if not routes:
|
||||
return web.json_response(data={
|
||||
"error": {
|
||||
"message": "Route {0} not found".format(app),
|
||||
}
|
||||
}, status=404)
|
||||
route = routes.pop()
|
||||
|
||||
if not route.public:
|
||||
return web.json_response(data={
|
||||
"error": {
|
||||
"message": "Unable to execute private "
|
||||
"route {0}".format(path)
|
||||
}
|
||||
}, status=403)
|
||||
|
||||
return await super(PublicRunnableV1Controller,
|
||||
self).run(request, **kwargs)
|
||||
|
||||
@ -118,9 +139,19 @@ class RunnableV1Controller(controller.ServiceController,
|
||||
"200":
|
||||
description: successful operation. Return "runnable" JSON
|
||||
"404":
|
||||
description: App does not exist
|
||||
description: App not found
|
||||
"404":
|
||||
description: App route does not exist
|
||||
description: App route not found
|
||||
"""
|
||||
app = request.match_info.get('app')
|
||||
project_id = request.match_info.get('project_id')
|
||||
|
||||
if not (await app_model.Apps.exists(app, project_id)):
|
||||
return web.json_response(data={
|
||||
"error": {
|
||||
"message": "App {0} not found".format(app),
|
||||
}
|
||||
}, status=404)
|
||||
|
||||
return await super(RunnableV1Controller,
|
||||
self).run(request, **kwargs)
|
||||
|
@ -17,14 +17,19 @@ import json as jsonlib
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def setup_execute(self, app_name):
|
||||
def setup_execute(self, app_name, create_public_route=False):
|
||||
app, _ = self.testloop.run_until_complete(
|
||||
self.test_client.apps.create(app_name)
|
||||
)
|
||||
new_app_name = app["app"]["name"]
|
||||
route_data = self.route_data
|
||||
|
||||
if create_public_route:
|
||||
route_data.update(is_public="true")
|
||||
|
||||
route, _ = self.testloop.run_until_complete(
|
||||
self.test_client.routes.create(
|
||||
new_app_name, **self.route_data)
|
||||
new_app_name, **route_data)
|
||||
)
|
||||
self.testloop.run_until_complete(
|
||||
self.test_client.routes.update(
|
||||
@ -199,7 +204,8 @@ class AppRoutesTestSuite(object):
|
||||
self.assertEqual(200, status)
|
||||
|
||||
def execute_public(self):
|
||||
with setup_execute(self, "execute_public") as app_name:
|
||||
with setup_execute(self, "execute_public",
|
||||
create_public_route=True) as app_name:
|
||||
result, status = self.testloop.run_until_complete(
|
||||
self.test_client.routes.execute_public(
|
||||
app_name, self.route_data["path"]
|
||||
@ -207,3 +213,23 @@ class AppRoutesTestSuite(object):
|
||||
)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(200, status)
|
||||
|
||||
def fail_to_execute_private_as_public(self):
|
||||
with setup_execute(self, "fail_to_execute_"
|
||||
"private_as_public") as app_name:
|
||||
_, status = self.testloop.run_until_complete(
|
||||
self.test_client.routes.execute_public(
|
||||
app_name, self.route_data["path"]
|
||||
)
|
||||
)
|
||||
self.assertEqual(403, status)
|
||||
|
||||
def fail_to_run_app_from_other_project(self):
|
||||
with setup_execute(self, "fail_to_run_app_"
|
||||
"from_other_project") as app_name:
|
||||
_, status = self.testloop.run_until_complete(
|
||||
self.other_test_client.routes.execute_public(
|
||||
app_name, self.route_data["path"]
|
||||
)
|
||||
)
|
||||
self.assertEqual(404, status)
|
||||
|
@ -74,12 +74,17 @@ class FunctionalTestsBase(base.PicassoTestsBase, testtools.TestCase):
|
||||
)
|
||||
|
||||
self.project_id = str(uuid.uuid4()).replace("-", "")
|
||||
self.other_project_id = str(uuid.uuid4()).replace("-", "")
|
||||
|
||||
self.test_client = client.ProjectBoundTestClient(
|
||||
self.testapp, self.project_id)
|
||||
self.other_test_client = client.ProjectBoundTestClient(
|
||||
self.testapp, self.other_project_id)
|
||||
|
||||
self.testloop.run_until_complete(self.test_client.start_server())
|
||||
super(FunctionalTestsBase, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
self.testloop.run_until_complete(self.test_client.close())
|
||||
self.testloop.run_until_complete(self.other_test_client.close())
|
||||
super(FunctionalTestsBase, self).tearDown()
|
||||
|
@ -49,3 +49,10 @@ class TestAppRoutes(base.FunctionalTestsBase,
|
||||
|
||||
def test_public_execution(self):
|
||||
super(TestAppRoutes, self).execute_private()
|
||||
|
||||
def test_fail_to_execute_private_route(self):
|
||||
super(TestAppRoutes, self).fail_to_execute_private_as_public()
|
||||
|
||||
def test_fail_to_run_app_from_other_project(self):
|
||||
super(TestAppRoutes,
|
||||
self).fail_to_run_app_from_other_project()
|
||||
|
@ -55,3 +55,7 @@ class TestIntegrationAppRoutes(base.FunctionalTestsBase,
|
||||
|
||||
def test_public_execution(self):
|
||||
super(TestIntegrationAppRoutes, self).execute_private()
|
||||
|
||||
def test_fail_to_execute_private_route(self):
|
||||
super(TestIntegrationAppRoutes,
|
||||
self).fail_to_execute_private_as_public()
|
||||
|
4
tox.ini
4
tox.ini
@ -32,10 +32,10 @@ commands = flake8
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:py35-integration]
|
||||
commands = pytest --tb=long --capture=sys --cov=picasso --capture=fd {toxinidir}/picasso/tests/integration
|
||||
commands = pytest -v --tb=long --capture=sys --cov=picasso --capture=fd {toxinidir}/picasso/tests/integration
|
||||
|
||||
[testenv:py35-functional]
|
||||
commands = pytest --tb=long --capture=sys --cov=picasso --capture=fd {toxinidir}/picasso/tests/functional
|
||||
commands = pytest -v --tb=long --capture=sys --cov=picasso --capture=fd {toxinidir}/picasso/tests/functional
|
||||
|
||||
[testenv:py35-functional-regression]
|
||||
commands = {toxinidir}/scripts/test_regression.sh functional {posargs}
|
||||
|
Loading…
x
Reference in New Issue
Block a user