I wanted to deploy a static website using cloudformation but I am having issues creating the record set. The stack creation was successful until the hosted zone in resource section. I'm not sure why there is an issue creating the record set for a hosted zone.
Error: The following resource(s) failed to create: [RecordSet].
---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Assuming that you already have a Hosted Zone registered with Amazon Route 53, this Cfn template is to create a static site'
# Metadata:
# 'AWS::CloudFormation::Interface':
# ParameterGroups:
# - Label:
# default: 'HostedZone name'
# Parameters:
# - HostedZoneName
Parameters:
HostedZoneName:
Description: "The DNS name of an existing Amazon Route 53 hosted zone"
Type: String
AllowedPattern: "(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)"
Default: "thecloudcrew.net"
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
BucketName: !Ref HostedZoneName
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: error.html
LoggingConfiguration:
DestinationBucketName: !Ref S3LoggingBucket
LogFilePrefix: logs
WWWS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub
- www.${domain}
- { domain: !Ref HostedZoneName}
WebsiteConfiguration:
RedirectAllRequestsTo:
HostName: !Ref HostedZoneName
S3LoggingBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub
- ${domain}.logs
- { domain: !Ref HostedZoneName}
AccessControl: LogDeliveryWrite
HostedZone:
Type: "AWS::Route53::HostedZone"
Properties:
HostedZoneConfig:
Comment: "My Hosted zone for thecloudcrew.net"
HostedZoneTags:
-
Key: Name
Value: thecloudcrew
Name: !Ref HostedZoneName
RecordSet: #FIXME
Type: "AWS::Route53::RecordSet"
Properties:
AliasTarget:
DNSName: s3-website.us-east-2.amazonaws.com
HostedZoneId: Z2O1EMRO9K5GLX
Comment: "RecordSet for static website"
HostedZoneId: !Ref HostedZone #TODO
Name: !Ref HostedZone
Type: A
#Region: 'us-east-2'
# SetIdentifier: String
# TTL: String
# Weight: Integer
You're missing the Type: A property, you have to replace HosteZoneName by HostedZoneId. Also, remove Region it has no use in Route53 which is global.
Related
I have created a hosted zone resource via cloudformation. Now i want to create an api gateway via same template in two regions, say us-east-1 and us-west-1 .
customDomain:
Type: AWS::Route53::HostedZone
Properties:
Name: 'example.com'
I understand , i will have to create ssl certificate in both regions. so i have created another stack below. but how do i link , my example.com to api gateway on both the regions.
the error i'm getting now , if i deploy the stack below to second region is - create failed for Mycustomdomainconfig => "The domain name you provided already exists. (service: ApiGateway, ...Status Code 400...
Resources:
MyCertificate:
Type: "AWS::CertificateManager::Certificate"
Properties:
DomainName: example.com
ValidationMethod: DNS
DomainValidationOptions:
- DomainName: 'example.com'
HostedZoneId: 'abcde'
Myrecord:
Type: AWS::Route53::RecordSet
Properties:
Region: !Ref aws_region
SetIdentifier: !Sub "endpoint-${aws_region}"
HostedZoneId: 'abcde'
Name: 'example.com'
Type: A
AliasTarget:
DNSname: !GetAtt Mycustomdomainconfig.RegionalDomainName
HostedZoneId: !GetAtt Mycustomdomainconfig.RegionalHostedZoneId
Mycustomdomainconfig:
Type: AWS::ApiGateway::DomainName
Properties:
RegionalCertificationArn: !Ref MyCertificate
DomainName: 'example.com'
...
MyApiMapping:
Type: AWS::ApiGateway::BasePathMapping
Properties:
DomainName: !Ref Mycustomdomainconfig
RestApiId: !Ref MyApi
...
MyApi:
Type: AWS::Serverless::Api
Properties:
....
ORIGINAL QUESTIONS: How to get RegionalDomainName out of a AWS APIGateway DomainName in SAM Cloud-formation
EDIT: I changed the question to hopefully get more traffic to this answer as it answers several questions not just my original one.
I am getting the following error when I try and deploy my stack:
resource DomainName does not support attribute type regionalDomainName in Fn::GetAtt
My yml file looks like the following:
PublicApi:
Type: AWS::Serverless::Api
Properties:
Name: PublicApi
...
EndpointConfiguration: REGIONAL
DomainName:
Type: AWS::ApiGateway::DomainName
Properties:
RegionalCertificateArn: "arn:aws:acm:${Region}:XXXXXXXXXXX:certificate/XXXXXXXXXXXXX"
DomainName: !Sub ${Stage}.${name}
EndpointConfiguration:
Types:
- REGIONAL
myDNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId : Z1UJRXOUMOOFQ8
Name: !Sub ${Stage}.${name}
AliasTarget:
HostedZoneId: Z1UJRXOUMOOFQ8
DNSName: !GetAtt DomainName.regionalDomainName
Type: A
UrlMapping:
Type: AWS::ApiGateway::BasePathMapping
DependsOn:
- PublicApi
Properties:
DomainName: !Ref DomainName
RestApiId: !Ref PublicApi
Stage: !Ref Stage
The following is from the DomainName documentation:
"RegionalDomainName
The domain name associated with the regional endpoint for this custom domain name. You set up this association by adding a DNS record that points the custom domain name to this regional domain name."
I am confused as to what I need to do to make this DomainName Regional.
I have also been getting the following Errors in different iterations, that I thought this should fix:
"Cannot import certificates for EDGE while REGIONAL is active."
Any help on this front would be much appreciated!
I found from several different forums different solutions to different problems and finally came up with a working model. I hope this helps someone out in the future.
PublicApi:
Type: AWS::Serverless::Api
Properties:
Name: PublicApi
StageName: ApiStage
...
EndpointConfiguration: REGIONAL
DomainName:
Type: AWS::ApiGateway::DomainName
Properties:
RegionalCertificateArn: "arn:aws:acm:u${Region}:XXXXXXXX:certificate/XXXXXXXX"
DomainName: stage.example.com
SecurityPolicy: TLS_1_2
EndpointConfiguration:
Types:
- REGIONAL
LambdaDNS:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneName:
Ref: example.com.
RecordSets:
- Name:
Fn::Sub: stage.example.com.
Type: A
AliasTarget:
HostedZoneId: Z1UJRXOUMOOFQ8
DNSName:
Fn::GetAtt:
- DomainName
- RegionalDomainName
UrlMapping:
Type: AWS::ApiGateway::BasePathMapping
DependsOn:
- PublicApi
- PublicApiStage
Properties:
DomainName:
Ref: DomainName
RestApiId:
Ref: PublicApi
Stage: ApiStage
The key bit for me ended up being the DependsOn in the BasePathMapping.
The following code is my attempt at creating a SPA (Single Page Application) CloudFormation template. I understand there are probably many flaws but I can't conceptually understand how to break the circular dependency error I am getting. In my head, it only makes sense that Route53 depends on CloudFront because it needs to know the AliasTarget, it also makes sense that CloudFront needs to depend on Certificate Manager because it needs AcmCertificateArn and CertificateManager needs to depend on Route53 (for obvious reasons but I have a feeling someone is going to tell me this is where I break the chain).
AWSTemplateFormatVersion: '2010-09-09'
Description: Creates an S3 bucket configured for hosting a static website, and a Route
53 DNS record pointing to the bucket
Parameters:
DomainName:
Type: String
Description: The DNS name of an existing Amazon Route 53 hosted zone e.g. jevsejev.io
AllowedPattern: (?!-)[a-zA-Z0-9-.]{1,63}(?<!-)
ConstraintDescription: must be a valid DNS zone name.
FullDomainName:
Type: String
Description: The full domain name e.g. development.jevsejev.io
AllowedPattern: (?!-)[a-zA-Z0-9-.]{1,63}(?<!-)
ConstraintDescription: must be a valid DNS zone name.
Resources:
Route53:
Type: AWS::Route53::RecordSet
DependsOn:
- Cloudfront
Properties:
HostedZoneName: !Ref 'DomainName'
RecordSets:
Name: !Ref 'FullDomainName'
Type: A
AliasTarget:
DNSName: !GetAtt [Cloudfront, WebsiteURL]
CertificateManager:
Type: AWS::CertificateManager::Certificate
DependsOn:
- Route53
Properties:
DomainName: !Ref 'FullDomainName'
Cloudfront:
Type: AWS::CloudFront::Distribution
DependsOn:
- S3
Properties:
DistributionConfig:
Origins:
- DomainName: !GetAtt [S3, WebsiteURL]
Id: S3Origin
CustomOriginConfig:
HTTPPort: '80'
HTTPSPort: '443'
OriginProtocolPolicy: http-only
Enabled: true
HttpVersion: 'http2'
DefaultRootObject: index.html
Aliases:
- !Ref 'FullDomainName'
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
Compress: true
TargetOriginId: S3Origin
ForwardedValues:
QueryString: true
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
PriceClass: PriceClass_All
ViewerCertificate:
AcmCertificateArn: !Ref CertificateManager
SslSupportMethod: sni-only
S3:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref 'FullDomainName'
AccessControl: PublicRead
WebsiteConfiguration:
IndexDocument: index.html
I also have this problem and just get fixed.
Hope this it's helpful for people
The Certificate part once you have this property DomainValidationOptions and use your own HostedZone Id as Value of HostedZoneId, Certificate will get created without hanging there.
Below are my code for reference:
CldoudFrontHostedZoneId is a fixed value from AWS documents
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html
DefaultHostedZoneId is my HostedZone Id
Parameters:
DefaultHostedZoneId:
Description: Default own HostedZone Id
Type: String
Default: xxxxxxxxxxxxxx
CldoudFrontHostedZoneId:
Description: AWS only use this hosted zone Id for cloudfront
Type: String
Default: Z2FDTNDATAQYW2
Resources:
StagingCloudFrontCertificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: yyyyy.xxxxxxxx.company.com
ValidationMethod: DNS
DomainValidationOptions:
- DomainName: yyyyy.xxxxxxxx.company.com
HostedZoneId: !Ref DefaultHostedZoneId
StagingCloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName: !GetAtt StagingPublishedS3.DomainName
Id: !Ref StagingPublishedS3
S3OriginConfig:
OriginAccessIdentity: !Join ['', ['origin-access-identity/cloudfront/', !Ref StagingCloudFrontOriginAccessIdentity]]
Enabled: 'true'
Comment: Staging CloudFront Distribution
HttpVersion: http2
IPV6Enabled: true
PriceClass: PriceClass_100
Aliases:
- yyyyy.xxxxxxxx.company.com
ViewerCertificate:
MinimumProtocolVersion: TLSv1.2_2021
AcmCertificateArn: !Ref StagingCloudFrontCertificate
SslSupportMethod: sni-only
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
- OPTIONS
CachePolicyId: !Ref AWSmanagedCachePolicy
# ForwardedValues:
# QueryString: false
ViewerProtocolPolicy: 'redirect-to-https'
TargetOriginId: !Ref StagingPublishedS3
TrustedKeyGroups:
- !Ref StagingCloudFrontKeyGroup
CacheBehaviors:
- AllowedMethods:
- GET
- HEAD
PathPattern: /favicon.ico
TargetOriginId: !Ref StagingPublishedS3
ViewerProtocolPolicy: 'redirect-to-https'
CachePolicyId: !Ref AWSmanagedCachePolicy
StagingCloudfrontDNS:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneName: xxxxxxxx.company.com.
Comment: Zone apex alias targeted to CloudFront
RecordSets:
- Name: yyyyy.xxxxxxxx.company.com.
Type: A
AliasTarget:
HostedZoneId: !Ref CldoudFrontHostedZoneId
DNSName: !GetAtt StagingCloudFrontDistribution.DomainName
- Name: yyyyy.xxxxxxxx.company.com.
Type: AAAA
AliasTarget:
HostedZoneId: !Ref CldoudFrontHostedZoneId
DNSName: !GetAtt StagingCloudFrontDistribution.DomainName
When I do a create stack with the following cloudformation template using the input parameter EnvironmentType "dev", it creates the ebs application, creates the environment inside the application and deploys the sample-app.war file from the S3 bucket.
Then I am doing an update stack using the same template with an input parameter EnvironmentType "stage", this time it removes the existing dev environment and creates the stage environment inside the application.
I also tried to create stack again using the sample template entering sample application name created in the first step and this time it shows application already exist.
My requirement is to retain the dev environment and stage environment to get created inside the sample application using cloudformation.
Any suggestions, please..
---
AWSTemplateFormatVersion: 2010-09-09
Description: 'Create an ElasticBeanstalk Application, Environment and deploy the war file from S3 bucket'
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
-
Label:
default: 'EBS Application Configuration'
Parameters:
- ApplicationName
- ApplicationDescription
- ApplicationVersion
-
Label:
default: 'EBS Environment Configuration'
Parameters:
- EnvironmentName
- EnvironmentType
- EnvironmentDescription
- EnvironmentCName
- MinInstances
- MaxInstances
Mappings:
PropertiesMap:
IntanceType:
dev: 'SingleInstance'
qa: 'SingleInstance'
stage: 'LoadBalanced'
prod: 'LoadBalanced'
Parameters:
ApplicationName:
Type: String
Description: 'Name of the ElasticBeanstalk Application'
ApplicationDescription:
Type: String
Description: 'ElasticBeanstalk Application Description'
ApplicationVersion:
Type: String
Description: 'Application version description'
EnvironmentName:
Type: String
Description: 'Name of the Environment'
AllowedPattern: '^([A-Za-z]|[0-9]|-)+$'
EnvironmentType:
Type: String
Description: 'Type of the Environment (dev, qa, stage, prod)'
AllowedValues:
- 'dev'
- 'qa'
- 'stage'
- 'prod'
EnvironmentCName:
Type: String
Description: 'CName Prefix for the ElasticBeanstalk environment'
AllowedPattern: '^([A-Za-z]|[0-9]|-)+$'
EnvironmentDescription:
Type: String
Description: 'Description of the ElasticBeanstalk environment'
MinInstances:
Type: Number
Description: 'Minimum load balanced instances (Mandatory for stage/prod)'
Default: 2
MinValue: 2
MaxValue: 10
MaxInstances:
Type: Number
Description: 'Maximum load balanced instances (Mandatory for stage/prod)'
Default: 2
MinValue: 2
MaxValue: 10
Conditions:
IsStageOrProdEnvironment:
!Or [!Equals [stage, !Ref EnvironmentType], !Equals [prod, !Ref EnvironmentType]]
Resources:
EBSApplication:
Type: AWS::ElasticBeanstalk::Application
Properties:
ApplicationName: !Ref ApplicationName
Description: !Ref ApplicationDescription
EBSApplicationVersion:
Type: AWS::ElasticBeanstalk::ApplicationVersion
Properties:
ApplicationName: !Ref EBSApplication
Description: !Ref ApplicationVersion
SourceBundle:
S3Bucket: deployable
S3Key: artifacts/sample-app.war
EBSApplicationConfigurationTemplate:
Type: AWS::ElasticBeanstalk::ConfigurationTemplate
Properties:
ApplicationName: !Ref EBSApplication
Description: 'ElasticBeanstalk Configuration Template'
SolutionStackName: '64bit Amazon Linux 2018.03 v3.0.2 running Tomcat 8.5 Java 8'
OptionSettings:
- Namespace: aws:elasticbeanstalk:environment
OptionName: EnvironmentType
Value: !FindInMap [PropertiesMap, IntanceType, !Ref EnvironmentType]
- Namespace: aws:autoscaling:asg
OptionName: MinSize
Value: !If [IsStageOrProdEnvironment, !Ref MinInstances, !Ref 'AWS::NoValue']
- Namespace: aws:autoscaling:asg
OptionName: MaxSize
Value: !If [IsStageOrProdEnvironment, !Ref MaxInstances, !Ref 'AWS::NoValue']
EBSEnvironment:
Type: AWS::ElasticBeanstalk::Environment
Properties:
ApplicationName: !Ref EBSApplication
CNAMEPrefix: !Ref EnvironmentCName
Description: !Ref EnvironmentDescription
EnvironmentName: !Ref EnvironmentName
TemplateName: !Ref EBSApplicationConfigurationTemplate
VersionLabel: !Ref EBSApplicationVersion
Outputs:
ApplicationURL:
Description: 'ElasticBeanstalk environment endpoint'
Value: !Join
- ''
- - 'http://'
- !GetAtt EBSEnvironment.EndpointURL
I have the following Cloudformation config, it does the following:
Creates and Elasticbeanstalk app
Links a domain name to its loadbalancer
I need to be able to access an FTP server but they only allow whitelisted IP addresses.
How would I go about creating a static (elastic?) IP within configuration, route traffic through it, and have the IP remain the same if I run this Cloudformation multiple times?
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
S3Bucket:
Type: String
Description: S3 Bucket containing zip file
RolePath:
Type: String
Description: RolePath
HostedZoneName:
Type: String
Description: HostedZoneName
QueueNamePrefix:
Type: String
Description: QueueNamePrefix
AppDebug:
Type: String
Description: Debug
Default: 'false'
AppDnsCname:
Type: String
Description: AppDnsCname
Environment:
Type: String
Description: Environment
AppName:
Type: String
Description: AppName
AWSRegion:
Type: String
Description: AWSRegion
AppHealthCheckPath:
Type: String
Description: Path for container health check
Description: Elastic Beanstalk application & IAM policies
Resources:
ElasticBeanstalkProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: !Ref 'RolePath'
Roles:
- !Ref 'ElasticBeanstalkRole'
ElasticBeanstalkRole:
Type: AWS::IAM::Role
Properties:
Path: !Ref 'RolePath'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess
- arn:aws:iam::aws:policy/AmazonEC2ContainerServiceFullAccess
- arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker
- arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier
- arn:aws:iam::aws:policy/AmazonSQSFullAccess
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Policies: []
ElasticBeanstalkApplication:
Type: AWS::ElasticBeanstalk::Application
Properties:
Description: !Ref 'AppName'
ElasticBeanstalkVersion:
Type: AWS::ElasticBeanstalk::ApplicationVersion
Properties:
ApplicationName: !Ref 'ElasticBeanstalkApplication'
Description: Source Code
SourceBundle:
S3Bucket: !Ref 'S3Bucket'
S3Key: !Ref 'S3ZipKey'
ElasticBeanstalkConfigurationTemplate:
Type: AWS::ElasticBeanstalk::ConfigurationTemplate
DependsOn:
- ElasticBeanstalkProfile
Properties:
Description: my-app Configuration Template
ApplicationName: !Ref 'ElasticBeanstalkApplication'
SolutionStackName: 64bit Amazon Linux 2017.09 v2.8.4 running Multi-container Docker 17.09.1-ce (Generic)
OptionSettings:
- Namespace: aws:elasticbeanstalk:environment
OptionName: EnvironmentType
Value: LoadBalanced
- Namespace: aws:elasticbeanstalk:application
OptionName: Application Healthcheck URL
Value: !Ref 'AppHealthCheckPath'
- Namespace: aws:elasticbeanstalk:cloudwatch:logs
OptionName: StreamLogs
Value: true
- Namespace: aws:elasticbeanstalk:cloudwatch:logs
OptionName: DeleteOnTerminate
Value: false
- Namespace: aws:elasticbeanstalk:cloudwatch:logs
OptionName: RetentionInDays
Value: 180
- Namespace: aws:autoscaling:launchconfiguration
OptionName: IamInstanceProfile
Value: !GetAtt 'ElasticBeanstalkProfile.Arn'
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DEBUG
Value: !Ref 'AppDebug'
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: AWS_REGION
Value: !Ref 'AWSRegion'
- Namespace: aws:elasticbeanstalk:application:environment
- Namespace: aws:autoscaling:launchconfiguration
OptionName: InstanceType
Value: "t2.small"
- Namespace: aws:elasticbeanstalk:healthreporting:system
OptionName: SystemType
Value: "enhanced"
MyAppDNS:
Type: AWS::Route53::RecordSetGroup
DependsOn: ElasticBeanstalkEnvironment
Properties:
HostedZoneName: !Ref 'HostedZoneName'
RecordSets:
- Name: !Ref 'AppDnsCname'
Type: CNAME
TTL: '60'
ResourceRecords:
- !GetAtt 'ElasticBeanstalkEnvironment.EndpointURL'
ElasticBeanstalkEnvironment:
Type: AWS::ElasticBeanstalk::Environment
Properties:
Description: !Ref 'Environment'
ApplicationName: !Ref 'ElasticBeanstalkApplication'
TemplateName: !Ref 'ElasticBeanstalkConfigurationTemplate'
VersionLabel: !Ref 'ElasticBeanstalkVersion'
Tier:
Type: Standard
Name: WebServer
Use Elastic IP resource association through CloudFormation.
Create the Elastic IP resource:
Type: AWS::EC2::EIP
Properties:
InstanceId: String
Domain: String
Associate the Elastic IP resource with your EC2 instance resource:
Type: AWS::EC2::EIPAssociation
Properties:
AllocationId: String
EIP: String
InstanceId: String
NetworkInterfaceId: String
PrivateIpAddress: String
Don't forget to join these two using !Ref
and finally, here's an official example on how to do this.
Assigning an Amazon EC2 Elastic IP Using AWS::EC2::EIP Snippet