我正在尝试使用Cloud Formation在我的CloudFrontDistribution中设置证书。
我的证书已通过证书管理器发出。它已被批准,我已经验证证书可以通过CloudFront控制台直接手动配置。
在我的CloudFormation模板中,我尝试在IamCertificateId属性中使用与证书关联的 Identifier 和 ARN 值:
"ViewerCertificate" : {
"IamCertificateId" : "********",
"SslSupportMethod": "sni-only"
}
但是在这两种情况下我都收到以下错误:
The specified SSL certificate doesn't exist, isn't valid, or doesn't include a valid certificate chain.
阅读DistributionConfig Complex Type的文档,看起来有一个'ACMCertificateArn'属性,但这似乎不适用于CloudFormation。
任何帮助都将不胜感激。
答案 0 :(得分:14)
(更新:自Aug 9 2016起,AWS CloudFormation现在使用AcmCertificateArn
属性支持ACM,因此不再需要下面描述的自定义资源。)
虽然AWS :: CloudFront :: Distribution资源尚未更新以支持ACMCertificateArn属性,但目前可以使用custom CloudFormation resource直接使用AWS API实现所需的功能。资源已更新。
请参阅Ryan S. Brown的帖子CloudFormation To Build A CDN With (Free) Custom SSL,其中描述了他将ACM证书与CloudFront分配相关联的Custom::CloudFrontAcmAssociation
资源的实现。该代码位于ryansb/acm-certs-cloudformation
。
要使用它,您需要通过AWS Lambda函数提供CloudFormation资源的实现。 Ryan的实现已发布到公共S3存储桶,因此您可以在CloudFormation模板中直接引用它以进行测试,如下所示:
"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
}
},
Lambda::Function
资源依赖于IAM服务角色和相关策略来委派必需的权限到lambda函数(上面的ExecRole
引用),所以你也需要添加它: / p>
"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"]}
}
]
}
}
},
使用lambda函数,最后添加Custom::CloudFrontAcmAssociation
资源,提供分发ID,证书ARN和自定义资源lambda函数的ARN:
"DistributionCertificateSetting": {
"Type": "Custom::CloudFrontAcmAssociation",
"Properties": {
"DistributionId": {
"Ref": "SiteCDN"
},
"CertificateArn": {
"Ref": "AcmCertificate"
},
"ServiceToken": {
"Fn::GetAtt": [
"AcmAssociationFunction",
"Arn"
]
}
}
},
tldr:将上面的所有代码复制到您的CloudFormation模板中,设置相应的SiteCDN
和AcmCertificate
属性(或使用硬编码值编辑模板),您应该有自定义资源解决方法直到亚马逊更新官方CloudFront资源。
答案 1 :(得分:9)
Cloudformation添加了此属性,但未记录。您可以轻松使用:
"ViewerCertificate": {
"SslSupportMethod": "sni-only",
"AcmCertificateArn": "CERTIFICATE_ARN"
}
请注意,证书必须在us-east-1区域创建,否则将不被接受。
答案 2 :(得分:2)
我有一个正确创建的证书(公钥2048位),上传了完整链。更具挑战性的是在其他AWS服务(公共ELB)中使用证书时没有问题。
我也正确地传递了证书ID(我也尝试过使用ARN,但这不正确)。
在我的情况下,问题是证书是用"路径":" /"创建的。在我使用" Path":" / cloudfront /"上传新证书(使用不同的名称)之后,一切都正常运行。
aws iam upload-server-certificate \
--server-certificate-name cert_cf \
--certificate-body file://cert.crt \
--private-key file://cert.key \
--certificate-chain file://chain.pem \
--path /cloudfront/
答案 3 :(得分:0)
我现在使用的另一种有效方法是,只要不颁发证书,就使用默认证书创建堆栈(受this post启发)
看起来像
"Conditions": {
"HasAcmCertificate": {
"Fn::Equals": [
{
"Ref": "CloudfrontCertificateArn"
},
"NOT_ISSUED"
]
}
},
...
"Cloudfront": {
"Properties": {
"DistributionConfig": {
...
"ViewerCertificate": {
"AcmCertificateArn": {
"Fn::If": [
"HasAcmCertificate",
{
"Ref": "AWS::NoValue"
},
{
"Ref": "CloudfrontCertificateArn"
}
]
},
"CloudFrontDefaultCertificate": {
"Fn::If": [
"HasAcmCertificate",
true,
{
"Ref": "AWS::NoValue"
}
]
},
"SslSupportMethod": {
"Fn::If": [
"HasAcmCertificate",
{
"Ref": "AWS::NoValue"
},
"sni-only"
]
}
}
}
},
"Type": "AWS::CloudFront::Distribution"
},
答案 4 :(得分:-2)
花了几天时间,但在AWS支持的帮助下找到答案。
以下信息:
"ViewerCertificate" : {
"IamCertificateId" : "********",
"SslSupportMethod": "sni-only"
}
使用CLI" aws iam list-server-certificates":
{
"ServerCertificateId": "ASCAXXXXXXXXXXXXXX",
"ServerCertificateName": "devops.XXXXXXX.com",
"Expiration": "2017-03-10T15:00:33Z",
"Path": "/cloudfront/",
"Arn": "arn:aws:iam::XXXXXXXXXXX:server-certificate/cloudfront/devops.XXXXXXXXXXX.com",
"UploadDate": "2016-03-14T16:13:59Z"
},
一旦我发现我添加了一个带有ServerCertificateId的变量cloudfront.CloudFrontCertificateId并将其输入ViewerCertificate:
"ViewerCertificate" : {
"IamCertificateId" : {{ cloudfront.CloudFrontCertificateId }},
"SslSupportMethod": "sni-only"
}