简体   繁体   中英

AWS CDK - Tie Cognito user pool to API Gateway

I'm trying to set up a pretty basic infrastructure using AWS CDK that consists of

  • Cognito user pool
  • A lambda
  • An Authorizer
  • API GW with root and sub path and few methods
  • The path which should use the Cognito User Pool as Authorizer

Problem: I don't know how to properly create the Authorizer so it is accepted by API GW

Synthing the CF template works fine, but during deployment I get the following error:

Invalid authorizer ID specified. Setting the authorization type to CUSTOM or COGNITO_USER_POOLS requires a valid authorizer.

So, seems my Authorizer is not proper enough, even if the creation of the authorizer itself is marked as successful during the deployment.

Any ideas?

Here what I have in code:

from aws_cdk import (
    core,
    aws_lambda,
    aws_apigateway,
    aws_cognito
)


class PlayGroundStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Basic lamdba setup
        my_lambda = aws_lambda.Function(
            scope=self,
            id="lambda-1",
            runtime=aws_lambda.Runtime.PYTHON_3_6,
            code=aws_lambda.Code.asset('lambda'),
            handler='hello.handler'
        )

        # Few MethodOptions for the API GW
        my_get_operation = aws_apigateway.MethodOptions(operation_name="GET")
        my_post_operation = aws_apigateway.MethodOptions(operation_name="POST")

        # The API itself
        rest_api = aws_apigateway.LambdaRestApi(
            scope=self,
            id="rest-api-1",
            handler=my_lambda,
            proxy=False,
            default_method_options=my_get_operation
        )

        # User Pool used for auth
        api_userpool = aws_cognito.UserPool(
            scope=self,
            id="user-pool-1",
            sign_in_type=aws_cognito.SignInType.EMAIL
        )

        # The authorizer that should be attached to API GW
        my_cfn_authorizer = aws_apigateway.CfnAuthorizer(
            id='api_authorizer_cfn',
            rest_api_id=rest_api.rest_api_id,
            name='api_authorizer_cfn_name',
            scope=self,
            type='COGNITO_USER_POOLS',
            identity_source='method.request.header.Authorization',
            provider_arns=[api_userpool.user_pool_arn]
        )

        # Set methods for root node
        rest_api.root.add_method(my_get_operation.operation_name)
        rest_api.root.add_method(my_post_operation.operation_name)

        # Create a resource
        my_resource = rest_api.root.add_resource("my_sub_url")
        # And attach the Authorizer
        # This is where I get the error
        my_resource.add_method(http_method="GET",
                               authorization_type=aws_apigateway.AuthorizationType.COGNITO,
                               authorizer=my_cfn_authorizer)

I figured it out. You need to set

authorization_type = my_cfn_authorizer.auth_type

and that fixes everything. It would've been so much better if they could just tell us to do that in the documentation, but python documentation is scarce.


class PlayGroundStack(core.Stack):

        ...

        # The authorizer that should be attached to API GW
        my_cfn_authorizer = aws_apigateway.CfnAuthorizer(
            id='api_authorizer_cfn',
            rest_api_id=rest_api.rest_api_id,
            name='api_authorizer_cfn_name',
            scope=self,
            type='COGNITO_USER_POOLS',
            identity_source='method.request.header.Authorization',
            provider_arns=[api_userpool.user_pool_arn]
        )

        # Set methods for root node
        rest_api.root.add_method(my_get_operation.operation_name)
        rest_api.root.add_method(my_post_operation.operation_name)

        my_resource = rest_api.root.add_resource("my_sub_url")
        # FIX HERE!!!!!!!
        my_resource.add_method(http_method="GET",
                               authorization_type=my_cfn_authorizer.auth_type, 
                               authorizer=my_cfn_authorizer)

you can't use string literal to ID field. The logical id that you provide for each ressource is concatenaed with a hash at run time. In other word, the ID that you see, and the ID that you get are not the same. More details here

You have to use getter api to retrieve the ID of your ressource. For example rest_api.rest_api_id()

cdk documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM