繁体   English   中英

如何使用 Cloud Formation 使用 ACM 证书预置 CloudFront 分配

[英]How to provision a CloudFront distribution with an ACM Certificate using Cloud Formation

我正在尝试使用 Cloud Formation 在我的 CloudFrontDistribution 中设置证书。

我的证书是通过证书管理器颁发的。 它已获得批准,并且我已通过 CloudFront 控制台直接通过手动配置验证该证书是否有效。

在我的 CloudFormation 模板中,我尝试在 IamCertificateId 属性中使用与证书关联的IdentifierARN值:

 "ViewerCertificate": { "IamCertificateId": "********", "SslSupportMethod": "sni-only" }

但在这两种情况下,我都会收到以下错误:

 The specified SSL certificate doesn't exist, isn't valid, or doesn't include a valid certificate chain.

阅读DistributionConfig 复杂类型的文档,看起来有一个“ACMCertificateArn”属性,但这似乎不适用于 CloudFormation。

任何帮助,将不胜感激。

(更新:截至2016年8月9日 ,AWS CloudFormation现在使用AcmCertificateArn属性支持ACM,因此不再需要下面描述的自定义资源。)


尽管尚未更新AWS :: CloudFront :: Distribution资源以支持ACMCertificateArn属性,但目前可以使用自定义CloudFormation资源直接使用AWS API实现所需功能,直到官方资源更新为止。

请参阅Ryan S. Brown的帖子, CloudFormation使用(免费)自定义SSL构建CDN ,其中描述了将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参考),因此您还需要添加它:

"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模板中,设置相应的SiteCDNAcmCertificate属性(或使用硬编码值编辑模板),并且您应该有自定义资源解决方法,直到Amazon更新官方CloudFront资源。

Cloudformation添加了此属性,但未记录。 您可以轻松使用:

"ViewerCertificate": {
            "SslSupportMethod": "sni-only",
            "AcmCertificateArn": "CERTIFICATE_ARN"
}

请注意,证书必须在us-east-1区域中创建,否则将不被接受。

我有一个正确创建的证书(公钥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/

我现在使用的另一种有效方法只是在没有颁发证书的情况下创建具有默认证书的堆栈(灵感来自此帖子

看起来像

"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"
},

重要的是要注意 cloudformation 模板的字段名称的大写。

AcmCertificateArn不是 ACMCertificateArn

IamCertificateId不是 IAMCertificateId

作为 cloudformation 的新手,我从使用不同 CamelCase 的 CLI 查询的 output 粘贴。 Cloudformation 会抱怨,但发现不同的情况对我来说并不是很明显。

花了几天时间,但在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"
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM