Search code examples
amazon-web-servicesaws-api-gatewayaws-cdk

hostedZone ID doesn't match when using custom domain for api gateway


I'm using CDK to deploy aws api gateway.

The created api gateway looks like blow, and it's mapped to hosted zone Z1UJRXOUMOOFQ8:

enter image description here

My Route 53 hosted zone is this, and it only has one hosted zone Z07841403UX33F69270EK:

enter image description here

My questions are:

  1. Why are these two hosted zone ID not match? I'm expecting the API gateway hosted zone ID to be the same as the hosted zone ID shown in Route 53, and I have no idea where does API gateway hosted zone ID come from as I only have one hosted zone in this AWS account's Route 53.
  2. The API gateway domain name shown in the first picture d-mtr****.execute-api.us-east-1.amazonaws.com doesn't match the created API gateway https://mmz****.execute-api.us-east-1.amazonaws.com/prod/ which is outputed during CDK deployment.

Code

Dependencies in package.json:

  "dependencies": {
    "@aws-cdk/aws-apigatewayv2": "^1.180.0",
    "@aws-cdk/aws-apigatewayv2-alpha": "^2.50.0-alpha.0",
    "@aws-cdk/aws-apigatewayv2-integrations": "^1.180.0",
    "@aws-cdk/aws-apigatewayv2-integrations-alpha": "^2.50.0-alpha.0",
    "aws-cdk-lib": "^2.46.0",
    "constructs": "^10.1.156",
    "source-map-support": "^0.5.21"
  }

API Gateway Stack:


import * as CDK from "aws-cdk-lib";

import * as CertificateManager from "aws-cdk-lib/aws-certificatemanager";
import * as Route53 from "aws-cdk-lib/aws-route53";
import * as Route53Targets from "aws-cdk-lib/aws-route53-targets";
import * as ApiGateway from "aws-cdk-lib/aws-apigateway";

import * as ELBv2 from "aws-cdk-lib/aws-elasticloadbalancingv2";
import { Construct } from "constructs";
import { ALPHA, StageInfo } from "../config/stage-config";
import * as Cognito from "aws-cdk-lib/aws-cognito";

export class ApigatewayStack extends CDK.Stack {
  // Prefix for CDK constrcut ID
  private readonly constructIdPrefix: string;
  private readonly domainCertificate: CertificateManager.Certificate;
  private readonly businessAccountAuthorizer: ApiGateway.CfnAuthorizer;
  public readonly restApi: ApiGateway.RestApi;
  constructor(scope: Construct, id: string, props: ApigatewayStackProps) {
    super(scope, id, props);

    this.constructIdPrefix = `${props.packageName}-${props.stageInfo.stageName}`;

    const hostedZone: Route53.IHostedZone = Route53.HostedZone.fromLookup(
      this,
      `${this.constructIdPrefix}-HostedZoneLookup`,
      {
        domainName: props.stageInfo.domainName,
      }
    );

    this.domainCertificate = new CertificateManager.Certificate(
      this,
      `${this.constructIdPrefix}-restApiCertificate`,
      {
        certificateName: "certificateForRestApi",
        domainName: props.stageInfo.domainName,
        validation: CertificateManager.CertificateValidation.fromDns(hostedZone),
      }
    );

    this.restApi = new ApiGateway.RestApi(
      this,
      `${this.constructIdPrefix}-restApi`,
      {
        restApiName: "restApi",
        description: "The centralized API for example.com",
        domainName: {
          domainName: props.stageInfo.domainName,
          certificate: this.domainCertificate,
          //mappingKey: props.pipelineStageInfo.stageName
        },

        defaultCorsPreflightOptions: {
          allowOrigins: ApiGateway.Cors.ALL_ORIGINS,
          allowMethods: ApiGateway.Cors.ALL_METHODS
        },
      }
    );

    new Route53.ARecord(this, "AliasRecordForRestApi", {
      recordName: "AliasRecordForRestApi",
      deleteExisting: true, // delete existing one instead of doing it manually later
      zone: hostedZone,
      target: Route53.RecordTarget.fromAlias(
        new Route53Targets.ApiGateway(this.restApi)
      ),
      // or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomain(domainName)),
    });

   // Irrelevant code is hiden
}

Update

I made a stupid mistake, the record name above should be the domain name. I thought it was just a name for the Route53 record, as sometimes you can give a name to an AWS resource just to distinguish it from others.

Changing it to domain name then the whole thing works.

Now the only thing I still don't know is why the hosted zone id in the first screenshot can not be found in my Route 53.


Solution

  • That's the hosted zone that the d-mtr****.execute-api.us-east-1.amazonaws.com is located in.

    You would use that to make an ALIAS record in route 53, which takes a hostname and a target zone, and this will save 1 DNS lookup compared to a CNAME

    If your domain is example.com, you'd add a record myapihostname.example.com ALIAS d-mtr****.execute-api.us-east-1.amazonaws.com and refer to the zone that you're targeting.