-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for builtin API Gateway authorizers #381
Closed
Closed
Changes from 1 commit
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
35162b8
Add support for builtin API Gateway authorizers
jamesls 33cf604
Incorporate review feedback
jamesls 8ff56f6
Fix py3 test failures
jamesls cdc975b
Fail when using built in auths with the package command
jamesls 2caaff8
Delete unreferenced lambda functions on redeploys
jamesls 2cdde29
Add per-function granularity in config
jamesls 6789322
Use per-function config when deploying auth handlers
jamesls 107c07e
Incorporate review feedback
jamesls a234e45
Fix APIGateway documentation to include class
jamesls 8aa07e7
Add documentation for authorizers
jamesls c95b37b
Incorporate doc review feedback
jamesls File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,6 +64,7 @@ Topics | |
topics/packaging | ||
topics/pyversion | ||
topics/cfn | ||
topics/authorizers | ||
|
||
|
||
API Reference | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
Authorization | ||
============= | ||
|
||
Chalice supports multiple mechanisms for authorization. This topic | ||
covers how you can integrate authorization into your Chalice applications. | ||
|
||
In Chalice, all the authorizers are configured per-route and specified | ||
using the ``authorizer`` kwarg to an ``@app.route()`` call. You | ||
control which type of authorizer to use based on what's passed as the | ||
``authorizer`` kwarg. You can use the same authorizer instance for | ||
multiple routes. | ||
|
||
The first set of authorizers chalice supports cover the scenario where | ||
you have some existing authorization mechanism that you just want your | ||
Chalice app to use. | ||
|
||
Chalice also supports built-in authorizers, which allows Chalice to | ||
manage your custom authorizers as part of ``chalice deploy``. This is | ||
covered in the Built-in Authorizers section. | ||
|
||
|
||
AWS IAM Authorizer | ||
------------------ | ||
|
||
The IAM Authorizer allows you to control access to API Gateway with | ||
`IAM permissions`_ | ||
|
||
To associate an IAM authorizer with a route in chalice, you use the | ||
:class:`IAMAUthorizer` class: | ||
|
||
.. code-block:: python | ||
|
||
authorizer = IAMAuthorizer() | ||
|
||
@app.route('/iam-auth', methods=['GET'], authorizer=authorizer) | ||
def authenticated(): | ||
return {"success": True} | ||
|
||
|
||
See the `API Gateway documentation | ||
<http://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html>`__ | ||
for more information on controlling access to API Gateway with IAM permissions. | ||
|
||
Amazon Cognito User Pools | ||
------------------------- | ||
|
||
In addition to using IAM roles and policies with the :class:`IAMAuthorizer` you | ||
can also use a `Cognito user pools`_ to control who can access your Chalice | ||
app. A cognito user pool serves as your own identity provider to maintain a | ||
user directory. | ||
|
||
To integrate Cognito user pools with Chalice, you'll need to have an existing | ||
cognito user pool configured. | ||
|
||
|
||
.. code-block:: python | ||
|
||
authorizer = CognitoUserPoolAuthorizer( | ||
'MyPool', provider_arns=['arn:aws:cognito:...:userpool/name']) | ||
|
||
@app.route('/user-pools', methods=['GET'], authorizer=authorizer) | ||
def authenticated(): | ||
return {"sucecss": True} | ||
|
||
|
||
Within a request, you can access the ``app.current_request.context`` object | ||
for metadata about the authenticated request. | ||
|
||
For more information about using Cognito user pools with API Gateway, | ||
see the `Use Amazon Cognito User Pools documentation | ||
<http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html>`__. | ||
|
||
|
||
Custom Authorizers | ||
------------------ | ||
|
||
API Gateway also lets you write custom authorizers using a Lambda function. | ||
You can configure a Chalice route to use a pre-existing Lambda function as | ||
a custom authorizer. If you also want to write and manage your Lambda | ||
authorizer using Chalice, see the next section, Built-in Authorizers. | ||
|
||
To connect an existing Lambda function as a custom authorizer in chalice, | ||
you use the ``CustomAuthorizer`` class: | ||
|
||
.. code-block:: python | ||
|
||
authorizer = CustomAuthorizer( | ||
'MyCustomAuth', header='Authorization', | ||
authorizer_uri=('arn:aws:apigateway:region:lambda:path/2015-03-01' | ||
'/functions/arn:aws:lambda:region:account-id:' | ||
'function:FunctionName/invocations')) | ||
|
||
@app.route('/custom-auth', methods=['GET'], authorizer=authorizer) | ||
def authenticated(): | ||
return {"success": True} | ||
|
||
|
||
Built-in Authorizers | ||
-------------------- | ||
|
||
The ``IAMAuthorizer``, ``CognitoUserPoolAuthorizer``, and the | ||
``CustomAuthorizer`` classes are all for cases where you have existing | ||
resources for managing authorization and you want to wire them together with | ||
your Chalice app. A Built-in authorizer is used when you'd like to write your | ||
custom authorizer in Chalice, and have the additional Lambda functions managed | ||
when you run ``chalice deploy/delete``. This section will cover how to use the | ||
built-in authorizers in chalice. | ||
|
||
Creating an authorizer in chalice requires you use the ``@app.authorizer`` | ||
decorator to a function. The function must accept a single arg, which will be | ||
an instance of :class:`AuthRequest`. The function must return a | ||
:class:`AuthResponse`. As an example, we'll port the example from the `API | ||
Gateway documentation`_. First, we'll show the code and then walk through it: | ||
|
||
.. code-block:: python | ||
|
||
from chalice import Chalice, AuthResponse | ||
|
||
app = Chalice(app_name='demoauth1') | ||
|
||
|
||
@app.authorizer() | ||
def demo_auth(auth_request): | ||
token = auth_request.token | ||
# This is just for demo purposes as shown in the API Gateway docs. | ||
# Normally you'd call an oauth provider, validae the | ||
# jwt token, etc. | ||
# In this exampe, the token is treated as the status for demo | ||
# purposes. | ||
if token == 'allow': | ||
return AuthResponse(routes=['/'], principal_id='user') | ||
else: | ||
return AuthResponse(routes=[], principal_id='user') | ||
|
||
|
||
@app.route('/', authorizer=demo_auth) | ||
def index(): | ||
return {'context': app.current_request.context} | ||
|
||
|
||
In the example above we define a built-in authorizer by decorating | ||
the ``demo_auth`` function with the ``@app.authorizer()`` decorator. | ||
Note you must use ``@app.authorizer()`` and not ``@app.authorizer``. | ||
A built-in authorizer function has this type signature:: | ||
|
||
def auth_handler(auth_request: AuthRequest) -> AuthResponse: ... | ||
|
||
Within the auth handler you must determine if the request is | ||
authorized or not. The ``AuthResponse`` contains the allowed | ||
URLs as well as the principal id of the user. You can optionally | ||
return a dictionary of key value pairs (as the ``context`` kwarg). | ||
This dictionary will be passed through on subsequent requests. | ||
In our example above we're not using the context dictionary. | ||
|
||
Now let's deploy our app. As usual, we just need to run | ||
``chalice deploy`` and chalice will automatically deploy all the | ||
necessary Lambda functions for us. | ||
|
||
Now when we try to make a request, we'll get an Unauthorized error:: | ||
|
||
$ http https://api.us-west-2.amazonaws.com/dev/ | ||
HTTP/1.1 401 Unauthorized | ||
|
||
{ | ||
"message": "Unauthorized" | ||
} | ||
|
||
If we add the appropriate authorization header, we'll see the call succeed:: | ||
|
||
$ http https://api.us-west-2.amazonaws.com/dev/ 'Authorization: allow' | ||
HTTP/1.1 200 OK | ||
|
||
{ | ||
"context": { | ||
"accountId": "12345", | ||
"apiId": "api", | ||
"authorizer": { | ||
"principalId": "user" | ||
}, | ||
"httpMethod": "GET", | ||
"identity": { | ||
"accessKey": null, | ||
"accountId": null, | ||
"apiKey": "", | ||
"caller": null, | ||
"cognitoAuthenticationProvider": null, | ||
"cognitoAuthenticationType": null, | ||
"cognitoIdentityId": null, | ||
"cognitoIdentityPoolId": null, | ||
"sourceIp": "1.1.1.1", | ||
"user": null, | ||
"userAgent": "HTTPie/0.9.9", | ||
"userArn": null | ||
}, | ||
"path": "/dev/", | ||
"requestId": "d35d2063-56be-11e7-9ce1-dd61c24a3668", | ||
"resourceId": "id", | ||
"resourcePath": "/", | ||
"stage": "dev" | ||
} | ||
} | ||
|
||
The low level API for API Gateway's custom authorizer feature requires | ||
that an IAM policy must be returned. The :class:`AuthResponse` class we're | ||
using is a wrapper over building the IAM policy ourself. If you want | ||
low level control and would prefer to contruct the IAM policy yourself | ||
you can return a dictionary of the IAM policy instead of an instance of | ||
:class:`AuthResponse`. If you do that, the dictionary is returned | ||
without modification back to API Gateway. | ||
|
||
For more information on custom authorizers, see the | ||
`Use API Gateway Custom Authorizers | ||
<http://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html>`__ | ||
page in the API Gateway user guide. | ||
|
||
|
||
.. _IAM permissions: http://docs.aws.amazon.com/IAM/latest/UserGuide/access_permissions.html | ||
.. _Cognito User Pools: http://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html | ||
.. _API Gateway documentation: http://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html#api-gateway-custom-authorizer-lambda-function-create |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validae -> validate