terraform有条件地根据外部数据创建资源?

时间:2017-07-06 06:03:18

标签: terraform

作为设置的一部分,我创建了TLS证书并将其存储在S3中。创建证书是通过external数据源完成的,该数据源运行命令以生成证书。然后我使用这些输出来创建S3桶对象resource

这可以很好地运行第一次时间terraform apply。但是,如果我更改任何其他(非证书)变量,资源等并重新运行,它会重新运行external命令,该命令生成新的密钥/证书对,将它们上传到S3,并打破已经存在的所有内容的工作原理。

有条件创建资源的方法吗?我可以使用什么模式来创建证书,只有它们不存在?

我确实在本地存储生成的密钥/证书,但这是敏感的密钥材料;我不希望它存储在本地磁盘中(每个环境都有密钥)。

密钥/证书生成和存储:

data "external" "ca" {
  program = ["sh","-c","jq '.root|fromjson' | cfssl gencert -initca -"]
  #
  query = {root = "${ data.template_file.etcd-ca-csr.rendered }"}
  # the result will be saved in
  # data.external.etcd-ca.result.key
  # data.external.etcd-ca.result.csr
  # data.external.etcd-ca.result.cert
}

resource "aws_s3_bucket_object" "ca_cert" {
  bucket = "${aws_s3_bucket.my_bucket.id}"
  key = "ca.pem"
  content = "${data.external.ca.result.cert}"
}
resource "aws_s3_bucket_object" "ca_key" {
  bucket = "${aws_s3_bucket.my_bucket.id}"
  key = "ca-key.pem"
  content = "${data.external.ca.result.key}"
}

很高兴看到使用某种形式的条件或完全不同的生成模式。

1 个答案:

答案 0 :(得分:2)

此行为的原因是external是一个数据源,因此Terraform希望它是只读且无副作用的。它为每个计划重新运行数据源。

为了通过外部脚本执行此操作,需要使用资源调配程序运行脚本将其上载到S3,因为当前没有external等效项对于资源 允许有副作用,而配置者只有副作用 - (也就是说,他们可以'产生结果以在配置中的其他地方使用。)

另一种方法是使用Terraform的built-in TLS provider,它允许在Terraform内部创建证书。在这种情况下,您似乎正在尝试创建新的CA证书和密钥,这可以通过tls_self_signed_cert完成,如下所示:

resource "tls_private_key" "ca" {
  algorithm = "RSA"
  rsa_bits = 2048
}

resource "tls_self_signed_cert" "ca" {
  key_algorithm   = "RSA"
  private_key_pem = "${tls_private_key.ca.private_key_pem}"

  # ... subject and validity settings, as appropriate

  is_ca_certificate = true

  allowed_uses = ["cert_signing"]      
}

resource "aws_s3_bucket_object" "ca_cert" {
  bucket  = "${aws_s3_bucket.my_bucket.id}"
  key     = "ca.pem"
  content = "${resource.tls_self_signed_cert.ca.cert_pem}"
}

resource "aws_s3_bucket_object" "ca_key" {
  bucket  = "${aws_s3_bucket.my_bucket.id}"
  key     = "ca-key.pem"
  content = "${resource.tls_self_signed_cert.ca.private_key_pem}"
}

生成的私钥将包含在状态中以供将来运行使用,因此确保安全地存储状态非常重要。请注意,使用external数据源也是如此,因为数据源结果也存储在状态中。因此,从存储秘密的角度来看,这种方法是等效的。

我在an article on my website中写了更多有关使用Terraform进行TLS证书管理的详细信息。它的范围比你的要求更广泛,但可能有一些兴趣。