简体   繁体   中英

aws-cdk LambdaRestApi: The final policy size is bigger than the limit

Hi i have been trying many possibilities, but now i would need some help.

I am using aws-cdk to create architecture by code and so far things have going well. Now i am running into this issue:

The final policy size is bigger than the limit (20480)

In understand what it means, but i have no idea how to solve it.

I am creating a lambdafunction to handle all requests:

const router = new lambda.Function(this, apiName + '-handler-temp', {
      runtime: LambdaRuntime, // execution environment
      code: lambda.Code.fromAsset('bin/lambda'), // code loaded from "lambda" directory
      handler: 'index.handler', // file is "index", function is "handler"
      vpc: vpc,
      environment: {
        DB_HOST: props?.rdsEndpoint as string,
        DB_USER: props?.rdsDbUser as string,
        DB_PASS: props?.rdsDBPass as string,
        DB_PORT: props?.rdsPort as string,
        DB_DIALECT: props?.rdsDbSchema as string,
        DB_DATABASE: props?.rdsDBName as string,
      },
      layers: [layer],
      timeout: Duration.seconds(30),
      memorySize: 1024,
    })

and the LambdaRestApi is defined like this:

const api = new LambdaRestApi(this, apiName, {
      handler: router,
      proxy: false,
      cloudWatchRole: false,
      description: 'API for Backend',
      deployOptions: {
        stageName: 'prod',
      },
      domainName: domainProperties,
    })

I am creating Endpoints where i am using 23 times addMethod .

eg


const user = api.root.addResource('user')
user.addMethod(HttpMethod.POST)
user.addMethod(HttpMethod.GET)
user.addMethod(HttpMethod.PATCH)

since only one lambda is used to be invoked from apigateway, i am curious, how i can get control of only one policy to be used for lambda execution and it is not creating a new one every time.

I also tried to add property role: role to the lambda function with this role definition:

const role = new Role(this, apiName + 'ApiGWPermissions', {
      assumedBy: new ServicePrincipal('apigateway.amazonaws.com'),
    })

    role.addToPolicy(
      new PolicyStatement({
        resources: ['*'],
        actions: ['lambda:InvokeFunction'],
      })
    )

but then i am running into different errors.

Has someone solved this riddle?

Cheers

As suggested in the CDK issue which Ian Walters mentioned, stripping the generated method permissions solved this for me. I'm using .Net but I'd expect that the approach should work for all language implementations. This function removes the permissions:

public void StripMethodPermissions(ConstructNode node) {
    foreach (var child in node.Children) {
        if (child is Amazon.CDK.AWS.APIGateway.Method) {
            var method = ((Amazon.CDK.AWS.APIGateway.Method)child);
            var permissions = method.Node.Children.Where(c => c is Amazon.CDK.AWS.Lambda.CfnPermission);
            foreach (var permission in permissions) {
                child.Node.TryRemoveChild(permission.Node.Id);
            }
        }
        if (child.Node.Children.Length > 0) StripMethodPermissions(child.Node);
    }
}

I'm using the technique like this:

var api = new RestApi(this, "MyRestApi", new RestApiProps {
    RestApiName = "MyRestApiV1"
});

var handlerLambda = new Function(this, "RequestHandler", new FunctionProps {
    Runtime = Runtime.DOTNET_CORE_3_1,
    ...
});

// Add resources and methods which use the handlerLambda here

// Remove all generated permissions
StripMethodPermissions(api.Root.Node);

// Add a single invoke permission for the lambda
handlerLambda.GrantInvoke(new ServicePrincipal("apigateway.amazonaws.com"));

Thanks to nija-at for showing the way

@Elliveny has the correct answer. Here is a code snitbit for Python which does the same thing (as I cannot post formatted code in comments):

from aws_cdk import (
    aws_lambda as _lambda,
    aws_events as events,
    aws_iam as iam,
    core,
)

for child in self.node.children:
    if isinstance(child, events.Rule):
        for eventChild in child.node.children:
            if isinstance(eventChild, _lambda.CfnPermission):
                child.node.try_remove_child(eventChild.node.id)

Remember that if you do this, you still need to grant invoke on your lambda for the "events.amazonaws.com" ServicePrincipal. Something like:

my_lambda.add_permission(
    "RuleInvoke",
    principal=iam.ServicePrincipal("events.amazonaws.com"),
    action="lambda:InvokeFunction",
    source_arn=f"arn:aws:events:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:rule/your-rule-name-here*",
)

I hit a similar issue. There is a CDK issue that might help resolve it if addressed,

https://github.com/aws/aws-cdk/issues/9327

Its also worth noting that by default lambda integrations have allowTestInvoke set to true, which pretty much is going to double the policy document size.

I'm not sure if you can alter the integration options for the lambda with LambdaRestApi though, I'm using RestApi directly.

A short term fix might be to use RestApi rather than LambdaRestApi and create the lambda integration directly with the allowTestInvoke option set to false.

The other thing I did that helped was to just create more than one lambda that worked the same way, but got attached to different routes (eg same code, permissions etc, just different logical id) to also reduce the policy document size a bit.

I'm a bit pressed for development time hence the work-arounds. Personally, I think the right solution would be to fix it in the CDK and propose a PR such that LambdaRestApi just did what the user would expect, wild-card permission for the lambda for all

You can increase the memory size of lambda by doing this

    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/promoCodes/
      Role: !GetAtt FunctionRole.Arn
      Handler: promoCodesListCsvPDF.promoCodesListCsvPDF
      Policies:
        - AWSLambdaExecute # Managed Policy
        - AWSLambdaBasicExecutionRole # Managed Policy
      MemorySize: 512
      Layers:
        - !Ref NodeDependenciesLayer
      Events:
        promoCodesListCsvPDFEvent:
          Type: Api
          Properties:
            Path: /api/promo-codes/csv-pdf
            Method: POST

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