Search code examples
amazon-web-servicesterraformterraform-provider-awsaws-ssm

Output list of maps in parent module from child module in Terraform


I have three child modules and one parent module for ssm patching. One module in particular is different than the rest (RHEL) it will never need to be changed, so the child module was written differently.

I have my baseline approval rules written as a dynamic object and have prepared the variable for the object.

    resource "aws_ssm_patch_baseline" "baseline" {
    
      name             = format("%s-%s-%s-baseline", var.patch_baseline_label, var.env, lower(local.operating_system))
      description      = var.description
      operating_system = local.operating_system
    
      approved_patches                  = var.approved_patches
      rejected_patches                  = var.rejected_patches
      approved_patches_compliance_level = var.compliance_level
      
      dynamic "approval_rule" {
        for_each = var.baseline_approval_rules
        content {
    
          approve_after_days  = approval_rule.value.approve_after_days
          compliance_level    = approval_rule.value.compliance_level
          enable_non_security = approval_rule.value.enable_non_security
    
          # patch filter values : https://docs.aws.amazon.com/cli/latest/reference/ssm/describe-patch-properties.html
          dynamic "patch_filter" {
            for_each = approval_rule.value.patch_baseline_filters
    
            content {
              key    = patch_filter.value.name
              values = patch_filter.value.values
            }
          }
        }
      }
    
      tags = merge(var.tags, { Name = format("%s-%s-%s", var.patch_baseline_label, var.env, lower(local.operating_system)) })
    }

The variable for the approval rules is written as such:

    variable "baseline_approval_rules" {
      description = "list of approval rules defined in the patch baseline (Max 10 rules). For compliance_level, it means that if an approved patch is reported as missing, this is the severity of the compliance violation. Valid compliance levels include the following: CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL, UNSPECIFIED. The default value is UNSPECIFIED."
      type = list(object({
        approve_after_days : number
        compliance_level : string
        enable_non_security : bool
        patch_baseline_filters : list(object({
          name : string
          values : list(string)
        }))
      }))
    
      default = [
        {
          approve_after_days  = 0
          // The compliance level of a patch will default to unspecified if a patch isn't applied
          compliance_level    = "CRITICAL"
          enable_non_security = false
          patch_baseline_filters = [
            {
              name   = "PRODUCT"
              values = ["RedhatEnterpriseLinux6.10", "RedhatEnterpriseLinux6.5", "RedhatEnterpriseLinux6.6", "RedhatEnterpriseLinux6.7", "RedhatEnterpriseLinux6.8", "RedhatEnterpriseLinux6.9", "RedhatEnterpriseLinux7", "RedhatEnterpriseLinux7.0", "RedhatEnterpriseLinux7.1", "RedhatEnterpriseLinux7.2", "RedhatEnterpriseLinux7.3", "RedhatEnterpriseLinux7.4", "RedhatEnterpriseLinux7.5", "RedhatEnterpriseLinux7.6", "RedhatEnterpriseLinux7.7", "RedhatEnterpriseLinux7.8", "RedhatEnterpriseLinux8", "RedhatEnterpriseLinux8.0", "RedhatEnterpriseLinux8.1", "RedhatEnterpriseLinux8.2"]
            },
            {
              name   = "CLASSIFICATION"
              values = ["Security"]
            },
            {
              name   = "SEVERITY"
              values = ["Critical"]
            }
          ]
        }
      ]
    
    }

In the parent module, I would like an output that generates a map for the baseline approval rules.. something similar to

    [
      {
        name = "product",
        valueFrom = <VALUE FROM PRODUCT IN patch_baseline_filters >,
      {
        name = "severity",
        valueFrom = <VALUE FROM SEVERITY IN patch_baseline_filters>,

      {
        name = <etc>,
        valueFrom = <ETC>
      }
    ]

I'm trying to use functions like zipmap and sort to output the values to a map, but I have had no success.

Thanks!

EDIT:

Entire RHEL resource output looks like this:

    + entire_rhel_resource = [
          + {
              + approval_rule                        = [
                  + {
                      + approve_after_days  = 0
                      + approve_until_date  = null
                      + compliance_level    = "CRITICAL"
                      + enable_non_security = false
                      + patch_filter        = [
                          + {
                              + key    = "PRODUCT"
                              + values = [
                                  + "RedhatEnterpriseLinux6.10",
                                  + "RedhatEnterpriseLinux6.5",
                                  + "RedhatEnterpriseLinux6.6",
                                  + "RedhatEnterpriseLinux6.7",
                                  + "RedhatEnterpriseLinux6.8",
                                  + "RedhatEnterpriseLinux6.9",
                                  + "RedhatEnterpriseLinux7",
                                  + "RedhatEnterpriseLinux7.0",
                                  + "RedhatEnterpriseLinux7.1",
                                  + "RedhatEnterpriseLinux7.2",
                                  + "RedhatEnterpriseLinux7.3",
                                  + "RedhatEnterpriseLinux7.4",
                                  + "RedhatEnterpriseLinux7.5",
                                  + "RedhatEnterpriseLinux7.6",
                                  + "RedhatEnterpriseLinux7.7",
                                  + "RedhatEnterpriseLinux7.8",
                                  + "RedhatEnterpriseLinux8",
                                  + "RedhatEnterpriseLinux8.0",
                                  + "RedhatEnterpriseLinux8.1",
                                  + "RedhatEnterpriseLinux8.2",
                                ]
                            },
                          + {
                              + key    = "CLASSIFICATION"
                              + values = [
                                  + "Security",
                                ]
                            },
                          + {
                              + key    = "SEVERITY"
                              + values = [
                                  + "Critical",
                                ]
                            },
                        ]
                    },
                ]
              + approved_patches                     = null
              + approved_patches_compliance_level    = "UNSPECIFIED"
              + approved_patches_enable_non_security = null
              + arn                                  = (known after apply)
              + description                          = "RedHat Enterprise Linux Default Patch Baseline"
              + global_filter                        = []
              + id                                   = (known after apply)
              + name                                 = "SENSITIVEredhat_enterprise_linux-baseline"
              + operating_system                     = "REDHAT_ENTERPRISE_LINUX"
              + rejected_patches                     = null
              + rejected_patches_action              = (known after apply)
              + source                               = []
              + tags                                 = {
                  + "Name"      = "SENSITIVEredhat_enterprise_linux"
                  + "owner"     = "SENSITIVE"
                  + "team"      = "SENSITIVE"
                  + "terraform" = "true"
                }
              + tags_all                             = {
                  + "Name"      = "SENSITIVEredhat_enterprise_linux"
                  + "owner"     = "SENSITIVE"
                  + "team"      = "SENSITIVE"
                  + "terraform" = "true"
                }
            },
        ]

Solution

  • Here is the best I could come up with:

    output "rhel_server_types" {
      description = "types of patches applied for rhel systems"
      value       = [for i in aws_ssm_patch_baseline.baseline.approval_rule[0].patch_filter : {
        name      = lower(i.key)
        valueFrom = i.values
      }]
    }