Skip to content
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

(apigatewayv2): IAM Permissions not being created for Api Gateway to access http lambda integration #18201

Closed
kevinmcgillicuddy opened this issue Dec 28, 2021 · 6 comments · Fixed by #18716
Assignees
Labels
@aws-cdk/aws-apigatewayv2 Related to Amazon API Gateway v2 bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. p1

Comments

@kevinmcgillicuddy
Copy link

kevinmcgillicuddy commented Dec 28, 2021

What is the problem?

API gateway does not create needed IAM roles to connect to an HTTP Lambda integration, this started when upgrading to CDK v2

Reproduction Steps

When using AWS-CDK 2.3.0-alpha.0

"@aws-cdk/aws-apigatewayv2-alpha": "2.3.0-alpha.0",
"@aws-cdk/aws-apigatewayv2-authorizers-alpha": "^2.3.0-alpha.0",
"@aws-cdk/aws-apigatewayv2-integrations-alpha": "^2.3.0-alpha.0"

We have 2 routes that point to the same integration, permissions in cloudformation are only created for the first one

const jobsIntegration = new apiGatewayIntegrations.HttpLambdaIntegration('JobsIntegration', jobsFunction);

  props.httpApi.addRoutes({
    path: '/hr/jobs',
    methods: [ apiGateway.HttpMethod.GET ],
    integration: jobsIntegration,
    authorizer: props.Authorizer
  });

  props.httpApi.addRoutes({
    path: '/hr/job/{reqId}',
    methods: [ apiGateway.HttpMethod.GET ],
    integration: jobsIntegration,
    authorizer: props.Authorizer
  });

cloudformation:

    "HttpApiGEThrjobsJobsIntegrationPermissionFFAB51F1": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Fn::ImportValue": "OutputFnGetAttJobsFunction382FBD18Arn3EEB55F3"
        },
        "Principal": "apigateway.amazonaws.com",
        "SourceArn": {
          "Fn::Join": [
            "",
            [
              "arn:",
              {
                "Ref": "AWS::Partition"
              },
              ":execute-api:us-east-1:123:",
              {
                "Ref": "HttpApiF5A9A8A7"
              },
              "/*/*/hr/jobs"
            ]
          ]
        }
      },
      "Metadata": {
        "aws:cdk:path": "/ApiGateway/HttpApi/GET--hr--jobs/JobsIntegration-Permission"
      }

API gateway access logs:

   {
    "requestId": "=",
    "ip": "",
    "requestTime": "28/Dec/2021:16:25:46 +0000",
    "httpMethod": "GET",
    "routeKey": "GET /hr/job/{reqId}",
    "status": "500",
    "protocol": "HTTP/1.1",
    "responseLength": "35",
    "contenxtError": "Internal Server Error",
    "integrationErrorMessage": "The IAM role configured on the integration or API Gateway doesn't have permissions to call the integration. Check the permissions and try again."
}

What did you expect to happen?

It to create permissions for both routes

What actually happened?

It only created for the first route - see above cloudformation output

work around is as follows - create a new integration linked to the same function

 const jobsIntegration = new apiGatewayIntegrations.HttpLambdaIntegration('JobsIntegration', jobsFunction);
 **const jobIntegration = new apiGatewayIntegrations.HttpLambdaIntegration('JobIntegration', jobsFunction);**

   props.httpApi.addRoutes({
     path: '/hr/jobs',
     methods: [ apiGateway.HttpMethod.GET ],
     integration: jobsIntegration,
     authorizer: props.Authorizer
   });

   props.httpApi.addRoutes({
     path: '/hr/job/{reqId}',
     methods: [ apiGateway.HttpMethod.GET ],
     integration: **jobIntegration** ,
     authorizer: props.Authorizer
   });

CDK CLI Version

2.3.0

Framework Version

No response

Node.js Version

14.18.0

OS

Windows 11

Language

Typescript

Language Version

4.5.2

Other information

No response

@kevinmcgillicuddy kevinmcgillicuddy added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Dec 28, 2021
@github-actions github-actions bot added the @aws-cdk/aws-iam Related to AWS Identity and Access Management label Dec 28, 2021
@peterwoodworth peterwoodworth changed the title IAM Permissions not being created for Api Gateway to access http lambda integration (apigwv2): IAM Permissions not being created for Api Gateway to access http lambda integration Dec 28, 2021
@peterwoodworth peterwoodworth removed the @aws-cdk/aws-iam Related to AWS Identity and Access Management label Dec 28, 2021
@github-actions github-actions bot added the @aws-cdk/aws-iam Related to AWS Identity and Access Management label Dec 28, 2021
@peterwoodworth peterwoodworth changed the title (apigwv2): IAM Permissions not being created for Api Gateway to access http lambda integration (apigatewayv2): IAM Permissions not being created for Api Gateway to access http lambda integration Dec 28, 2021
@github-actions github-actions bot added the @aws-cdk/aws-apigatewayv2 Related to Amazon API Gateway v2 label Dec 28, 2021
@peterwoodworth peterwoodworth removed the @aws-cdk/aws-iam Related to AWS Identity and Access Management label Dec 28, 2021
@ryparker ryparker added the p1 label Dec 28, 2021
@nanto
Copy link

nanto commented Jan 5, 2022

I got the same problem on CDK v1.137.0. The following workaround (calling integration.bind method explicitly) works for me.

import { HttpApi, HttpMethod } from "@aws-cdk/aws-apigatewayv2";
import { HttpLambdaIntegration } from "@aws-cdk/aws-apigatewayv2-integrations";

const api = new HttpApi(...);
const integration = new HttpLambdaIntegration(...);
api.addRoutes({
  path: '/foo',
  methods: [HttpMethod.GET],
  integration,
});
const [barRoute] = api.addRoutes({
  path: '/bar',
  methods: [HttpMethod.GET],
  integration,
});
integration.bind({ route: barRoute, scope: barRoute });

@tmokmss
Copy link
Contributor

tmokmss commented Jan 16, 2022

WebSocket API also has the same issue #18208.
Currently it seems we cannot share the same integration instance with multiple routes.

Another workaround is to create an integration instance per route.

Since we are calling bind only once per integration instance, it isn't possible to reuse a single integration instance for multiple routes.

if (!this.integration) {
const config = this.bind(options);

@andrei-cdl
Copy link

andrei-cdl commented Jan 18, 2022

This might be related, but I also have similar behavior after updating from 1.134.0 to 1.139.0. I have 2 routes added to an httpGateway.

however only 1 route is added to the lambda trigger (the first one listed).

i.e

gateway.addRoutes({
    path: '/user',
    methods: [HttpMethod.ANY],
    integration: userFnProxy,
  });

  gateway.addRoutes({
    path: '/user/{proxy+}',
    methods: [HttpMethod.ANY],
    integration: userFnProxy,
  });

it no longer adds the {proxy+} which is not the correct behavior but makes sense as to why it's not created the IAM permissions in your case as well since the second route isn't being added. (I only noticed this because I deleted all routes to the lambda and redeployed, the second route is missing in aws console now as shown in the image there should be 2 triggers.

image

@fullstackcreatives
Copy link

Same issue here after upgrading to cdk v2 and to "@aws-cdk/aws-apigatewayv2-integrations-alpha" I get

"The IAM role configured on the integration or API Gateway doesn't have permissions to call the integration. Check the permissions and try again"

for all routes but the first one.

If you create a "HttpLambdaIntegration" for each route it works. Is this the expected behaviour?

@andrei-cdl
Copy link

andrei-cdl commented Jan 25, 2022

@fullstackcreatives it works if you define multiple HttpLambdaIntegrations?

i.e

  const userFnBase = new LambdaProxyIntegration({ handler: userFn })  // renamed to HttpLambdaIntegration > 1.137
  gateway.addRoutes({
    path: '/user',
    methods: [HttpMethod.ANY],
    integration: userFnBase,
  });
  
  const userFnProxy = new LambdaProxyIntegration({ handler: userFn })
  gateway.addRoutes({
    path: '/user/{proxy+}',
    methods: [HttpMethod.ANY],
    integration: userFnProxy,
  });

@mergify mergify bot closed this as completed in #18716 Mar 8, 2022
mergify bot pushed a commit that referenced this issue Mar 8, 2022
…execute permission is created (#18716)

When multiple routes are defined for a single lambda integration, only one of
the routes gets permission to execute the function. This is because the
permissions are added when the integration is bound to the route, which happens
only once per integration.

Split the `_bindToRoute` workflow into two parts:

1. The actual bind, followed by the creation of an `HttpIntegration`. We keep
doing this only once per integration.
2. A post-bind step, that happens for every route. 

In the case of `HttpLambdaIntegration`, adding the permission has been moved to
the post bind step. All other integrations remain the same.

Fixes #18201.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@github-actions
Copy link

github-actions bot commented Mar 8, 2022

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

TheRealAmazonKendra pushed a commit to TheRealAmazonKendra/aws-cdk that referenced this issue Mar 11, 2022
…execute permission is created (aws#18716)

When multiple routes are defined for a single lambda integration, only one of
the routes gets permission to execute the function. This is because the
permissions are added when the integration is bound to the route, which happens
only once per integration.

Split the `_bindToRoute` workflow into two parts:

1. The actual bind, followed by the creation of an `HttpIntegration`. We keep
doing this only once per integration.
2. A post-bind step, that happens for every route. 

In the case of `HttpLambdaIntegration`, adding the permission has been moved to
the post bind step. All other integrations remain the same.

Fixes aws#18201.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-apigatewayv2 Related to Amazon API Gateway v2 bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. p1
Projects
None yet
9 participants