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

(aws-apigatewayv2): Validation of apiMappingKey in ApiMappingProps is too strict #26298

Closed
Dzhuneyt opened this issue Jul 9, 2023 · 7 comments
Labels
@aws-cdk/aws-apigatewayv2 Related to Amazon API Gateway v2 bug This issue is a bug. closed-for-staleness This issue was automatically closed because it hadn't received any attention in a while. effort/medium Medium work item – several days of effort p2 response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days.

Comments

@Dzhuneyt
Copy link
Contributor

Dzhuneyt commented Jul 9, 2023

Describe the bug

Previously resolved at #15948, but I think not fully.

The new ApiMapping() construct is pretty much a wrapper around the CfnApiMapping CloudFormation resource, but I think it is opinionated regarding the apiMappingKey prop in a way that doesn't make sense.

Both the CloudFormation resource and the AWS Web Based console allow the mapping key to be empty, but the CDK construct new ApiMapping() enforces the prop to be an non-empty string, when defined, which stems from this check.

This is fine for the most common use case, where there is just API mapping inside a Custom Domain and people never pass the "apiMappingKey" prop, or pass it as undefined, but for more advanced use cases like adding two mappings inside the same Custom Domain, this is actually a blocking limitation. One that just forced me to not use this L1 construct but rather opt for the L1 CloudFormation resources.

Expected Behavior

People should be able to use the new ApiMapping() construct passing an empty apiMappingKey, which matches the CloudFormation L1 resource and the AWS web console experience.

Current Behavior

People should be able to use multiple new ApiMapping() constructs with an empty apiMappingKey.

Reproduction Steps

Using two instances of:

new ApiMapping(this, 'ApiMappingOne'...)
new ApiMapping(this, 'ApiMappingTwo'...)

while passing an empty string inside the prop "apiMappingKey" for both, leads to a CDK validation error empty string for api mapping key not allowed, but the same operation is allowed "manually" through the AWS Web Console or CloudFormation templates.

Possible Solution

Remove this validation.

Additional Information/Context

No response

CDK CLI Version

2.85.0 (build 4e0d726)

Framework Version

No response

Node.js Version

v18.16.0

OS

MacOS

Language

Typescript

Language Version

No response

Other information

No response

@Dzhuneyt Dzhuneyt added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jul 9, 2023
@github-actions github-actions bot added the @aws-cdk/aws-apigatewayv2 Related to Amazon API Gateway v2 label Jul 9, 2023
@pahud
Copy link
Contributor

pahud commented Jul 10, 2023

CFN allows this prop to be undefined but I am not sure if it allows it to be empty string(''), which is defined but empty string.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-apimapping.html#cfn-apigatewayv2-apimapping-apimappingkey

Are you able to pass empty string '' in the L1 cosntruct with no error? If yes, we probably should remove this restriction.

Can you share your cdk synth output for this resource using L1 construct that successfully deploy in CFN?

@pahud
Copy link
Contributor

pahud commented Jul 10, 2023

And, can you elaborate more about your use case for "adding two mappings inside the same Custom Domain" that requires the apiMappingKey to be ""(empty string)?

@pahud pahud self-assigned this Jul 10, 2023
@pahud pahud added p2 effort/medium Medium work item – several days of effort and removed needs-triage This issue or PR still needs to be triaged. labels Jul 10, 2023
@Dzhuneyt
Copy link
Contributor Author

Dzhuneyt commented Jul 10, 2023

The use case is, have two domains that map to the same API Gateway's stage, e.g.
customer.prod.something.com
customer.something.com

Both domains are registered as separate AWS::ApiGateway::DomainName resources and have their own ACM configuration.

@Dzhuneyt
Copy link
Contributor Author

Dzhuneyt commented Jul 10, 2023

Some excerpts from an active/deployed CloudFormation stack, confidential information redacted with "XXX" for privacy:

...
...
  "DomainNamemainXXXB1F90BF9": {
   "Type": "AWS::ApiGatewayV2::DomainName",
   "Properties": {
    "DomainName": "main-api.example.com",
    "DomainNameConfigurations": [
     {
      "CertificateArn": "arn:aws:acm:us-east-1:XXX:certificate/41125841-30ea-478d-a759-6541577bf6bb",
      "EndpointType": "REGIONAL"
     }
    ]
   }
  },
  "CfnApiMappingmainXXX": {
   "Type": "AWS::ApiGatewayV2::ApiMapping",
   "Properties": {
    "ApiId": {
     "Ref": "HttpApiF5A9A8A7"
    },
    "DomainName": {
     "Ref": "DomainNamemainXXXB1F90BF9"
    },
    "Stage": "$default",
    "ApiMappingKey": ""
   },
   "DependsOn": [
    "DomainNamemainXXXB1F90BF9",
    "HttpApiDefaultStage3EEB07D6"
   ]
  },
...
...
  "DomainNamemainXXXB987A8BE": {
   "Type": "AWS::ApiGatewayV2::DomainName",
   "Properties": {
    "DomainName": "main-api.prod.example.com",
    "DomainNameConfigurations": [
     {
      "CertificateArn": "arn:aws:acm:us-east-1:XXX:certificate/41125841-30ea-478d-a759-6541577bf6bb",
      "EndpointType": "REGIONAL"
     }
    ]
   }
  },
  "CfnApiMappingmainXXX": {
   "Type": "AWS::ApiGatewayV2::ApiMapping",
   "Properties": {
    "ApiId": {
     "Ref": "HttpApiF5A9A8A7"
    },
    "DomainName": {
     "Ref": "DomainNamemainXXXB987A8BE"
    },
    "Stage": "$default",
    "ApiMappingKey": ""
   },
   "DependsOn": [
    "DomainNamemainXXXB987A8BE",
    "HttpApiDefaultStage3EEB07D6"
   ]
  },

@pahud
Copy link
Contributor

pahud commented Jul 10, 2023

@Dzhuneyt

Thank you for your use case sharing. If cloudformation accepts empty string for ApiMappingKey, I don't see any reason we should restrict that in CDK.

@pahud pahud added p1 and removed p2 labels Jul 10, 2023
@pahud
Copy link
Contributor

pahud commented Jul 11, 2023

Hi @Dzhuneyt

I just write a sample cdk app for your use case. I think apiMappingKey could be just ignored as below:

import * as cdk from 'aws-cdk-lib';
import * as apigw from '../../lib';

class DummyRouteIntegration extends apigw.HttpRouteIntegration {
  constructor() {
    super('DummyRouteIntegration');
  }

  public bind(_: apigw.HttpRouteIntegrationBindOptions): apigw.HttpRouteIntegrationConfig {
    return {
      payloadFormatVersion: apigw.PayloadFormatVersion.VERSION_1_0,
      type: apigw.HttpIntegrationType.HTTP_PROXY,
      method: apigw.HttpMethod.ANY,
      uri: 'https://aws.amazon.com/{proxy}',
    };
  }
}

const app = new cdk.App();

const env = { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT };

const stack = new cdk.Stack(app, 'aws-cdk-aws-apigatewayv2-http-apimapping', { env });

const MOCK_CERT_ARN = 'arn:aws:acm:us-east-1:*****:certificate/********';
const certificate = cdk.aws_certificatemanager.Certificate.fromCertificateArn(stack, 'ImportedCert', MOCK_CERT_ARN);

const domain1 = new apigw.DomainName(stack, 'Domain1', {
  domainName: 'demo1.example.com',
  certificate,
});

const domain2 = new apigw.DomainName(stack, 'Domain2', {
  domainName: 'demo2.example.com',
  certificate,
});

const httpApi = new apigw.HttpApi(stack, 'HttpApi');

httpApi.addRoutes({
  path: '/{proxy+}',
  integration: new DummyRouteIntegration(),
});

new apigw.ApiMapping(stack, 'Mapping1', {
  api: httpApi,
  domainName: domain1,
  // apiMappingKey: 'domain1Mapping',
});

new apigw.ApiMapping(stack, 'Mapping2', {
  api: httpApi,
  domainName: domain2,
  // apiMappingKey: 'domain2Mapping',
});

app.synth();

This works for me with multiple custom domain name sharing a single http api with 2 apiMappings.

Does this work for you?

@pahud pahud added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. p2 and removed p1 labels Jul 11, 2023
@pahud pahud removed their assignment Jul 12, 2023
@github-actions
Copy link

This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

@github-actions github-actions bot added closing-soon This issue will automatically close in 4 days unless further comments are made. closed-for-staleness This issue was automatically closed because it hadn't received any attention in a while. and removed closing-soon This issue will automatically close in 4 days unless further comments are made. labels Jul 13, 2023
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. closed-for-staleness This issue was automatically closed because it hadn't received any attention in a while. effort/medium Medium work item – several days of effort p2 response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days.
Projects
None yet
Development

No branches or pull requests

2 participants