SAM Добавление сайта s3 к API Gateway + Lambda с одним настраиваемым доменным именем - PullRequest
0 голосов
/ 06 февраля 2020

Я работаю над созданием приложения для заметок (api + веб-сайт) на одном пользовательском домене (например: mysub.domain.com). Я бы хотел, чтобы

  • API-шлюз для всех моих Lambdas был доступен через путь / api /
  • Остальные мои пути для домен обслуживает веб-сайт s3 stati c

В настоящее время

  • Моя конечная точка лямбды работает на https://mysub.domain.com/api/notes (SSL уже работает и в консоли AWS)
  • через BasePathMapping (см. Yaml ниже)
  • уже добавил запись CNAME для моего субдомена, указывающую на конечная точка Cloudfront, созданная с помощью $ sam deploy
Parameters:
  DomainName:
    Type: String
    Default: mysub.nydomain.com

Resources:

  #######  DOMAIN - START ######
  AppDomainName:
    Type: AWS::ApiGateway::DomainName
    Properties:
      CertificateArn: arn:aws:acm:us-east-1:123456789012:certificate/1b23c456-7890-1b2b-a345-a6bb4a7fa89c
      DomainName: !Ref DomainName

  APIBasePathMapping:
    Type: AWS::ApiGateway::BasePathMapping
    Properties:
      BasePath: 'api'
      DomainName: !Ref AppDomainName
      RestApiId: !Ref ServerlessRestApi
      Stage: !Ref ServerlessRestApiProdStage

  #######  LAMBDA - START ######
  NotesFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: notes/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref NotesTable
      Events:
        Notes:
          Type: Api
          Properties:
            Path: /notes
            Method: post
  #######  TABLES - START ######
  NotesTable:
    Type: AWS::DynamoDB::Table
    Properties:
      ...
Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  NotesApi:
    Description: "API Gateway endpoint URL for Prod stage for Notes function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/bt-device-history/"
  NotesFunction:
    Description: "Hello World Lambda Function ARN"
    Value: "DeviceHistoryFunction"
  NotesFunctionIamRole:
    Description: "Implicit IAM Role created for NotesFunction"
    Value: !GetAtt NotesFunctionRole.Arn

Когда я добавляю следующее (корзина s3 и распределение Cloudfront) в раздел Ресурсы моего шаблона SAM YAML

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:
      - Sid: PublicReadForGetBucketObjects
        Effect: Allow
        Principal: '*'
        Action: s3:GetObject
        Resource: !Join ['', ['arn:aws:s3:::', !Ref 'WebsiteBucket', /*]]
WebsiteCloudfront:
Type: AWS::CloudFront::Distribution
DependsOn:
  - WebsiteBucket
Properties:
  DistributionConfig:
    Comment: Cloudfront Distribution pointing to S3 bucket
    Origins:
      - DomainName: !Select [2, !Split ["/", !GetAtt WebsiteBucket.WebsiteURL]]
        Id: S3Origin
        CustomOriginConfig:
          HTTPPort: '80'
          HTTPSPort: '443'
          OriginProtocolPolicy: http-only
    Enabled: true
    HttpVersion: 'http2'
    DefaultRootObject: index.html
    Aliases:
      - !Ref 'DomainName'
    DefaultCacheBehavior:
      AllowedMethods:
        - GET
        - HEAD
      Compress: true
      TargetOriginId: S3Origin
      ForwardedValues:
        QueryString: true
        Cookies:
          Forward: none
      ViewerProtocolPolicy: redirect-to-https
    PriceClass: PriceClass_All
    ViewerCertificate:
      AcmCertificateArn: arn:aws:acm:us-east-1:123456789012:certificate/1bf2c345--6789-0b1b-a123-a4bb5a6fa44c
      SslSupportMethod: sni-only
WebsiteDNSName:
Type: AWS::Route53::RecordSetGroup
Properties:
  HostedZoneName: !Join ['', [!Ref 'DomainName', .]]
  RecordSets:
    - Name: !Ref 'DomainName'
      Type: A
      AliasTarget:
        HostedZoneId: Z2FDTNDATAQYW2
        DNSName: !GetAtt [WebsiteCloudfront, DomainName]

Я получаю следующую ошибку в $sam deploy

AWS::CloudFront::Distribution   WebsiteCloudfront      One or more of the CNAMEs you provided are already associated with a
                                                       different resource. (Service: AmazonCloudFront; Status Code: 409; Error
                                                       Code: CNAMEAlreadyExists; Request ID:
                                                       e044dd29-4550-4f86-be44-22bbf7c34b16)
AWS::CloudFormation::Stack      note-app                The following resource(s) failed to create: [WebsiteCloudfront].

Как можно использовать один пользовательский домен для моего веб-сайта stati c и API, используя модель шаблона SAM?

1 Ответ

1 голос
/ 06 февраля 2020

Вы хотели бы:

  • Настроить CloudFront с двумя источниками, S3 и шлюзом API.
  • Использовать шлюз API для прокси вашей конечной точки s3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...