Terraform调用CloudFormation创建AWS IoT审计配置遇资源已存在错误
解决AWS IoT AccountAuditConfiguration已存在时的Terraform+CloudFormation更新问题
问题背景
因为Terraform原生不支持AWS IoT AccountAuditConfiguration资源,通过Terraform调用CloudFormation模板配置时触发「Resource already exists」错误,需要实现更新已有配置而非重复创建的逻辑。
相关文件
sample.json.tpl(CloudFormation模板)
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Amazon Web Services IoT AccountAuditConfiguration Template", "Resources": { "IoTAuditConfiguration": { "Type": "AWS::IoT::AccountAuditConfiguration", "Properties": { "AccountId": "${account_id}", "AuditCheckConfigurations": { "AuthenticatedCognitoRoleOverlyPermissiveCheck": { "Enabled": true }, "CaCertificateExpiringCheck": { "Enabled": true }, "CaCertificateKeyQualityCheck": {"Enabled": true }, "ConflictingClientIdsCheck": { "Enabled": true }, "DeviceCertificateExpiringCheck": { "Enabled": true }, "DeviceCertificateKeyQualityCheck": { "Enabled": true }, "DeviceCertificateSharedCheck": { "Enabled": true }, "IntermediateCaRevokedForActiveDeviceCertificatesCheck" : {"Enabled" : true}, "IotPolicyOverlyPermissiveCheck": { "Enabled": true }, "IoTPolicyPotentialMisConfigurationCheck" : {"Enabled" : true}, "IotRoleAliasAllowsAccessToUnusedServicesCheck": { "Enabled": true }, "IotRoleAliasOverlyPermissiveCheck": { "Enabled": true }, "LoggingDisabledCheck": { "Enabled": true }, "RevokedCaCertificateStillActiveCheck": { "Enabled": true }, "RevokedDeviceCertificateStillActiveCheck": { "Enabled": true }, "UnauthenticatedCognitoRoleOverlyPermissiveCheck": { "Enabled": true } }, "AuditNotificationTargetConfigurations": { "Sns": { "TargetArn": "${sns_notifications_arn}", "RoleArn": "${role}", "Enabled": true } }, "RoleArn": "${role}" } } } }
cloudformation_deploy.tf(Terraform配置)
data "template_file" "aws_iot_account_audit_enable" { template = "${file("${path.module}/sample.json.tpl")}" vars = { account_id = data.aws_caller_identity.current.account_id sns_notifications_arn = aws_sns_topic.iot_topic.arn role = aws_iam_role.iot_role.name } } resource "aws_cloudformation_stack" "stack" { name = "stack" template_body = "${data.template_file.aws_iot_account_audit_enable.rendered}" }
错误信息
Error: waiting for CloudFormation Stack (arn:aws:cloudformation:us-east-2:xxxxxxxxxxxx:stack/stack/xxxxxxxxxxxxx) create: failed to create CloudFormation stack, rollback requested (ROLLBACK_COMPLETE): ["The following resource(s) failed to create: [IoTAuditConfiguration]. Rollback requested by user." "Resource handler returned message: \"The AccountAuditConfiguration already exists.\" (RequestToken: xxxxxxxxxxxxxxxxxxx, HandlerErrorCode: AlreadyExists)"]
解决方案
AWS IoT AccountAuditConfiguration是账户级唯一资源,每个AWS账户仅能存在一个实例。CloudFormation默认尝试创建新资源,因此已存在时会报错。以下两种方法可实现更新逻辑:
方法一:CloudFormation资源导入+Terraform更新栈
导入已存在的配置到CloudFormation栈
先将模板渲染为实际JSON文件(替换所有变量),然后执行AWS CLI导入命令:aws cloudformation import-stack \ --stack-name stack \ --template-body file://sample.json \ --resources-to-import '[ { "ResourceType": "AWS::IoT::AccountAuditConfiguration", "LogicalResourceId": "IoTAuditConfiguration", "ResourceIdentifier": { "AccountId": "你的AWS账户ID" } } ]'修正Terraform配置并支持更新
替换旧的template_file为Terraform 0.12+支持的templatefile函数,同时修正RoleArn参数(需传入ARN而非角色名):data "aws_caller_identity" "current" {} resource "aws_cloudformation_stack" "stack" { name = "stack" template_body = templatefile("${path.module}/sample.json.tpl", { account_id = data.aws_caller_identity.current.account_id sns_notifications_arn = aws_sns_topic.iot_topic.arn role = aws_iam_role.iot_role.arn }) capabilities = ["CAPABILITY_NAMED_IAM"] }后续修改模板或变量后,Terraform会触发CloudFormation栈更新,从而同步修改IoT审计配置。
方法二:用Terraform null_resource调用AWS CLI直接更新
跳过CloudFormation,直接通过AWS CLI的update-account-audit-configuration命令实现创建/更新(首次执行等同于创建,后续执行则更新):
data "aws_caller_identity" "current" {} resource "null_resource" "iot_audit_config" { triggers = { audit_checks = jsonencode({ AuthenticatedCognitoRoleOverlyPermissiveCheck = { Enabled = true }, CaCertificateExpiringCheck = { Enabled = true }, CaCertificateKeyQualityCheck = { Enabled = true }, ConflictingClientIdsCheck = { Enabled = true }, DeviceCertificateExpiringCheck = { Enabled = true }, DeviceCertificateKeyQualityCheck = { Enabled = true }, DeviceCertificateSharedCheck = { Enabled = true }, IntermediateCaRevokedForActiveDeviceCertificatesCheck = { Enabled = true }, IotPolicyOverlyPermissiveCheck = { Enabled = true }, IoTPolicyPotentialMisConfigurationCheck = { Enabled = true }, IotRoleAliasAllowsAccessToUnusedServicesCheck = { Enabled = true }, IotRoleAliasOverlyPermissiveCheck = { Enabled = true }, LoggingDisabledCheck = { Enabled = true }, RevokedCaCertificateStillActiveCheck = { Enabled = true }, RevokedDeviceCertificateStillActiveCheck = { Enabled = true }, UnauthenticatedCognitoRoleOverlyPermissiveCheck = { Enabled = true } }) sns_topic_arn = aws_sns_topic.iot_topic.arn role_arn = aws_iam_role.iot_role.arn } provisioner "local-exec" { command = <<EOF aws iot update-account-audit-configuration \ --account-id ${data.aws_caller_identity.current.account_id} \ --audit-check-configurations '${self.triggers.audit_checks}' \ --audit-notification-target-configurations '{"Sns": {"TargetArn": "${self.triggers.sns_topic_arn}", "RoleArn": "${self.triggers.role_arn}", "Enabled": true}}' \ --role-arn ${self.triggers.role_arn} EOF } }
当triggers中的配置发生变化时,Terraform会自动重新执行CLI命令更新审计配置。
内容的提问来源于stack exchange,提问作者NotAgain
相关产品推荐
相关产品推荐

