github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/test/count_test.go (about)

     1  package test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/aquasecurity/defsec/pkg/providers"
     7  	"github.com/aquasecurity/defsec/pkg/rules"
     8  	"github.com/aquasecurity/defsec/pkg/scan"
     9  	"github.com/aquasecurity/defsec/pkg/severity"
    10  	"github.com/aquasecurity/defsec/pkg/terraform"
    11  	"github.com/stretchr/testify/assert"
    12  
    13  	"github.com/aquasecurity/trivy-iac/test/testutil"
    14  )
    15  
    16  func Test_ResourcesWithCount(t *testing.T) {
    17  	var tests = []struct {
    18  		name            string
    19  		source          string
    20  		expectedResults int
    21  	}{
    22  		{
    23  			name: "unspecified count defaults to 1",
    24  			source: `
    25  			resource "bad" "this" {}
    26  `,
    27  			expectedResults: 1,
    28  		},
    29  		{
    30  			name: "count is literal 1",
    31  			source: `
    32  			resource "bad" "this" {
    33  				count = 1
    34  			}
    35  `,
    36  			expectedResults: 1,
    37  		},
    38  		{
    39  			name: "count is literal 99",
    40  			source: `
    41  			resource "bad" "this" {
    42  				count = 99
    43  			}
    44  `,
    45  			expectedResults: 99,
    46  		},
    47  		{
    48  			name: "count is literal 0",
    49  			source: `
    50  			resource "bad" "this" {
    51  				count = 0
    52  			}
    53  `,
    54  			expectedResults: 0,
    55  		},
    56  		{
    57  			name: "count is 0 from variable",
    58  			source: `
    59  			variable "count" {
    60  				default = 0
    61  			}
    62  			resource "bad" "this" {
    63  				count = var.count
    64  			}
    65  `,
    66  			expectedResults: 0,
    67  		},
    68  		{
    69  			name: "count is 1 from variable",
    70  			source: `
    71  			variable "count" {
    72  				default = 1
    73  			}
    74  			resource "bad" "this" {
    75  				count =  var.count
    76  			}
    77  `,
    78  			expectedResults: 1,
    79  		},
    80  		{
    81  			name: "count is 1 from variable without default",
    82  			source: `
    83  			variable "count" {
    84  			}
    85  			resource "bad" "this" {
    86  				count =  var.count
    87  			}
    88  `,
    89  			expectedResults: 1,
    90  		},
    91  		{
    92  			name: "count is 0 from conditional",
    93  			source: `
    94  			variable "enabled" {
    95  				default = false
    96  			}
    97  			resource "bad" "this" {
    98  				count = var.enabled ? 1 : 0
    99  			}
   100  `,
   101  			expectedResults: 0,
   102  		},
   103  		{
   104  			name: "count is 1 from conditional",
   105  			source: `
   106  			variable "enabled" {
   107  				default = true
   108  			}
   109  			resource "bad" "this" {
   110  				count = var.enabled ? 1 : 0
   111  			}
   112  `,
   113  			expectedResults: 1,
   114  		},
   115  		{
   116  			name: "issue 962",
   117  			source: `
   118  			resource "something" "else" {
   119  				count = 2
   120  				ok = true
   121  			}
   122  
   123  			resource "bad" "bad" {
   124  				secure = something.else[0].ok
   125  			}	
   126  `,
   127  			expectedResults: 0,
   128  		},
   129  		{
   130  			name: "Test use of count.index",
   131  			source: `
   132  resource "bad" "thing" {
   133  	count = 1
   134  	secure = var.things[count.index]["ok"]
   135  }
   136  	
   137  variable "things" {
   138  	description = "A list of maps that creates a number of sg"
   139  	type = list(map(string))
   140  	
   141  	default = [
   142  		{
   143  			ok = true
   144  		}
   145  	]
   146  }
   147  			`,
   148  			expectedResults: 0,
   149  		},
   150  	}
   151  
   152  	for _, test := range tests {
   153  		t.Run(test.name, func(t *testing.T) {
   154  			r1 := scan.Rule{
   155  				Provider:  providers.AWSProvider,
   156  				Service:   "service",
   157  				ShortCode: "abc123",
   158  				Severity:  severity.High,
   159  				CustomChecks: scan.CustomChecks{
   160  					Terraform: &scan.TerraformCustomCheck{
   161  						RequiredLabels: []string{"bad"},
   162  						Check: func(resourceBlock *terraform.Block, _ *terraform.Module) (results scan.Results) {
   163  							if resourceBlock.GetAttribute("secure").IsTrue() {
   164  								return
   165  							}
   166  							results.Add(
   167  								"example problem",
   168  								resourceBlock,
   169  							)
   170  							return
   171  						},
   172  					},
   173  				},
   174  			}
   175  			reg := rules.Register(r1)
   176  			defer rules.Deregister(reg)
   177  			results := scanHCL(t, test.source)
   178  			var include string
   179  			var exclude string
   180  			if test.expectedResults > 0 {
   181  				include = r1.LongID()
   182  			} else {
   183  				exclude = r1.LongID()
   184  			}
   185  			assert.Equal(t, test.expectedResults, len(results.GetFailed()))
   186  			if include != "" {
   187  				testutil.AssertRuleFound(t, include, results, "false negative found")
   188  			}
   189  			if exclude != "" {
   190  				testutil.AssertRuleNotFound(t, exclude, results, "false positive found")
   191  			}
   192  		})
   193  	}
   194  }