Terraform中的可选CloudFront Lambda函数关联

时间:2018-12-11 02:33:40

标签: aws-lambda amazon-cloudfront terraform

我们正在CloudFront和S3上托管我们的Web应用程序。该基础结构是在Terraform模块中配置的。我们正在使用同一模块(由Terragrunt管理)将Web应用程序部署到暂存和生产环境。

很显然,我们不希望公众访问我们的暂存环境。因此,我们创建了一个Lambda函数来启用基本HTTP身份验证,并使用lambda_function_association资源中的aws_cloudfront_distribution来启用它。

问题是我们不希望Lambda也能在我们的产品环境中运行。我无法有条件地在资源上设置关联。

我还尝试过创建两个具有相同名称的资源并设置count属性,以便仅存在这些资源。

例如

# Basic Auth Guard
resource "aws_cloudfront_distribution" "default" {
  count = "${var.behind_auth_guard}"
  ...
}

# No Basic Auth Guard
resource "aws_cloudfront_distribution" "default" {
  count = "${var.behind_auth_guard ? 0 : 1}"
}

但是,当我尝试部署代码时,却得到aws_cloudfront_distribution.default: resource repeated multiple times

有什么方法可以实现我想要的吗?

我考虑过的另一个选项是在两个版本上都设置Lambda,但是在生产中什么也不做。但是,这似乎效率低下且成本高昂,因为每次请求都会调用Lamdba,并且希望在可能的情况下避免这种情况。

2 个答案:

答案 0 :(得分:2)

使用Terraform v0.12.0,这将非常容易解决,因为它支持Dynamic Nested Blocks。不幸的是,该版本不会在2019年第一季度之前发布。

同时,您可以稍作改动,接受您自己提出的建议。您只需要进行很小的更改,因为不支持重复的名称。

# Basic Auth Guard
resource "aws_cloudfront_distribution" "cf_with_guard" {
  count = "${var.behind_auth_guard}"
  ...
}

# No Basic Auth Guard
resource "aws_cloudfront_distribution" "cf_no_guard" {
  count = "${var.behind_auth_guard ? 0 : 1}"
}

如果现在要使用此资源的任何输出,则必须使用小的hack。例如,如果要输出分布的id

output "cf_id" {
  value = "${var.behind_auth_guard ? join("", aws_cloudfront_distribution.cf_with_guard.*.id) : join("", aws_cloudfront_distribution.cf_no_guard.*.id)}"
}

join()是必需的,因为您不能引用不存在的资源。即使在if语句中也没有。 join()通过引用所有资源的列表来解决此问题,如果资源的count为0,则为空。

注意事项,以备将来参考:如果v0.12.0已发布,则不再需要上述解决方法。只需参考动态嵌套块即可。

答案 1 :(得分:0)

正如 Joris 在上面指出的动态嵌套块是要走的路。以下是对我有用的方法:

dynamic "lambda_function_association" {
  for_each = var.ENV == "prod" ? [] : [0]
  content {
    event_type   = "viewer-request"
    lambda_arn   = "${aws_lambda_function.my_auth_lambda.qualified_arn}"
  }
}

这会为除生产环境之外的所有内容打开 lambda 函数。