SAM 使用单个自定义域名将 s3 网站添加到 API 网关 + Lambda

SAM Adding s3 website to API Gateway + Lambda with single custom domain name

我正在努力在单个自定义域(例如:mysub.domain.com)上创建笔记应用程序(api + 网站)。我想要

目前,

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].

我的静态网站如何使用单个自定义域并且 api 需要使用 SAM 模板模型?

你会:

  • 设置具有两个来源的 CloudFront,S3 和 API 网关。
  • 使用 API 网关代理您的 s3 端点