Skip to content

feat(data-classes): authorizer for http api and rest api #620

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

Merged
merged 19 commits into from
Aug 21, 2021

Conversation

michaelbrewer
Copy link
Contributor

@michaelbrewer michaelbrewer commented Aug 18, 2021

Issue #, if available:

Description of changes:

Changes / TODO

  • http api request payload v2.0
  • http api simple response builder (payload v2.0 only)
  • method / route arn parser and buildinger
  • client cert support for rest api and http api
  • rest api request payment / http api payload v1.0
  • rest api auth policy builder / http api auth policy builder
  • Basic docs

Examples

Rest api example for a request type event and build iam policy with context info:

from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.api_gateway_authorizer_event import (
    APIGatewayAuthorizerRequestEvent,
    APIGatewayAuthorizerResponse,
    HttpVerb,
)


def get_user_by_token(token):
    return {}


@event_source(data_class=APIGatewayAuthorizerRequestEvent)
def handler(event: APIGatewayAuthorizerRequestEvent, context):
    user = get_user_by_token(event.get_header_value("Authorization"))

    arn = event.parsed_arn
    builder = APIGatewayAuthorizerResponse("user", arn.region, arn.aws_account_id, arn.api_id, arn.stage)
    if user is None:
        # No user was found, so we return not authorized
        builder.deny_all_methods()
        return builder.asdict()

    # Found the user and setting the details in the context
    builder.context = user

    # Conditional IAM Policy
    if user.get("isAdmin", False):
        builder.allow_all_methods()
    else:
        builder.allow_method(HttpVerb.GET, "/user-profile")

    return builder.asdict()

Rest api with a token request event and a simple allow all or deny all

from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.api_gateway_authorizer_event import (
    APIGatewayAuthorizerTokenEvent,
    APIGatewayAuthorizerResponse,
)


@event_source(data_class=APIGatewayAuthorizerTokenEvent)
def handler(event: APIGatewayAuthorizerTokenEvent, context):
    arn = event.parsed_arn
    builder = APIGatewayAuthorizerResponse("user", arn.region, arn.aws_account_id, arn.api_id, arn.stage)
    if event.authorization_token == "42":
        builder.allow_all_methods()
    else:
        builder.deny_all_methods()
    return builder.asdict()

Http api payload version 2 example of a http api authorizer checks it the Authorization header is "foo"

NOTE: The use of .asdict()

from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.api_gateway_authorizer_event import (
    APIGatewayAuthorizerEventV2,
    APIGatewayAuthorizerResponseV2,
)


@event_source(data_class=APIGatewayAuthorizerEventV2)
def handler(event: APIGatewayAuthorizerEventV2, context):
    is_authorized = event.get_header_value("Authorization") == "foo"
    return APIGatewayAuthorizerResponseV2(authorize=is_authorized).asdict()

Http api payload version 2 A more complicated example getting the user details by an authorization header and setting the context

from aws_lambda_powertools.utilities.data_classes import event_source
from aws_lambda_powertools.utilities.data_classes.api_gateway_authorizer_event import (
    APIGatewayAuthorizerEventV2,
    APIGatewayAuthorizerResponseV2,
)


def get_user_by_token(token):
    ...


@event_source(data_class=APIGatewayAuthorizerEventV2)
def handler(event: APIGatewayAuthorizerEventV2, context):
    user = get_user_by_token(event.get_header_value("Authorization"))

    if user is None:
        # No user was found, so we return not authorized
        return APIGatewayAuthorizerResponseV2().asdict()

    # Found the user and setting the details in the context
    return APIGatewayAuthorizerResponseV2(authorize=True, context=user).asdict()

Checklist

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@pull-request-size pull-request-size bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Aug 18, 2021
@codecov-commenter
Copy link

codecov-commenter commented Aug 18, 2021

Codecov Report

Merging #620 (97c17c9) into develop (16563bb) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##           develop     #620    +/-   ##
=========================================
  Coverage    99.95%   99.95%            
=========================================
  Files          114      115     +1     
  Lines         4599     4828   +229     
  Branches       254      265    +11     
=========================================
+ Hits          4597     4826   +229     
  Partials         2        2            
Impacted Files Coverage Δ
...ities/data_classes/api_gateway_authorizer_event.py 100.00% <100.00%> (ø)
.../utilities/data_classes/api_gateway_proxy_event.py 100.00% <100.00%> (ø)
...lambda_powertools/utilities/data_classes/common.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 16563bb...97c17c9. Read the comment docs.

@michaelbrewer michaelbrewer changed the title feat: http api v2 authorizer with simple response feat(data-classes): http api v2 authorizer with simple response Aug 18, 2021
@michaelbrewer michaelbrewer marked this pull request as ready for review August 19, 2021 05:17
@michaelbrewer
Copy link
Contributor Author

@heitorlessa - do you know of any other sources for documentation on http api authorizers payload v2

@pull-request-size pull-request-size bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Aug 20, 2021
@boring-cyborg boring-cyborg bot added the documentation Improvements or additions to documentation label Aug 20, 2021
@pull-request-size pull-request-size bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Aug 20, 2021
@heitorlessa heitorlessa self-assigned this Aug 20, 2021
@heitorlessa heitorlessa added the feature New feature or functionality label Aug 20, 2021
@heitorlessa
Copy link
Contributor

heitorlessa commented Aug 20, 2021

@sthulb could you have a look at the ARN Parser as it's the only area I'm in doubt, please? Nvm, it's the actual API GW ARN generated by API GW, that piece is stable

Copy link
Contributor

@heitorlessa heitorlessa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor suggested change on Authorizer Response class name for v2, and could you create a new section for HTTP API authorizers in the data class docs?

That will make it faster to release it tomorrow, pretty plz ;)

@michaelbrewer
Copy link
Contributor Author

@heitorlessa Done and added in a policy builder based on the blueprint.

@michaelbrewer michaelbrewer changed the title feat(data-classes): http api v2 authorizer with simple response feat(data-classes): http api and rest api authorizer Aug 21, 2021
Copy link
Contributor

@heitorlessa heitorlessa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for making the other improvements. Two tiny changes to improve UX and we're good to go!

@heitorlessa heitorlessa added this to the 1.20.0 milestone Aug 21, 2021
APIGatewayAuthorizerResponse,
HttpVerb,
)
from secrets import compare_digest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooooh shiny!

Copy link
Contributor

@heitorlessa heitorlessa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much Mike! I'm merging as-is, and fixing some typos and the allow/deny_all_routes to take a method param w/ ALL by default.

@heitorlessa heitorlessa changed the title feat(data-classes): http api and rest api authorizer feat(data-classes): authorizer for http api and rest api Aug 21, 2021
@heitorlessa heitorlessa merged commit d02dd2e into aws-powertools:develop Aug 21, 2021
@michaelbrewer michaelbrewer deleted the feat-api-gw-auth-v2 branch August 21, 2021 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation feature New feature or functionality size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants