I am attempting to set a certificate in my CloudFrontDistribution using Cloud Formation.
My certificate has been issued via Certificate Manager. It has been approved, and I have validated that the certificate works by manual configuration directly through the CloudFront console.
Within my CloudFormation template, I have attempted to use both the Identifier and ARN values associated with the certificate in the IamCertificateId property:
"ViewerCertificate" : {
"IamCertificateId" : "********",
"SslSupportMethod": "sni-only"
}
But in both cases I receive the following error:
The specified SSL certificate doesn't exist, isn't valid, or doesn't include a valid certificate chain.
Reading the docs for the DistributionConfig Complex Type it looks like there is a 'ACMCertificateArn' property, but this does not seem to work via CloudFormation.
Any help would be appreciated.
ACM stands for AWS Certificate Manager. It provides the free SSL certificates which can be integrated with AWS development services such as ELB and cloudfront etc. Using the public certificates generated from ACM, You can secure your domain names and the sub-domains.
To create a CloudFront distributionOpen the CloudFront console at https://console.aws.amazon.com/cloudfront/v3/home . Choose Create Distribution, and then choose Get Started. Under Origin Settings, for Origin Domain Name, choose the Amazon S3 bucket that you created earlier.
CloudFront supports the same certificate authorities that Mozilla does. For the current list, see Mozilla Included CA Certificate List . You can't use a self-signed certificate for HTTPS communication between CloudFront and your origin.
The correct answer is option A (CloudFront cannot serve content from a non-AWS origin server).
Cloudformation added this property but it is not documented. You can use like this easily:
"ViewerCertificate": {
"SslSupportMethod": "sni-only",
"AcmCertificateArn": "CERTIFICATE_ARN"
}
Be aware that the certificate must be created in us-east-1 region, if not it won't be accepted.
(Update: As of Aug 9 2016, AWS CloudFormation now supports ACM using the AcmCertificateArn
property, so the custom resource described below is no longer needed.)
Although the AWS::CloudFront::Distribution resource hasn't been updated to support the ACMCertificateArn property yet, it is currently possible to use a custom CloudFormation resource to implement the functionality needed using the AWS API directly until the official resource is updated.
See Ryan S. Brown's post, CloudFormation To Build A CDN With (Free) Custom SSL where he describes his implementation of a Custom::CloudFrontAcmAssociation
resource that associates an ACM certificate with a CloudFront distribution. The code is available at ryansb/acm-certs-cloudformation
.
To use it, you need to make the CloudFormation resource's implementation available through an AWS Lambda function. Ryan's implementation is already published to a public S3 bucket, so you can reference this directly for testing purposes in your CloudFormation template like so:
"AcmAssociationFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "cloudfront_associator.handler",
"MemorySize": 128,
"Runtime": "python2.7",
"Code": {
"S3Bucket": "demos.serverlesscode.com",
"S3Key": "acm-certificate-resource-functions.zip"
},
"Role": {"Fn::GetAtt": ["ExecRole", "Arn"]},
"Timeout": 300
}
},
The Lambda::Function
resource has a dependency on an IAM service Role and associated Policy to delegate the necessary permissions to the lambda function (the ExecRole
reference above), so you need to add that too:
"ExecRolePolicies": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyName": "ExecRolePolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"acm:*",
"cloudfront:List*",
"cloudfront:Get*",
"cloudfront:UpdateDistribution"
],
"Resource": [ "*" ],
"Effect": "Allow"
},
{
"Action": [ "logs:*" ],
"Resource": "arn:aws:logs:*:*:*",
"Effect": "Allow"
}
]
},
"Roles": [{"Ref": "ExecRole"}]
}
},
"ExecRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": ["sts:AssumeRole"],
"Effect": "Allow",
"Principal": {"Service": ["lambda.amazonaws.com"]}
}
]
}
}
},
With the lambda function in place, finally add the Custom::CloudFrontAcmAssociation
resource, providing the distribution ID, certificate ARN, and the custom resource lambda function's ARN:
"DistributionCertificateSetting": {
"Type": "Custom::CloudFrontAcmAssociation",
"Properties": {
"DistributionId": {
"Ref": "SiteCDN"
},
"CertificateArn": {
"Ref": "AcmCertificate"
},
"ServiceToken": {
"Fn::GetAtt": [
"AcmAssociationFunction",
"Arn"
]
}
}
},
tldr: copy all the code above into your CloudFormation template, set the appropriate SiteCDN
and AcmCertificate
properties (or edit the template with hard-coded values), and you should have a custom resource workaround until Amazon updates the official CloudFront resource.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With