如何访问无服务器框架的serverless.yml中的插件输出?

时间:2017-11-12 19:31:11

标签: amazon-web-services aws-lambda amazon-cloudformation serverless-framework

上下文:要实现完整的“基础架构作为代码”,我想编写使用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,或者此脚本需要了解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
  3. 接收DNS txt记录以进行验证
  4. 将DNS txt记录附加到route53记录集
  5. 部署DNS记录并验证证书
  6. 从certbot下载证书并将其上传至ACM
  7. 从ACM收到证书ARN
  8. 从云信息模板
  9. 内的云端分发中引用证书ARN
  10. 使用附加证书ARN重新部署

2 个答案:

答案 0 :(得分:1)

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

当我遇到这个问题时,我创建了一个Lambda来备份SSL证书并安装它。 (它需要很长的超时,但这没关系 - 它不需要经常运行)。它需要的密钥可以作为安全的环境变量给出。

然后我使用error: StatusCodeError: 400 -设置每日触发器来检查证书是否应该刷新。该插件也可以配置为在部署时预热相关的lambdas,这允许我检查每次部署时过期或缺少的SSL证书。

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

答案 1 :(得分:0)

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