hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.72k stars 9.08k forks source link

"Error: empty result" when importing aws_controltower_control resource using import block #38421

Closed nc-rajeshnair closed 1 month ago

nc-rajeshnair commented 1 month ago

Description

Terraform.tfvars

controls = [
    {
        control_names =  [
            "AWSGR_CLOUDTRAIL_CHANGE_PROHIBITED",
            "AWSGR_CLOUDTRAIL_CLOUDWATCH_LOGS_ENABLED",
            "AWSGR_CLOUDTRAIL_ENABLED",
            "AWSGR_CLOUDTRAIL_VALIDATION_ENABLED",
            "AWSGR_CLOUDWATCH_EVENTS_CHANGE_PROHIBITED",
            "AWSGR_CONFIG_AGGREGATION_AUTHORIZATION_POLICY",
            "AWSGR_CONFIG_AGGREGATION_CHANGE_PROHIBITED",
            "AWSGR_CONFIG_CHANGE_PROHIBITED",
            "AWSGR_CONFIG_ENABLED",
            "AWSGR_CONFIG_RULE_CHANGE_PROHIBITED",
            "AWSGR_IAM_ROLE_CHANGE_PROHIBITED",
            "AWSGR_LAMBDA_CHANGE_PROHIBITED",
            "AWSGR_LOG_GROUP_POLICY",
            "AWSGR_SNS_CHANGE_PROHIBITED",
            "AWSGR_SNS_SUBSCRIPTION_CHANGE_PROHIBITED",
        ],
        organizational_unit_ids = ["ou-xxx-xxx", "ou-yyy-yyyy", "ou-zzz-zzzz", "ou-www-wwww", "ou-eee-eeee", "ou-ttt-tttt", "ou-ggg-gggg", "ou-oooo-ooooo", "ou-jjjj-jjjj", "ou-llll-llll",  "ou-hhh-hhhh", ],
    },
    {
        control_names = [
            "AWSGR_AUDIT_BUCKET_DELETION_PROHIBITED",
            "AWSGR_AUDIT_BUCKET_PUBLIC_READ_PROHIBITED",
            "AWSGR_AUDIT_BUCKET_PUBLIC_WRITE_PROHIBITED",
            "AWSGR_CLOUDTRAIL_CHANGE_PROHIBITED",
            "AWSGR_CLOUDTRAIL_CLOUDWATCH_LOGS_ENABLED",
            "AWSGR_CLOUDTRAIL_ENABLED",
            "AWSGR_CLOUDTRAIL_VALIDATION_ENABLED",
            "AWSGR_CLOUDWATCH_EVENTS_CHANGE_PROHIBITED",
            "AWSGR_CONFIG_AGGREGATION_AUTHORIZATION_POLICY",
            "AWSGR_CONFIG_AGGREGATION_CHANGE_PROHIBITED",
            "AWSGR_CONFIG_CHANGE_PROHIBITED",
            "AWSGR_CONFIG_ENABLED",
            "AWSGR_CONFIG_RULE_CHANGE_PROHIBITED",
            "AWSGR_CT_AUDIT_BUCKET_ENCRYPTION_CHANGES_PROHIBITED",
            "AWSGR_CT_AUDIT_BUCKET_LIFECYCLE_CONFIGURATION_CHANGES_PROHIBITED",
            "AWSGR_CT_AUDIT_BUCKET_LOGGING_CONFIGURATION_CHANGES_PROHIBITED",
            "AWSGR_CT_AUDIT_BUCKET_POLICY_CHANGES_PROHIBITED",
            "AWSGR_DETECT_CLOUDTRAIL_ENABLED_ON_SHARED_ACCOUNTS",
            "AWSGR_IAM_ROLE_CHANGE_PROHIBITED",
            "AWSGR_LAMBDA_CHANGE_PROHIBITED",
            "AWSGR_LOG_GROUP_POLICY",
            "AWSGR_SNS_CHANGE_PROHIBITED",
            "AWSGR_SNS_SUBSCRIPTION_CHANGE_PROHIBITED",
        ],
        organizational_unit_ids = ["ou-xxx-xxxxx"],
    }
]

variables.tf

variable "controls" {

  type = list(object({
    control_names           = list(string)
    organizational_unit_ids = list(string)
  }))

}

Data Sources

data "aws_organizations_organization" "organization" {}

# Fetch current root id from HNK AWS Control Tower
data "aws_organizations_organizational_units" "root" {
  parent_id = data.aws_organizations_organization.organization.roots[0].id
}

# Get OUs data resources up to five levels of OUs deep under a root

data "aws_organizations_organizational_units" "ous_depth_1" {
  for_each  = toset([for x in data.aws_organizations_organizational_units.root.children : x.id])
  parent_id = each.key
  depends_on = [
    data.aws_organizations_organizational_units.root
  ]
}

data "aws_organizations_organizational_units" "ous_depth_2" {
  for_each  = toset([for y in flatten([for x in data.aws_organizations_organizational_units.ous_depth_1 : x.children]) : y.id])
  parent_id = each.key
  depends_on = [
    data.aws_organizations_organizational_units.ous_depth_1
  ]
}

data "aws_organizations_organizational_units" "ous_depth_3" {
  for_each  = toset([for y in flatten([for x in data.aws_organizations_organizational_units.ous_depth_2 : x.children]) : y.id])
  parent_id = each.key
  depends_on = [
    data.aws_organizations_organizational_units.ous_depth_2
  ]
}

data "aws_organizations_organizational_units" "ous_depth_4" {
  for_each  = toset([for y in flatten([for x in data.aws_organizations_organizational_units.ous_depth_3 : x.children]) : y.id])
  parent_id = each.key
  depends_on = [
    data.aws_organizations_organizational_units.ous_depth_3
  ]
}

Local variables

locals {

  # guardrails_ids_map = { for idx, id in local.guardrails_ids : idx => id }

  ous_depth_1 = [for x in data.aws_organizations_organizational_units.root.children : x]
  ous_depth_2 = flatten([for x in data.aws_organizations_organizational_units.ous_depth_1 : x.children if length(x.children) != 0])
  ous_depth_3 = flatten([for x in data.aws_organizations_organizational_units.ous_depth_2 : x.children if length(x.children) != 0])
  ous_depth_4 = flatten([for x in data.aws_organizations_organizational_units.ous_depth_3 : x.children if length(x.children) != 0])
  ous_depth_5 = flatten([for x in data.aws_organizations_organizational_units.ous_depth_4 : x.children if length(x.children) != 0])

  # Compute map from OU id to OU arn for the whole organization
  ous_id_to_arn_map = { for ou in concat(local.ous_depth_1, local.ous_depth_2, local.ous_depth_3, local.ous_depth_4, local.ous_depth_5) :
    ou.id => ou.arn
  }

  guardrails_list = flatten([
    for i in range(0, length(var.controls)) : [
      for pair in setproduct(element(var.controls, i).control_names, element(var.controls, i).organizational_unit_ids) :
      {
        control = "arn:aws:controltower:${data.aws_region.current.name}::control/${pair[0]}"
        ou = pair[1]
        control_identifier = "arn:aws:controltower:${data.aws_region.current.name}::control/${pair[0]}"
        target_identifier = local.ous_id_to_arn_map[pair[1]]
      }
    ]
  ])

Resource Creation

resource "aws_controltower_control" "hnk_controltower_control" {
  for_each = { for idx, val in local.guardrails_list : "${val.ou}-${val.control}" => val }
  control_identifier = each.value.control_identifier
  target_identifier  = each.value.target_identifier
}

Resource Import

import {
  for_each = { for idx, val in local.guardrails_list : "${val.ou}-${val.control}" => val }
  to = aws_controltower_control.hnk_controltower_control[each.value]
  id = "${each.value.target_identifier},${each.value.control_identifier}"
}

When i run this code i get an Empty Result error. I have also verified all the values no luck. Need help to fix this.

References

No response

Would you like to implement a fix?

None

github-actions[bot] commented 1 month ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

justinretzolk commented 1 month ago

Hey @nc-rajeshnair šŸ‘‹ Thank you for taking the time to raise this! We use Issues in this repository to track feature enhancements and bugs in the AWS Provider. To maintain that, we ask that broader questions are raised using one of the community resources, such as the AWS Provider forum. With that in mind, I'm going to close this issue.

github-actions[bot] commented 1 month ago

[!WARNING] This issue has been closed, meaning that any additional comments are hard for our team to see. Please assume that the maintainers will not see them.

Ongoing conversations amongst community members are welcome, however, the issue will be locked after 30 days. Moving conversations to another venue, such as the AWS Provider forum, is recommended. If you have additional concerns, please open a new issue, referencing this one where needed.

github-actions[bot] commented 1 week ago

I'm going to lock this issue because it has been closed for 30 days ā³. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.