上下文:要实现完整的“基础架构作为代码”,我想编写使用certbot
请求SSL证书的过程,使用DNS TXT
记录验证域,将证书上载到Amazon Certificate Manager(ACM),最后将证书ACM ARN附加到我的Cloudfront分发。这应该都是通过无服务器框架完成的。
我看到了两个可能的选项来实现这一目标。
选项1:使用异步javascript文件变量
即。在serverless.yml
我会定义如下条目:
custom:
domains:
prod: tommedema.tk
ssl:
prod:
dnsTxtRoot: ${{file(scripts/request-cert.js):cert.dnsTxtRoot}}
dnsTxtWww: ${{file(scripts/request-cert.js):cert.dnsTxtWww}}
certArn: ${{file(scripts/request-cert.js):cert.certArn}}
然后资源将使用这些变量:
- Type: TXT
Name: _acme-challenge.www.${{self:custom.domains.${{self:provider.stage}}, ''}}
TTL: '86400'
ResourceRecords:
- ${{self:custom.ssl.${{self:provider.stage}}.dnsTxtWww}}
scripts/request-cert.js
的样子:
module.exports.cert = () => {
console.log('running async logic')
// TODO: run certbot, get DNS records, upload to ACM
return Promise.resolve({
dnsTxtRoot: '"LnaKMkgqlIkXXXXXXXX-7PkKvqb_wqwVnC4q0"',
dnsTxtWww: '"c43VS-XXXXXXXXXWVBRPCXXcA"',
certArn: 'arn:aws:acm:us-east-1:XXXX95:certificate/XXXXXX'
})
}
此处的问题是,似乎无法将参数发送到request-cert.js
,或者此脚本需要了解serverless
或options
插件参数(因为它不是一个插件,但没有上下文的简单脚本)。这意味着脚本无法识别部署所针对的阶段和域等,因此缺少必要的变量来请求证书。
因此,选项1似乎是不可能的。
选项2:创建插件
当然我可以创建一个插件,它将包含所有必需的变量,因为它可以访问serverless
和options
个对象。现在的问题是我必须访问serverless.yml
内插件的输出,到目前为止我还没有看到如何做到这一点。即我希望能够做到这样的事情:
custom:
domains:
prod: tommedema.tk
ssl:
prod:
dnsTxtRoot: ${{myPlugin:cert.dnsTxtRoot}}
dnsTxtWww: ${{myPlugin:cert.dnsTxtWww}}
certArn: ${{myPlugin:cert.certArn}}
但这似乎不太可能。是吗?
如果这也是不可能的,我怎样才能以编程方式实现我的目的(即遵循基础设施作为代码原则)使用自定义SSL证书部署我的服务,而无需任何手动步骤?即。
答案 0 :(得分:1)
您可以在部署时执行此操作,但证书过期,因此最好将其作为重复出现的内容。
当我遇到这个问题时,我创建了一个Lambda来备份SSL证书并安装它。 (它需要很长的超时,但这没关系 - 它不需要经常运行)。它需要的密钥可以作为安全的环境变量给出。
然后我使用error: StatusCodeError: 400 -
设置每日触发器来检查证书是否应该刷新。该插件也可以配置为在部署时预热相关的lambdas,这允许我检查每次部署时过期或缺少的SSL证书。
也许你可以做类似的事情。
答案 1 :(得分:0)
使用Step Functions将是此特定用例的最佳选择。由于您有3个不同的步骤,它们将是三个独立的Lambda函数,Step Functions可以在它们之间传递输入/输出,包括等待时间和重试。