serverless create_domain - Failed to create custom domain - amazon-web-services

I am trying to use serverless-domain-manager to deploy serverless to custom domains on AWS but every time I run serverless create_domain I get the generic error "Failed to create custom domain". Here are the steps I've taken and the contents of my yml:
Registered domain on AWS
Set up a hosted zone in route 53
Created a certificate for *.mydomain.com in certificate manager in AWS
Created an iAM user with admin privileges
Run aws configure with iAM user keys
.yml
service: service-name
plugins:
- serverless-apigw-binary
- serverless-apigwy-binary
- serverless-content-encoding
- serverless-api-cloudfront
- serverless-plugin-tracing
- serverless-domain-manager
custom:
apigwBinary:
types:
- 'image/jpeg'
- 'text/html'
- 'text/css'
- 'application/javascript'
- 'application/x-javascript'
- '*/*'
contentEncoding:
minimumCompressionSize: 0
stage: ${opt:stage, self:provider.stage}
domains:
prod: api.mydomain.com
test: api-test.mydomain.com
dev: api-dev.mydomain.com
customDomain:
basePath: ""
domainName: ${self:custom.domains.${self:custom.stage}}
stage: "${self:custom.stage}"
createRoute53Record: true
certificateArn: "cert-arn"
hostedZoneId: "zone-id"
provider:
name: aws
runtime: nodejs12.x
endpointType: regional
region: ap-southeast-2
memorySize: 3008
timeout: 300
tracing: true
iamRoleStatements:
- Effect: 'Allow'
Action:
- 'xray:PutTraceSegments'
- 'xray:PutTelemetryRecords'
- 'lambda:InvokeFunction'
Resource:
- '*'
package:
exclude:
- node_modules/aws-sdk/**
- .vscode/**
- bin/**
- obj/**
functions:
api:
warmup: true
handler: index.handler
events:
- http: ANY /
- http: 'ANY {proxy+}'
Every time I run serverless create_domain I get the same generic error with no extra info.
Thanks

As Erico pointed out you get a bit more info with SLS_DEBUG. It could be that you have an issue with domain certificate and that debug message would tell you that.
In my case it seemed to be a cert problem as it was in a different AWS region so sls create_domain couldn't find it. Overall it's been a rather confusing experience.
Check out the endpointType option:
customDomain:
...
endpointType="regional"
https://github.com/amplify-education/serverless-domain-manager/issues/46
https://aws.amazon.com/about-aws/whats-new/2017/11/amazon-api-gateway-supports-regional-api-endpoints/

In my case, my hosted zone is in another AWS account, so createRoute53Record: true failed to create the route53 record and the hence the generic error.
Changing to createRoute53Record: false fixed the error for me.

Related

AWS Route 53 message forbidden while trying to add A record to cloud front

I am deploying a React.js application using the server less framework on cloudfront.
The architecture is very simple, I have an S3 bucket and a CloudFront CDN.
CloudFormation ends without any error setting up my configuration and I'm able to visit my react page using the CloudFront Distribution domain name using https and default certificate.
Now I bought a domain in Route 53 and I would like to link it to my CloudFront.
I tried everything but I did not succeed. Can anyone please give me some hint?
Action I already tried:
Adding the certificate's are (after creating it) on my resources.CloudFrontDistribution.ViewerCertificate.AcmCertificateArn
Adding manually an A record to point to my CloudFront. This generates the following JSON error on my browser: {"message":"Forbidden"}
Manually adding the certificate through AWS Console on my CloudFront
None of those action gave me any hint about how to solve or even debug the problem.
This is my current serverless.yml:
service: my-app-react
provider:
name: aws
runtime: nodejs12.x
region: eu-south-1
memorySize: 512
timeout: 6
logRetentionInDays: 7
plugins:
- serverless-s3-sync
custom:
bucketName: my-app-react-33333
s3Sync:
- bucketName: ${self:custom.bucketName}
localDir: build/
domains:
dev:
domainName: <my-domain>
certificateName: <my-domain>
resources:
Resources:
ReactAppBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.bucketName}
AccessControl: PublicRead
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: index.html
S3AccessPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: ReactAppBucket
PolicyDocument:
Statement:
- Sid: PublicReadGetObject
Effect: Allow
Principal: "*"
Action:
- s3:GetObject
Resource:
- arn:aws:s3:::${self:custom.bucketName}/*
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Origins:
- DomainName: ${self:custom.bucketName}.s3.eu-south-1.amazonaws.com
Id: ReactApp
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: https-only
DefaultRootObject: index.html
CustomErrorResponses:
- ErrorCode: 404
ResponseCode: 200
ResponsePagePath: /index.html
DefaultCacheBehavior:
AllowedMethods:
- HEAD
- GET
- DELETE
- OPTIONS
- PATCH
- POST
- PUT
TargetOriginId: ReactApp
ForwardedValues:
QueryString: false
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
ViewerCertificate:
AcmCertificateArn: <my-certificate-arn>
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2021
Oh, now I think I may know your issue. Cluodfront distributions can only use ACM certs created in us-east-1. See Requirements for using SSL/TLS certificates with CloudFront.
I didn't pick up on that before, but it is likely your issue. You don't have to have your distribution or any other resources there, just the certificates.
When I create certs using cloudformation, I set up the certificate handler templates in us-east-1 and the rest of the resource templates in my local region. With terraform, as another example, I have a separate provider just for these resources.

How can I deploy websocket with serverless framework

I have below configuration on serverless.yml. But it doesn't deploy websocket connection. I wonder what could be wrong with my configuration. I have followed this instruction: https://www.serverless.com/framework/docs/providers/aws/events/websocket/
service:
name: ${opt:componentName}-api
plugins:
- '#hewmen/serverless-plugin-typescript'
provider:
name: aws
runtime: nodejs12.x
region: ap-southeast-2
websocketsApiName: custom-websockets-api-name
websocketApiRouteSelectionExpression: $request.body.action
stackName: ${opt:stage}-${self:service.name}
iamRoleStatements:
- Effect: Allow
Action:
- logs:Create*
- logs:Get*
Resource: "*"
- Effect: Allow
Action:
- dynamodb:*
Resource: "*"
functions:
wsHandler:
handler: src/websocketLambda.handleWebSocket
name: ${self:provider.stackName}-ws
evnets:
- websocket: $default
The output of serverless deploy is:
Serverless: Stack update finished...
Service Information
service: device-api-transactions-api
stage: dev
region: ap-southeast-2
stack: dev-device-api-transactions-api
resources: 6
api keys:
None
endpoints:
None
functions:
wsHandler: dev-device-api-transactions-api-ws
layers:
None
Serverless: Removing old service artifacts from S3...
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.

Cannot fix The provided execution role does not have permissions to call CreateNetworkInterface on EC2

I am trying to deploy with VPC and this is my serverless.yaml
vpcSettings: &vpcSettings
vpc: ${self:custom.allVpcSettings.${self:provider.stage}.vpc}
provider:
name: aws
runtime: nodejs10.x
stage: ${opt:stage, 'local'}
region: us-west-1
memorySize: 256
timeout: 30
deploymentPrefix: fs-sls-${self:provider.stage}-deploy
deploymentBucket: fs-serverless-deployment
variables: ${file(.env.${opt:stage, self:provider.stage}.json)}
environment:
NODE_ENV: ${self:provider.variables.NODE_ENV}
functions:
ping:
handler: src/handler.ping
description: Let us know if the service is up and running
events:
- http:
path: ping
method: get
cors: true
graphql:
handler: src/handler.graphqlHandler
<<: *vpcSettings
description: One function where all GQL request comes
memorySize: 1024
events:
- http:
path: graphql
method: post
cors: true
- http:
path: graphql
method: get
cors: true
plugins:
- serverless-offline
custom:
serverless-offline:
port: 6000
allVpcSettings:
local:
vpc: 'This is a dummy value that should be ignored'
dev:
vpc:
securityGroupIds:
- sg-xxxxxxxxxxxxxxx
subnetIds:
- subnet-xxxxxxxxxxxxxxx
- subnet-xxxxxxxxxxxxxxx
prod:
vpc:
securityGroupIds:
- sg-xxxxxxxxxxxxxxx
subnetIds:
- subnet-xxxxxxxxxxxxxxx
- subnet-xxxxxxxxxxxxxxx
It fails with the following error
Serverless Error ---------------------------------------
The provided execution role does not have permissions to call CreateNetworkInterface on EC2
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com
Your Environment Information ---------------------------
Operating System: darwin
Node Version: 10.16.0
Framework Version: 1.52.0
Plugin Version: 2.0.0
SDK Version: 2.1.1
The user that I created for this purpose has AdministratorAccess as well as AWSLambdaVPCAccessExecutionRole in it's permissions. What else is expected here?
So I fixed it. It means the role of deploying lambda doesn't have permission. So it boils down to the fact to give it the role. First, confirm if you have the role.
Check in the image where to look for the role.
Once you don't find it. Which you most likely won't. Take the Role name and goto IAM -> Roles and Search for the role name and add AWSLambdaVPCAccessExecutionRole to the selected role.
This should give it the required permission.
Now try deploying the SLS and it should work.
Once you have the role, edit it by adding the
Although the user that you've created to deploy this lambda function has Administrator access, the lambda function itself needs networking permissions if you're deploying it into a VPC.
Try adding these permissions in the provider block of your serverless.yml template:
- Effect: Allow
Action:
- ec2:DescribeNetworkInterfaces
- ec2:CreateNetworkInterface
- ec2:DeleteNetworkInterface
- ec2:DescribeInstances
- ec2:AttachNetworkInterface
Resource:
- *
If that works, you'll want to deploy a more limited permission structure for your production environment.

Serverless custom domain

I want to setup a custom domain with the serverless framework and AWS.
This is what I have in serverless.yml
service: chapiLabs-rest-api
plugins:
- serverless-domain-manager
- serverless-express
custom:
customDomain:
domainName: chapitime.chapilabs.com
basePath: ''
stage: ${self:provider.stage}
certificateName: '*.chapilabs.com'
createRoute53Record: true
package:
exclude:
- node_modules
include:
- dist
provider:
name: aws
runtime: nodejs8.10
webpackIncludeModules:
forceInclude:
- mysql
- mysql2
- sequelize
functions:
get:
handler: dist/get.get
events:
- http:
path: v1/client/{id}
method: get
request:
parameters:
paths:
id: true
create:
handler: dist/auth.auth
events:
- http:
path: v1/auth
method: post
I used this npm package as plugin: https://github.com/amplify-education/serverless-domain-manager
I added a certificate via DNS using CloudFlare
Then I made a deploy and got the next log.
In cloudflare I added a CNAME to add the ACM validation and another CNAME pointing cloudfront.
But the domain name is not working. Any ideas why? I didn't bought the domain in AWS.
After some deployments the cloudfront url changed and I didn't noticed. I just updated the CNAME record in CloudFlare and it started working.

How to configure a Serverless S3 bucket resource to use a CORS AllowOrigin set to the http endpoint of its function

I'm using Serverless to create a web application that serves its static content, e.g. a web font, from a S3 bucket. The S3 bucket is configured as a resource in my serverless.yml file. Its CORS configuration has an AllowOrigin set to a wildcard.
I want to change this to have an AllowOrigin with the http endpoint of the service as created by Serverless, e.g. 31alib51b6.execute-api.eu-west-1.amazonaws.com.
I wondered if it's possible to configure this in the serverless.yml file itself.
My example serverless.yml file:
service: example-service
provider:
name: aws
runtime: nodejs4.3
region: eu-west-1
functions:
web:
handler: handler.handler
name: ${self:service}-${self:provider.stage}
description: ${self:service} web application - ${self:provider.stage}
events:
- http:
path: web
method: get
- http:
path: web/{proxy+}
method: get
resources:
Resources:
S3Assets:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:service}-${self:provider.stage}-assets
CorsConfiguration:
CorsRules:
- AllowedMethods:
- GET
- HEAD
AllowedOrigins:
- "*"
You can define the AllowedOrigin with the following statement:
CorsConfiguration:
CorsRules:
- AllowedMethods:
- GET
- HEAD
AllowedOrigins:
- Fn::Join:
- ""
- - "https://"
- Ref: ApiGatewayRestApi
- ".execute-api.eu-west-1.amazonaws.com"
"Ref: ApiGatewayRestApi" references the internal name of the generated API.