如何访问serverless Framework的serverless.yml中的插件输出



Context:为了实现完整的"基础设施即代码",我想编码使用certbot请求SSL证书、使用DNSTXT记录验证域、将证书上传到亚马逊证书管理器(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发送参数,也不可能让这个脚本知道serverlessoptions插件参数(因为它不是一个插件,而是一个没有上下文的简单脚本)。这意味着脚本无法知道部署所针对的阶段和域等,因此它缺少请求证书所需的变量。

因此,选项1似乎是不可能的。

选项2:创建一个插件

当然,我可以创建一个插件,它将具有所有必需的变量,因为它可以访问serverlessoptions对象。现在的问题是,我必须访问serverless.yml中插件的输出,到目前为止,我还没有看到如何做到这一点。也就是说,我希望能够做这样的事情:

custom:
domains:
prod: tommedema.tk
ssl:
prod:
dnsTxtRoot: ${{myPlugin:cert.dnsTxtRoot}}
dnsTxtWww: ${{myPlugin:cert.dnsTxtWww}}
certArn: ${{myPlugin:cert.certArn}}

但这似乎是不可能的。是这样吗?

如果这也是不可能的,我如何在没有任何手动步骤的情况下以编程方式(即遵循基础设施作为代码原则)部署具有自定义SSL证书的服务?即

  1. 从certbot请求证书
  2. 从certbot接收用于验证的DNS txt记录
  3. 将DNS txt记录附加到路由53记录集
  4. 部署DNS记录并验证证书
  5. 从certbot下载证书并将其上传到ACM
  6. 从ACM接收ARN证书
  7. 云形成模板内云锋分布内的证书ARN参考
  8. 随附ARN证书重新部署

可以在部署时执行此操作,但证书已过期,因此最好将其作为重复操作。

当我遇到这个问题时,我创建了一个Lambda来追加SSL证书并安装它。它需要的密钥可以作为安全的环境变量给出。

然后,我使用serverless-warmup-plugin设置一个每日触发器,以检查证书是否要刷新。该插件也可配置为在部署时预热相关的Lambda,这使我能够在每次部署时检查是否有过期或丢失的SSL证书。

也许你可以做一些类似的事情。

对于这个特定的用例,使用Step函数是最好的选择。由于您有3个不同的步骤,它们将是三个独立的Lambda函数,Step函数可以在它们之间传递输入/输出,并包括等待时间和重试。

最新更新