tenable / terrascan

Detect compliance and security violations across Infrastructure as Code to mitigate risk before provisioning cloud native infrastructure.

Home Page:https://runterrascan.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

AC_AZURE_0356 (subnets must have NSGs assigned) being triggered when using complex input types

adhodgson1 opened this issue · comments

  • terrascan version: 1.18.0
  • Operating System: Windows 11

Description

I have a complex vnet module which can create multiple subnets and NSGs and this module is triggering the accurics.azure.NS.161 policy violation. I also have noted similar behaviour to that found in #1453 whereby the inbound SSH any rule isn't being caught, however in my case its because the rule is defined in a complex input type. I don't know if I am asking too much here or whether anything can be done about it. Here is some example code to reproduce the issue:

locals {
  nsg_rule_list = flatten([
    for nsg_name, nsg in local.network_security_groups : [
      for rule_name, rule in lookup(nsg, "rules", {}) : merge(rule, {
        nsg_name = nsg_name
        name     = rule_name
      })
    ]
  ])
  subnets = {
    subnet1 = {
      address_prefixes          = ["172.16.1.0/25"]
      network_security_group_id = "subnet1-nsg"
    }
  }
  network_security_groups = {
    subnet1-nsg = {
      rules = {
        "inbound ssh" = {
          description                = "Allow inbound SSH traffic"
          priority                   = 100
          direction                  = "Inbound"
          access                     = "Allow"
          protocol                   = "Tcp"
          source_port_range          = "*"
          destination_port_range     = "22"
          source_address_prefix      = "*"
          destination_address_prefix = "*"
        }
      }
    }
  }
}

resource "azurerm_resource_group" "rg" {
  name     = "test-rg"
  location = "uksouth"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "test-vnet"
  address_space       = ["172.16.1.0/24"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "subnet" {
  for_each             = { for subnet_name, subnet in local.subnets : subnet_name => subnet }
  name                 = each.key
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = each.value.address_prefixes
}

resource "azurerm_network_security_group" "nsg" {
  for_each            = local.network_security_groups
  name                = each.key
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_network_security_rule" "nsg_rule" {
  for_each                     = { for nsg in local.nsg_rule_list : "${nsg.nsg_name}_${nsg.name}" => nsg }
  name                         = each.value.name
  description                  = lookup(each.value, "description", null)
  resource_group_name          = azurerm_resource_group.rg.name
  network_security_group_name  = azurerm_network_security_group.nsg[each.value.nsg_name].name
  priority                     = each.value.priority
  direction                    = each.value.direction
  access                       = each.value.access
  protocol                     = each.value.protocol
  source_port_range            = lookup(each.value, "source_port_range", null)
  source_port_ranges           = lookup(each.value, "source_port_ranges", null)
  destination_port_range       = lookup(each.value, "destination_port_range", null)
  destination_port_ranges      = lookup(each.value, "destination_port_ranges", null)
  source_address_prefix        = lookup(each.value, "source_address_prefix", null)
  source_address_prefixes      = lookup(each.value, "source_address_prefixes", null)
  destination_address_prefix   = lookup(each.value, "destination_address_prefix", null)
  destination_address_prefixes = lookup(each.value, "destination_address_prefixes", null)
}

resource "azurerm_subnet_network_security_group_association" "nsg_association" {
  for_each                  = { for subnet_name, subnet in local.subnets : subnet_name => subnet if lookup(subnet, "network_security_group", "") != "" }
  subnet_id                 = azurerm_subnet.subnet[each.key].id
  network_security_group_id = azurerm_network_security_group.nsg[each.value.network_security_group].id
}

What I Did

terrascan scan

Violation Details -
    
	Description    :	Ensure that Azure Virtual Network subnet is configured with a Network Security Group
	File           :	main.tf
	Module Name    :	root
	Plan Root      :	.\
	Line           :	47
	Severity       :	MEDIUM
	
	-----------------------------------------------------------------------
	
	Description    :	Ensure that Azure Resource Group has resource lock enabled
	File           :	main.tf
	Module Name    :	root
	Plan Root      :	.\
	Line           :	35
	Severity       :	LOW
	
	-----------------------------------------------------------------------
	

Scan Summary -

	File/Folder         :	C:\work\network-test
	IaC Type            :	terraform
	Scanned At          :	2023-02-24 12:30:17.2441648 +0000 UTC
	Policies Validated  :	131
	Violated Policies   :	2
	Low                 :	1
	Medium              :	1
	High                :	0