Comment configurer Route 53 pour pointer vers Api Gateway

12

J'écris un fichier de configuration Cloudformation pour créer un site Web en une seule fois. Cela comprend la création de fonctions lambda, la création de la passerelle API, la configuration d'un compartiment S3, la création de la zone Route 53 et des enregistrements.

Jusque là:

  • Création de fonctions Lambda et de son rôle (fonctionne)
  • Créer une passerelle API c'est son déploiement et son rôle (fonctionne)
  • Création d'un compartiment S3 et de sa stratégie (fonctionne)
  • Création d'une zone Route 53 et d'enregistrements DNS pour le site (travaux)
  • Créer un domaine pour API Gateway (aucune idée de ce que je fais)

Sert domain.comdonc les fichiers dans le compartiment S3 sans problème. L'utilisation de l'AWS URI pour API Gateway fonctionne https://trydsoonjc.execute-api.us-west-2.amazonaws.com/app/path/heresans problème.

Ce que je veux configurer est api.domain.comde pointer vers la passerelle API pour accéder à l'API du serveur.

Comment connecter Route 53 à API Gateway?

Ma Cloudformation telle qu'elle est maintenant est la suivante:

{
  "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"
    }
  }
}
Justin808
la source
4
Un nom de domaine personnalisé (nom d'hôte) n'est pas directement dirigé vers le point de terminaison API Gateway. Il s'agit de la distribution CloudFront sous-jacente, créée / détenue / contrôlée par API Gateway après la configuration d'API Gateway pour attendre / prendre en charge le nom de domaine personnalisé. C'est plus complexe que de simplement créer un enregistrement dans Route 53. Vous devrez consulter Utiliser le nom de domaine personnalisé comme nom d'hôte API API Gateway, sauf si vous êtes déjà familier avec ce processus.
Michael - sqlbot
2
Vous devrez également fournir un certificat SSL pour votre nom d'hôte personnalisé, ou en obtenir un auprès d'Amazon Certificate Manager, dans le cadre de la configuration, car API Gateway nécessite l'activation de HTTPS.
Michael - sqlbot

Réponses:

4

Vous devez créer un certificat SSL à l'aide du gestionnaire de certificats. Pour un point de terminaison de périphérie, créez-le dans eu-east-1, pour les points de terminaison régionaux et privés, créez-le dans la région dans laquelle vous déployez la passerelle API (ou lambda). Lisez plus ici . Je vais désigner l'ARN commeCertificateArn

Vous devez configurer un 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"
  }
}

Cela active le domaine pour la passerelle API. Ensuite, vous devez exposer l'API (c'est-à-dire votre RestAPI), dans une étape de déploiement spécifique . Dans votre modèle, vous n'avez aucune étape de déploiement. Jetez un oeil a AWS::ApiGateway::Stage. Un exemple minimal ressemblerait à ceci:

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

Cependant, vous voulez très probablement une configuration supplémentaire. Je vous suggère de jeter un œil à la MethodSettingspropriété.

Enfin, déployer une ressource de cartographie basePath: AWS::ApiGateway::BasePathMapping. Je vous suggère de mapper le chemin de base à l'étape que vous avez créée comme ceci:

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

Si vous modifiez une AWS::ApiGateway::Stageressource, vous devez forcer une mise à jour sur la AWS::ApiGateway::Deploymentressource correspondante - cela signifie généralement renommer la AWS::ApiGateway::Deploymentressource, pour garder cela à l'esprit. Sinon, il ne sera pas déployé.

Ça devrait le faire.

M. Glatki
la source