我想使用Terraform MySQL Provider保留mysql用户列表,并为创建新的测试环境提供方便。 .tf.tfstate文件似乎都希望以纯文本格式存储MySQL密码。由团队维护。当.tf中存在机密时,这种做法有何不同?可以完全加密这些值吗?

关于.tfstate:

我可以在运行Terraform apply之后将.tf安全地存储在某处,但是这种用法会更好完全不存储的情况下?

#1 楼

Terraform支持在调用期间添加带有变量的其他文件。

文档:https://www.terraform.io/intro/getting-started/variables.html#from-a-file

我们正在使用该功能在每次Terraform调用时提供一个secrets.tfvars文件。我们还使用脚本来包装命令,以使命令的调用保持一致,并且所有团队成员都避免犯相同的错误。包装程序在执行之前将.tfstate与S3同步,最后将.tfstate推回S3。我还听说有人用领事存储在状态中做相同的事情,甚至在领事中添加了一种信号量以防止两个人同时启动Terraform。在variables.tf文件中,它强制用户输入值。可以手动输入,也可以使用如上所述的-var-file命令选项输入。不对您的机密设置默认值是执行需要更改机密的更改的好方法。

secrets.tfvars文件是指向其中一个未存储在版本控制中的机密文件的符号链接。 。我们每个环境都有几个,例如secrets-prod.tfvarssecrets-dev.tfvarssecrets-stg.tfvars等。分享秘密的其他方式。由于当前机密信息的格式更改或机密信息本身,我们需要在版本控制渠道之外将其传达给团队-坦白说,这并不总是很好。但是秘密确实很少改变。

评论


链接到代码-gist.github.com/kesor/21f942be0350559b44f7ad1f9d846e7c

– Evgeny Zislis
17年4月3日在9:31

#2 楼

我们避免使用Terraform处理我们的秘密。即使您如上所述设法通过var文件“ secrtes.tfvars”注入机密,这些机密也会存储在terraform(远程)状态。

您可以保护远程状态文件通过使用例如S3授权,或者您可以gitignore本地状态文件,但我们决定不依赖这种保护。

评论


还要检查github.com/hashicorp/terraform/issues/516,这是他们跟踪tfstate泄露机密的问题的地方

– jottr
17-10-2在19:34



#3 楼

如果您使用的是AWS,请查看AWS Blog上Segment.io的“管理秘密的正确方法”。我们提倡对所有客户使用chamber来管理机密。通过结合使用AWS Systems Manager参数存储(SSM)和KMS密钥来工作。这样可确保机密信息在静止(和传输)时进行加密,由IAM保护,可通过CloudTrails进行审核,并且仅在运行时作为环境变量公开。

配置腔室并设置KMS密钥后,我们将机密写入参数存储中。

chamber write db TF_VAR_DB_USER foobar
chamber write db TF_VAR_DB_PASS secret


然后在调用terraform时使用这些秘密。您的HCL代码中名为DB_USERDB_PASS的变量。

例如,您可以将其添加到variables.tf

chamber exec db -- terraform plan


注意:chamber将始终以大写形式导出环境变量/>我们提供了一个名为terraform-aws-kms-key的Terraform模块,以简化配置KMS密钥的过程。请查看我们的详细文档,并提供有关如何使用具有多个名称空间的chamber以及如何使用带有Terraform的Chamber来管理机密的示例。请参阅我们完整的参考示例以了解供应室相关性。

对于.tfstate,您可以很好地说明状态文件中存在纯文本机密。真的没有办法解决这个问题。为了让terraform计算更改以构建计划,它需要知道“之前”和“之后”状态。因此,我们建议使用带有强制版本控制的加密S3存储桶。根据最佳实践,使用terraform-aws-tfstate-backend模块配置存储区和DynamoDB锁定表。

评论


这与AWS服务紧密相关,AWS服务没有提到这个问题,而且听起来并不能真正解决内部基础架构或任何其他云。

–滕西拜
18年7月27日在8:21

@tensibai,您是正确的。最初的问题没有提供足够的信息来确定操作平台以做出最佳建议。每个平台都将取决于平台功能而有所不同。在prem或baremetal上,用户可能要考虑结合使用Vault和Terraform Enterprise。实施范围将大得多。 :)

–埃里克·奥斯特曼(Erik Osterman)
18年7月27日在20:42

我已经使用过AWS Secrets Manager,并且不想使用Chamber和Parameter Store。是否可以使用Secrets Manager做同样的事情?

– red888
19年1月21日在16:19

#4 楼

要将机密信息导入.tf文件,您还可以使用外部数据源。这可能是例如解密您秘密的脚本。

评论


不利的一面是,任何具有依赖于外部数据源值的属性的资源都将被“计算”,因此即使机密未更改,每次运行也可能会被terraform修改。可能没问题,但在某些情况下可能要花一些时间或最坏的时间。

–达沃斯
20-2-6在10:52

#5 楼

我研究了几种不同的方式,但是在实现像Vault这样的更大的东西之前,我特别喜欢git-crypt做一个临时的事情。

评论


要告诉谁投票,请解释原因。

– jottr
17-10-2在19:43



#6 楼

您可以利用外部数据源将机密信息导入Terraform并使用gpg加密机密文件。

例如,这是terraform文件在创建密码为foobarbaz的rds实例时需要的

data "external" "rds" {
  program  = [ "cat", ".secrets/rds.json"]
}


resource "aws_db_instance" "default" {
  allocated_storage    = 20
  storage_type         = "gp2"
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t2.micro"
  name                 = "mydb"
  username             = "foo"
  password             = "${data.external.rds.result.password}"
  parameter_group_name = "default.mysql5.7"
}


您可以查看这篇文章,其中详细说明了如何执行此操作。

如何加密Terraform机密

#7 楼

您可以将值存储在参数存储中,并通过使用数据资源获取值在terraform资源中使用它们。
data "aws_ssm_parameter" "rds_password" {
  name = "/${var.project_name}/DB_PASSWORD"
}

resource "aws_db_instance" "rds" {
  ...
  password = data.aws_ssm_parameter.rds_password.value
  ...
}