Merge pull request #23 from denismakogon/issue/22

Issue #22: Make public route execution validation more strict
This commit is contained in:
Denis Makogon 2016-12-09 22:51:12 +02:00 committed by GitHub
commit 6f6a5e6f46
6 changed files with 82 additions and 9 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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}