How do I setup Route 53 to point to Api Gateway

8,309

You have to create a SSL certificate using the Certificate Manager. For an edge endpoint, create it in eu-east-1, for regional and private endpoints, create it in the region you are deploying the API gateway in (or the lambda). Read more here. I will refer to the ARN as CertificateArn

You have to configure a AWS::ApiGateway::DomainName:

"MyDomainName": {
  "Type": "AWS::ApiGateway::DomainName",
  "Properties": {
    "DomainName": {"Ref: "DomainName"},
    "CertificateArn": "arn:aws:acm:us-east-1:111122223333:certificate/fb1b9770-a305-495d-aefb-27e5e101ff3"
  }
}

This enables the Domain for the API Gateway. Next, you need to expose the API (i.e. your RestAPI), in a specific deployment stage. In your template, your have no deployment stages. Take a look a AWS::ApiGateway::Stage. A minimal example would look like this:

"Prod": {
            "Type": "AWS::ApiGateway::Stage",
            "Properties": {
                "StageName": "Prod",
                "Description": "Prod Stage",
                "RestApiId": {
                    "Ref": "APIGateway"
                },
                "DeploymentId": {
                    "Ref": "APITDeploymentTest"
                },
}

However, you most likely want some additional configuration in that. I suggest you take a look at the MethodSettings property.

At last, deploy a basepath mapping resource: AWS::ApiGateway::BasePathMapping. I suggest you map the basepath to the stage you created like this:

"ProdDomainBasePath": {
  "Type" : "AWS::ApiGateway::BasePathMapping",
  "Properties" : {
    "DomainName" : {"Ref: "DomainName"},
    "RestApiId" : {"Ref": "APIGateway"},
    "Stage" : "Prod"
  }
}

If you change an AWS::ApiGateway::Stage resource, you have to force an update on the corresponding AWS::ApiGateway::Deployment resource - this usually means renaming the AWS::ApiGateway::Deployment resource, to keep that in mind. Otherwise, it wont be deployed.

That should do it.

Share:
8,309

Related videos on Youtube

Justin808
Author by

Justin808

Just some guy on the interwebs.

Updated on September 18, 2022

Comments

  • Justin808
    Justin808 almost 2 years

    I'm writing a Cloudformation config file to create a website all in one go. This includes, creating lambda functions, creating the API Gateway, Setting up a S3 Bucket, Creating the Route 53 zone and records.

    So far:

    • Creating Lambda functions and it's role (works)
    • Creating API Gateway it's deployment and it's role (works)
    • Creating a S3 bucket and it's policy (works)
    • Creating a Route 53 zone and DNS records for the site (works)
    • Create a domain for API Gateway (no idea what I'm doing)

    So domain.com serves up the files in the S3 bucket without a problem. Using the AWS URI for API Gateway works https://trydsoonjc.execute-api.us-west-2.amazonaws.com/app/path/here without a problem.

    What I want to setup is a api.domain.com to point to the API Gateway to access the server's API.

    How do I connect Route 53 to API Gateway?

    My Cloudformation as it stand now is this:

    {
      "AWSTemplateFormatVersion": "2010-09-09",
      "Description" : "Website",
    
      "Parameters": {
        "DomainName": {
          "Type" : "String",
          "Description" : "The DNS name of an Amazon Route 53 hosted zone e.g. server.com",
          "AllowedPattern" : "(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)",
          "ConstraintDescription" : "must be a valid DNS zone name."
        }
      },
    
      "Mappings" : {
        "RegionMap" : {
          "us-east-1" : { "S3HostedZoneId" : "Z3AQBSTGFYJSTF", "S3WebsiteEndpoint" : "s3-website-us-east-1.amazonaws.com" },
          "us-west-1" : { "S3HostedZoneId" : "Z2F56UZL2M1ACD", "S3WebsiteEndpoint" : "s3-website-us-west-1.amazonaws.com" },
          "us-west-2" : { "S3HostedZoneId" : "Z3BJ6K6RIION7M", "S3WebsiteEndpoint" : "s3-website-us-west-2.amazonaws.com" },
          "eu-west-1" : { "S3HostedZoneId" : "Z1BKCTXD74EZPE", "S3WebsiteEndpoint" : "s3-website-eu-west-1.amazonaws.com" },
          "ap-southeast-1" : { "S3HostedZoneId" : "Z3O0J2DXBE1FTB", "S3WebsiteEndpoint" : "s3-website-ap-southeast-1.amazonaws.com" },
          "ap-southeast-2" : { "S3HostedZoneId" : "Z1WCIGYICN2BYD", "S3WebsiteEndpoint" : "s3-website-ap-southeast-2.amazonaws.com" },
          "ap-northeast-1" : { "S3HostedZoneId" : "Z2M4EHUR26P7ZW", "S3WebsiteEndpoint" : "s3-website-ap-northeast-1.amazonaws.com" },
          "sa-east-1" : { "S3HostedZoneId" : "Z31GFT0UA1I2HV", "S3WebsiteEndpoint" : "s3-website-sa-east-1.amazonaws.com" }
        }
      },
    
      "Resources": {
        "LambdaExecutionRole": {
          "Type": "AWS::IAM::Role",
          "Properties": {
            "AssumeRolePolicyDocument": {
              "Statement": [{
                "Effect": "Allow",
                "Principal": {
                  "Service": "lambda.amazonaws.com"
                },
                "Action": [ "sts:AssumeRole" ]
              }]
            },
            "Path": "/",
            "Policies": [{
              "PolicyName": "execution",
              "PolicyDocument": {
                "Statement": [{
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": "*"
                }, {
                  "Effect": "Allow",
                  "Action": [
                    "dynamodb:BatchGetItem",
                    "dynamodb:CreateTable",
                    "dynamodb:DeleteItem",
                    "dynamodb:DescribeTable",
                    "dynamodb:GetItem",
                    "dynamodb:PutItem",
                    "dynamodb:Query",
                    "dynamodb:Scan",
                    "dynamodb:UpdateItem",
                    "s3:GetObject",
                    "s3:PutObject",
                    "s3:ListBucket"
                  ],
                  "Resource": "*"
                }]
              }
            }]
          }
        },
    
        "APIGatewayExecutionRole": {
          "Type": "AWS::IAM::Role",
          "Properties": {
            "AssumeRolePolicyDocument": {
              "Statement": [{
                "Effect": "Allow",
                "Principal": {
                  "Service": "apigateway.amazonaws.com"
                },
                "Action": [ "sts:AssumeRole" ]
              }]
            },
            "Path": "/",
            "Policies": [{
              "PolicyName": "execution",
              "PolicyDocument": {
                "Statement": [{
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": "*"
                }, {
                  "Effect": "Allow",
                  "Action": [
                    "lambda:InvokeFunction"
                  ],
                  "Resource": "*"
                }]
              }
            }]
          }
        },
    
        "LambdaFunctionUpdate": {
          "Type": "AWS::Lambda::Function",
          "Properties": {
            "Code": {
              "ZipFile": "exports.handler = function (event, context) { context.succeed(\"Hello, World!\"); };"
            },
            "Description": "Update handler.",
            "Handler": "index.handler",
            "MemorySize": 128,
            "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn" ] },
            "Runtime": "nodejs4.3",
            "Timeout": 30
          }
        },
    
        "APIGateway": {
          "Type": "AWS::ApiGateway::RestApi",
          "Properties": {
            "Body": @@swagger,
            "FailOnWarnings": true,
            "Name": "smallPictures",
            "Description": "Structured wiki"
          }
        },
    
        "APITDeploymentTest": {
          "Type": "AWS::ApiGateway::Deployment",
          "Properties": {
            "RestApiId": { "Ref": "APIGateway" },
            "Description": "Deploy for testing",
            "StageName": "smallPicturesTesting"
          }
        },
    
        "WebsiteBucket" : {
          "Type" : "AWS::S3::Bucket",
          "Properties" : {
            "BucketName": {"Ref":"DomainName"},
            "AccessControl" : "PublicRead",
            "WebsiteConfiguration" : {
              "IndexDocument" : "index.html",
              "ErrorDocument" : "404.html"
            }
          },
          "DeletionPolicy" : "Retain"
        },
    
        "WebsiteBucketPolicy" : {
          "Type" : "AWS::S3::BucketPolicy",
          "Properties" : {
            "Bucket" : {"Ref" : "WebsiteBucket"},
            "PolicyDocument": {
              "Statement": [{
                  "Action": [ "s3:GetObject" ],
                  "Effect": "Allow",
                  "Resource": { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "WebsiteBucket" } , "/*" ]]},
                  "Principal": "*"
              }]
            }
          }
        },
    
        "DNS": {
          "Type": "AWS::Route53::HostedZone",
          "Properties": {
            "HostedZoneConfig": {
              "Comment": { "Fn::Join" : ["", ["Hosted zone for ", { "Ref" : "DomainName" } ]]}
            },
            "Name": { "Ref" : "DomainName" },
            "HostedZoneTags" : [{
              "Key": "Application",
              "Value": "Blog"
            }]
          }
        },
    
        "DNSRecord": {
          "Type": "AWS::Route53::RecordSetGroup",
          "Properties": {
            "HostedZoneName": {
                "Fn::Join": [ "", [ { "Ref": "DomainName" }, "." ]]
            },
            "Comment": "Zone records.",
            "RecordSets": [
              {
                "Name": { "Ref": "DomainName" },
                "Type": "A",
                "AliasTarget": {
                  "HostedZoneId": { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "S3HostedZoneId" ]},
                  "DNSName": { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "S3WebsiteEndpoint" ]}
                }
              }, {
                "Name": { "Fn::Join" : ["", ["www.", { "Ref" : "DomainName" }]]},
                "Type": "CNAME",
                "TTL" : "900",
                "ResourceRecords" : [
                  {"Fn::GetAtt":["WebsiteBucket", "DomainName"]}
                ]
              }
            ]
          }
        }
      },
    
      "Outputs": {
        "WebsiteURL": {
          "Value": { "Fn::GetAtt": ["WebsiteBucket", "WebsiteURL" ] },
          "Description": "URL for website hosted on S3"
        }
      }
    }