Skip to content

Commit

Permalink
Add support for wildcard routes and methods
Browse files Browse the repository at this point in the history
Fixes aws#403.

As part of this change, I switched the static list of HTTP
methods to use '*'.  This cuts down on the verbosity of the
policy and makes the string routes and the AuthRoutes() more
consistent in the policies they generate.
  • Loading branch information
jamesls committed Jul 31, 2017
1 parent ae738bd commit b061619
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 17 deletions.
12 changes: 9 additions & 3 deletions chalice/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -749,11 +749,16 @@ def _generate_allowed_resources(self, request):
if isinstance(route, AuthRoute):
methods = route.methods
path = route.path
elif route == '*':
# A string route of '*' means that all paths and
# all HTTP methods are now allowed.
methods = ['*']
path = '*'
else:
# If 'route' is just a string, then they've
# opted not to use the AuthRoute(), so we'll
# generate a policy that allows all HTTP methods.
methods = self.ALL_HTTP_METHODS
methods = ['*']
path = route
for method in methods:
allowed_resources.append(
Expand All @@ -775,11 +780,12 @@ def _generate_arn(self, route, request, method='*'):
# '/'.join(...)'d properly.
base.extend([method, route[1:]])
last_arn_segment = '/'.join(base)
if route == '/':
if route == '/' or route == '*':
# We have to special case the '/' case. For whatever
# reason, API gateway adds an extra '/' to the method_arn
# of the auth request, so we need to do the same thing.
last_arn_segment += '/'
# We also have to handle the '*' case which is for wildcards
last_arn_segment += route
final_arn = '%s:%s' % (parts[0], last_arn_segment)
return final_arn

Expand Down
4 changes: 3 additions & 1 deletion docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,9 @@ These classes are used when defining built-in authoriers in Chalice.
an instance of ``AuthRoute``. If you specify the URL as
a string, then all supported HTTP methods will be authorized.
If you want to specify which HTTP methods are allowed, you
can use ``AuthRoute``.
can use ``AuthRoute``. If you want to specify that all
routes and HTTP methods are supported you can use the
wildcard value of ``"*"``: ``AuthResponse(routes=['*'], ...)``

.. attribute:: principal_id

Expand Down
45 changes: 32 additions & 13 deletions tests/unit/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -905,8 +905,7 @@ def test_can_return_auth_response():
{'Action': 'execute-api:Invoke',
'Effect': 'Allow',
'Resource': [
'arn:aws:execute-api:us-west-2:1:id/dev/%s/a' %
method for method in app.AuthResponse.ALL_HTTP_METHODS
'arn:aws:execute-api:us-west-2:1:id/dev/*/a'
]}
]
}
Expand All @@ -926,10 +925,7 @@ def test_auth_response_serialization():
request = app.AuthRequest('TOKEN', 'authtoken', method_arn)
response = app.AuthResponse(routes=['/needs/auth'], principal_id='foo')
response_dict = response.to_dict(request)
expected = [
method_arn.replace('GET', method)
for method in app.AuthResponse.ALL_HTTP_METHODS
]
expected = [method_arn.replace('GET', '*')]
assert response_dict == {
'policyDocument': {
'Version': '2012-10-17',
Expand Down Expand Up @@ -973,15 +969,38 @@ def test_can_use_auth_routes_instead_of_strings(auth_request):
}


def test_auth_response_wildcard(auth_request):
response = app.AuthResponse(
routes=[app.AuthRoute(path='*', methods=['*'])],
principal_id='user')
serialized = response.to_dict(auth_request)
assert serialized['policyDocument'] == {
'Statement': [
{'Action': 'execute-api:Invoke',
'Effect': 'Allow',
'Resource': [
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/*/*']}],
'Version': '2012-10-17'
}


def test_auth_response_wildcard_string(auth_request):
response = app.AuthResponse(
routes=['*'], principal_id='user')
serialized = response.to_dict(auth_request)
assert serialized['policyDocument'] == {
'Statement': [
{'Action': 'execute-api:Invoke',
'Effect': 'Allow',
'Resource': [
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/*/*']}],
'Version': '2012-10-17'
}


def test_can_mix_auth_routes_and_strings(auth_request):
expected = [
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/DELETE/a',
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/HEAD/a',
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/OPTIONS/a',
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/PATCH/a',
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/POST/a',
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/PUT/a',
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/GET/a',
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/*/a',
'arn:aws:execute-api:us-west-2:123:rest-api-id/dev/GET/a/b',
]
response = app.AuthResponse(
Expand Down

0 comments on commit b061619

Please sign in to comment.