Terraform AWS Provider:SecretsManager 无法应用,因为版本已被删除
Terraform AWS Provider: SecretsManager can't apply because version was deleted
我们有一个创建过一次的 AWS SecretsManager Secret。该秘密将每小时由外部作业更新一次。
我遇到的问题是,有时 terraform plan/apply 会失败并显示以下消息:
AWS 提供商 2.48
Error: Error refreshing state: 1 error occurred:
* module.xxx.xxx: 1 error occurred:
* module.xxx.aws_secretsmanager_secret_version.xxx:
aws_secretsmanager_secret_version.xxx: error reading Secrets Manager Secret Version: InvalidRequestException: You can't perform this operation on secret version 68AEABC3-34BE-4723-8BF5-469A44F9B1D9 because it was deleted.
我们尝试了两种解决方案:
1) 通过 aws cli 强制删除整个秘密,但这有副作用,我们的依赖资源之一也将被重新创建(ecs 模板定义取决于该秘密)。这可行,但我们不希望重新创建 ecs 事物的副作用。
2) 手动编辑后端.tfstate 文件并设置当前AWS secret 版本。然后运行再次计划。
这两种解决方案在某种程度上似乎都很老套。解决此问题的最佳方法是什么?
您可以使用 terraform import
来协调 运行 与 plan
或 apply
之前的状态差异。
在你的情况下,这看起来像:
terraform import module.xxx.aws_secretsmanager_secret_version.xxx arn:aws:secretsmanager:some_region:some_account_id:secret:example-123456|xxxxx-xxxxxxx-xxxxxxx-xxxxx
我认为您遇到的问题可能是默认情况下 AWS 尝试 "help you" 不让您自动删除机密,直到 7 天过去。 AWS 通过告诉您他们给您 7 天的宽限期来更新可能依赖于此的 "code" 来尝试 "help you"。这使得自动化更加困难。
我通过将恢复 window 期限设置为“0 天”来解决这个问题,有效地消除了 AWS 提供的宽限期。
然后您可以手动(通过 AWS CLI)或通过 terraform 任意地进行 terraform、重命名或删除您的密钥。
您可以通过首先输入此值来更新现有机密。然后更改秘密的名称(如果你愿意),或根据需要删除它(这个 terraform 部分)并 运行 在恢复 window days = 0 后再次应用 terraform。
这是一个例子:
resource "aws_secretsmanager_secret" "mySecret" {
name = "your secret name"
recovery_window_in_days = "0"
// this is optional and can be set to true | false
lifecycle {
create_before_destroy = true
}
}
*注意,还有一个选项"create before destroy"你可以在生命周期上设置。
另外,您可以像这样使用 terraform 资源来更新秘密值:
此示例将设置一次秘密值,然后告诉 terraform 在初始创建后忽略对值(本示例中的用户名、密码)所做的任何更改。
如果删除生命周期部分,Terraform 将跟踪秘密值本身是否已更改。如果它们发生了变化,它们将恢复为 terraform 状态下的值。
如果您将 tfstate 文件存储在受 s3 保护的存储桶中,这比不这样做更安全,因为它们在状态文件中是纯文本,因此任何有权访问您的 terraform 状态文件的人都可以看到您的秘密值。
我建议:1) 弄清楚是什么意外地删除了您的机密? 2) 让你的 "external job" 成为一个 terraform bash 脚本来使用资源更新值,如下例所示。
希望这能给你一些想法。
resource "aws_secretsmanager_secret_version" "your-secret-data" {
secret_id = aws_secretsmanager_secret.your-secret.id
secret_string = <<-EOF
{
"username": "usernameValue",
"password": "passwordValue"
}
EOF
// ignore any updates to the initial values above done after creation.
lifecycle {
ignore_changes = [
secret_string
]
}
}
我们有一个创建过一次的 AWS SecretsManager Secret。该秘密将每小时由外部作业更新一次。 我遇到的问题是,有时 terraform plan/apply 会失败并显示以下消息:
AWS 提供商 2.48
Error: Error refreshing state: 1 error occurred:
* module.xxx.xxx: 1 error occurred:
* module.xxx.aws_secretsmanager_secret_version.xxx:
aws_secretsmanager_secret_version.xxx: error reading Secrets Manager Secret Version: InvalidRequestException: You can't perform this operation on secret version 68AEABC3-34BE-4723-8BF5-469A44F9B1D9 because it was deleted.
我们尝试了两种解决方案: 1) 通过 aws cli 强制删除整个秘密,但这有副作用,我们的依赖资源之一也将被重新创建(ecs 模板定义取决于该秘密)。这可行,但我们不希望重新创建 ecs 事物的副作用。 2) 手动编辑后端.tfstate 文件并设置当前AWS secret 版本。然后运行再次计划。
这两种解决方案在某种程度上似乎都很老套。解决此问题的最佳方法是什么?
您可以使用 terraform import
来协调 运行 与 plan
或 apply
之前的状态差异。
在你的情况下,这看起来像:
terraform import module.xxx.aws_secretsmanager_secret_version.xxx arn:aws:secretsmanager:some_region:some_account_id:secret:example-123456|xxxxx-xxxxxxx-xxxxxxx-xxxxx
我认为您遇到的问题可能是默认情况下 AWS 尝试 "help you" 不让您自动删除机密,直到 7 天过去。 AWS 通过告诉您他们给您 7 天的宽限期来更新可能依赖于此的 "code" 来尝试 "help you"。这使得自动化更加困难。
我通过将恢复 window 期限设置为“0 天”来解决这个问题,有效地消除了 AWS 提供的宽限期。
然后您可以手动(通过 AWS CLI)或通过 terraform 任意地进行 terraform、重命名或删除您的密钥。
您可以通过首先输入此值来更新现有机密。然后更改秘密的名称(如果你愿意),或根据需要删除它(这个 terraform 部分)并 运行 在恢复 window days = 0 后再次应用 terraform。
这是一个例子:
resource "aws_secretsmanager_secret" "mySecret" {
name = "your secret name"
recovery_window_in_days = "0"
// this is optional and can be set to true | false
lifecycle {
create_before_destroy = true
}
}
*注意,还有一个选项"create before destroy"你可以在生命周期上设置。
另外,您可以像这样使用 terraform 资源来更新秘密值:
此示例将设置一次秘密值,然后告诉 terraform 在初始创建后忽略对值(本示例中的用户名、密码)所做的任何更改。
如果删除生命周期部分,Terraform 将跟踪秘密值本身是否已更改。如果它们发生了变化,它们将恢复为 terraform 状态下的值。
如果您将 tfstate 文件存储在受 s3 保护的存储桶中,这比不这样做更安全,因为它们在状态文件中是纯文本,因此任何有权访问您的 terraform 状态文件的人都可以看到您的秘密值。
我建议:1) 弄清楚是什么意外地删除了您的机密? 2) 让你的 "external job" 成为一个 terraform bash 脚本来使用资源更新值,如下例所示。
希望这能给你一些想法。
resource "aws_secretsmanager_secret_version" "your-secret-data" {
secret_id = aws_secretsmanager_secret.your-secret.id
secret_string = <<-EOF
{
"username": "usernameValue",
"password": "passwordValue"
}
EOF
// ignore any updates to the initial values above done after creation.
lifecycle {
ignore_changes = [
secret_string
]
}
}