I'm working to create a notes application (api + website) on a single custom domain (ex : mysub.domain.com). I'd like the
- API Gateway for all my Lambdas to be accessible thru the path of /api/
- Have the rest of my paths for the domain serve up from an s3 static website
Currently,
- I have my lambda endpoint working at https://mysub.domain.com/api/notes (SSL is already working and in AWS console)
- via BasePathMapping (see yaml below)
- already added a CNAME record for my subdomain pointing to the Cloudfront endpoint that was created with
$ 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
When I add the following (s3 bucket and Cloudfront distribution) to the Resources section of my SAM YAML template
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]
I get the following error in $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].
How may use a single custom domain for my static website and api needs using the SAM template model?