aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.51k stars 3.85k forks source link

api_gateway: Creating HTTP Integration with VPC Link and NLB #26612

Open bearrito opened 1 year ago

bearrito commented 1 year ago

Describe the bug

No way to set URI field from within CDK

Below is a standard HttpIntegration for Use with VPC Link and NLB

vpc_integration = apigateway.Integration(
            type=apigateway.IntegrationType.HTTP_PROXY,
            integration_http_method=HttpMethods.ANY,
            uri=uri,
            options=apigateway.IntegrationOptions(
                connection_type=apigateway.ConnectionType.VPC_LINK,
                request_parameters={
                    "integration.request.path.proxy": "method.request.path.proxy"
                },
                vpc_link=link,
            ),
        )

Various AWS Sources show different settings for the URI Field.

There seems to be two cases

  1. Either not setting the URI
  2. Setting the URI.

In cases where the URI is set it also appears necessary to append a parameter to the end usually something like

uri=self._nlb.load_balancer_dns_name/{proxy}

The URI is set here but no proxy

  1. https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-cli.html
  2. https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-with-private-integration.html

Sets URI and Proxy

This CDK sample shows using proxy on the end

  1. https://github.com/aws-samples/serverless-patterns/blob/main/cognito-restapi-vpclink-cdk/cdk/lib/cdk-cognito-fargate-stack.js#L190
  2. Example with user setting proxy https://github.com/aws/aws-cdk/issues/10435

Other Examples

Third party sources show using Proxy as well.

  1. https://manurana.medium.com/tutorial-connecting-an-api-gateway-to-a-vpc-using-vpc-link-682a21281263

From my own experience I can say that using proxy is required. So I cannot leave URI unset.

However, the nlb.load_balancer_dns_name is a token. Try to passing it to the URI field results in

Invalid HTTP endpoint specified for URI (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestExcep
tion; Request ID: 0e01f5e3-4846-4315-b70f-0e7d1f5c3cd8; Proxy: null)

It does not matter if I try to append proxy or simply pass in the NLB name. Doesn't work.

  1. So there is minimally a documenation issue with regards to proxy and setting method paramters
  2. There doesn't seem to be a way to set the URI from within CDK.

Expected Behavior

Populate the URI field

Current Behavior

The URI field produces an error.

Reproduction Steps

Run the attached code

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.83.1 (build 006b542)

Framework Version

No response

Node.js Version

unknown

OS

ubuntu

Language

Python

Language Version

No response

Other information

No response

pahud commented 1 year ago

According to this https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-integration.html#cfn-apigatewayv2-integration-integrationuri

I think the URI should be the NLB listener ARN but I am not 100% sure. Have you tried it yet?

bearrito commented 1 year ago

Couple notes I'm not using the V2 module of api gateway. I'm using CDK eg my import looks like from aws_cdk import aws_apigateway as apigateway

I'm not sure what that link is referencing but I'm relatively sure it would not work for this use case. It appears to reference a private API Gateway, not a VPC link. I've found the docs on this aren't super helpful, they seem to leave out specifics, namely it is applicable to a VPC Link. I ultimately have to go with what works for a VPC Link. What works is using the full DNS name + "{proxy}

The CLI examples I linked to show the use of the DNS name. Even, If passing the ARN was acceptable it would not show how to append the "proxy"

The typescript example I linked to shows what I need to be able to do from Python

const proxy = api.root.addProxy({
      defaultIntegration: new apigateway.HttpIntegration(`http://${service.loadBalancer.loadBalancerDnsName}/{proxy}`, {
        httpMethod: "ANY",
        options: {
          connectionType: apigateway.ConnectionType.VPC_LINK,
          vpcLink: link,
          requestParameters: {
            "integration.request.path.proxy": "method.request.path.proxy"
          }
        }

It looks like there was an issue related to this, whereby the URI is set automatically, again with no ability to append {proxy}

https://github.com/aws/aws-cdk/pull/10730/files

bearrito commented 1 year ago

I believe I sorted this out. Main thing was properly prepending the protocol http to the dns name.

For anyone getting here via search the following will work in Python

  vpc_integration = apigateway.Integration(
            type=apigateway.IntegrationType.HTTP_PROXY,
            integration_http_method=HttpMethods.ANY,
            uri="http://" + self._nlb.load_balancer_dns_name + "/{proxy}",
            options=apigateway.IntegrationOptions(
                connection_type=apigateway.ConnectionType.VPC_LINK,
                request_parameters={
                    "integration.request.path.proxy": "method.request.path.proxy"
                },
                vpc_link=link,
            ),
        )

Make sure your method has something equivalent to the below

default_method_options = apigateway.MethodOptions(
            authorization_type=apigateway.AuthorizationType.IAM,
            request_parameters={"method.request.path.proxy": True},
        )
  api.root.add_proxy(
            default_integration=vpc_integration,
            default_method_options=default_method_options,
        )
matthewlowry commented 6 months ago

Dear @bearrito.

If I could, I would reach out through the internet and gently kiss you on the forehead.

I have just spent 1.5 days of beating my head against a brick wall and just dimly vaguely starting to get my head around how to set the uri of a HTTP_PROXY to pass through the {proxy+} from the API resource path. Then I stumbled upon this issue, and your last comment, and the veil was lifted from my eyes.

Thank you, dear sir or madam, whoever you may be, for leaving some hints to fellow weary travelers.

bearrito commented 6 months ago

@matthewlowry

I'm glad it helped. The AWS docs on this have about 90% of what you need, but the remaining missing 10% will absolutely devour your time.

OakLake commented 4 months ago

@bearrito - I was starting to despair, but then I found this. It worked like a charm. God bless you! [EDIT: typo]

adminy commented 22 hours ago

@bearrito doesn't work when the following headers are inserted by another api gateway:

x-amzn-vpce-config
x-amzn-vpce-id
x-amzn-vpc-id

the idea is this:

=> APIGW => VPC Link (HTTP-Proxy) => NLB
=> NLB (TLS) => APIGW Interface Endpoint => APIGW