github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/test/ignore_test.go (about) 1 package test 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/khulnasoft-lab/defsec/pkg/terraform" 8 9 "github.com/khulnasoft-lab/defsec/pkg/severity" 10 11 "github.com/khulnasoft-lab/defsec/pkg/scan" 12 13 "github.com/khulnasoft-lab/defsec/internal/rules" 14 15 "github.com/khulnasoft-lab/defsec/pkg/providers" 16 17 "github.com/stretchr/testify/assert" 18 ) 19 20 var exampleRule = scan.Rule{ 21 Provider: providers.AWSProvider, 22 Service: "service", 23 ShortCode: "abc123", 24 Aliases: []string{"aws-other-abc123"}, 25 Severity: severity.High, 26 CustomChecks: scan.CustomChecks{ 27 Terraform: &scan.TerraformCustomCheck{ 28 RequiredLabels: []string{"bad"}, 29 Check: func(resourceBlock *terraform.Block, _ *terraform.Module) (results scan.Results) { 30 attr := resourceBlock.GetAttribute("secure") 31 if attr.IsNil() { 32 results.Add("example problem", resourceBlock) 33 } 34 if attr.IsFalse() { 35 results.Add("example problem", attr) 36 } 37 return 38 }, 39 }, 40 }, 41 } 42 43 func Test_IgnoreAll(t *testing.T) { 44 45 var testCases = []struct { 46 name string 47 inputOptions string 48 assertLength int 49 }{ 50 {name: "IgnoreAll", inputOptions: ` 51 resource "bad" "my-rule" { 52 secure = false // terrasec:ignore:* 53 } 54 `, assertLength: 0}, 55 {name: "IgnoreLineAboveTheBlock", inputOptions: ` 56 // terrasec:ignore:* 57 resource "bad" "my-rule" { 58 secure = false 59 } 60 `, assertLength: 0}, 61 {name: "IgnoreLineAboveTheBlockMatchingParamBool", inputOptions: ` 62 // terrasec:ignore:*[secure=false] 63 resource "bad" "my-rule" { 64 secure = false 65 } 66 `, assertLength: 0}, 67 {name: "IgnoreLineAboveTheBlockNotMatchingParamBool", inputOptions: ` 68 // terrasec:ignore:*[secure=true] 69 resource "bad" "my-rule" { 70 secure = false 71 } 72 `, assertLength: 1}, 73 {name: "IgnoreLineAboveTheBlockMatchingParamString", inputOptions: ` 74 // terrasec:ignore:*[name=myrule] 75 resource "bad" "my-rule" { 76 name = "myrule" 77 secure = false 78 } 79 `, assertLength: 0}, 80 {name: "IgnoreLineAboveTheBlockNotMatchingParamString", inputOptions: ` 81 // terrasec:ignore:*[name=myrule2] 82 resource "bad" "my-rule" { 83 name = "myrule" 84 secure = false 85 } 86 `, assertLength: 1}, 87 {name: "IgnoreLineAboveTheBlockMatchingParamInt", inputOptions: ` 88 // terrasec:ignore:*[port=123] 89 resource "bad" "my-rule" { 90 secure = false 91 port = 123 92 } 93 `, assertLength: 0}, 94 {name: "IgnoreLineAboveTheBlockNotMatchingParamInt", inputOptions: ` 95 // terrasec:ignore:*[port=456] 96 resource "bad" "my-rule" { 97 secure = false 98 port = 123 99 } 100 `, assertLength: 1}, 101 {name: "IgnoreLineStackedAboveTheBlock", inputOptions: ` 102 // terrasec:ignore:* 103 // terrasec:ignore:a 104 // terrasec:ignore:b 105 // terrasec:ignore:c 106 // terrasec:ignore:d 107 resource "bad" "my-rule" { 108 secure = false 109 } 110 `, assertLength: 0}, 111 {name: "IgnoreLineStackedAboveTheBlockWithoutMatch", inputOptions: ` 112 #terrasec:ignore:* 113 114 #terrasec:ignore:x 115 #terrasec:ignore:a 116 #terrasec:ignore:b 117 #terrasec:ignore:c 118 #terrasec:ignore:d 119 resource "bad" "my-rule" { 120 secure = false 121 } 122 `, assertLength: 1}, 123 {name: "IgnoreLineStackedAboveTheBlockWithHashesWithoutSpaces", inputOptions: ` 124 #terrasec:ignore:* 125 #terrasec:ignore:a 126 #terrasec:ignore:b 127 #terrasec:ignore:c 128 #terrasec:ignore:d 129 resource "bad" "my-rule" { 130 secure = false 131 } 132 `, assertLength: 0}, 133 {name: "IgnoreLineStackedAboveTheBlockWithoutSpaces", inputOptions: ` 134 //terrasec:ignore:* 135 //terrasec:ignore:a 136 //terrasec:ignore:b 137 //terrasec:ignore:c 138 //terrasec:ignore:d 139 resource "bad" "my-rule" { 140 secure = false 141 } 142 `, assertLength: 0}, 143 {name: "IgnoreLineAboveTheLine", inputOptions: ` 144 resource "bad" "my-rule" { 145 # terrasec:ignore:aws-service-abc123 146 secure = false 147 } 148 `, assertLength: 0}, 149 {name: "IgnoreWithExpDateIfDateBreachedThenDontIgnore", inputOptions: ` 150 resource "bad" "my-rule" { 151 secure = false # terrasec:ignore:aws-service-abc123:exp:2000-01-02 152 } 153 `, assertLength: 1}, 154 {name: "IgnoreWithExpDateIfDateNotBreachedThenIgnoreIgnore", inputOptions: ` 155 resource "bad" "my-rule" { 156 secure = false # terrasec:ignore:aws-service-abc123:exp:2221-01-02 157 } 158 `, assertLength: 0}, 159 {name: "IgnoreWithExpDateIfDateInvalidThenDropTheIgnore", inputOptions: ` 160 resource "bad" "my-rule" { 161 secure = false # terrasec:ignore:aws-service-abc123:exp:2221-13-02 162 } 163 `, assertLength: 1}, 164 {name: "IgnoreAboveResourceBlockWithExpDateIfDateNotBreachedThenIgnoreIgnore", inputOptions: ` 165 #terrasec:ignore:aws-service-abc123:exp:2221-01-02 166 resource "bad" "my-rule" { 167 } 168 `, assertLength: 0}, 169 {name: "IgnoreAboveResourceBlockWithExpDateAndMultipleIgnoresIfDateNotBreachedThenIgnoreIgnore", inputOptions: ` 170 # terrasec:ignore:aws-service-abc123:exp:2221-01-02 171 resource "bad" "my-rule" { 172 173 } 174 `, assertLength: 0}, 175 {name: "IgnoreForImpliedIAMResource", inputOptions: ` 176 terraform { 177 required_version = "~> 1.1.6" 178 179 required_providers { 180 aws = { 181 source = "hashicorp/aws" 182 version = "~> 3.48" 183 } 184 } 185 } 186 187 # Retrieve an IAM group defined outside of this Terraform config. 188 189 # terrasec:ignore:aws-iam-enforce-mfa 190 data "aws_iam_group" "externally_defined_group" { 191 group_name = "group-name" # terrasec:ignore:aws-iam-enforce-mfa 192 } 193 194 # Create an IAM policy and attach it to the group. 195 196 # terrasec:ignore:aws-iam-enforce-mfa 197 resource "aws_iam_policy" "test_policy" { 198 name = "test-policy" # terrasec:ignore:aws-iam-enforce-mfa 199 policy = data.aws_iam_policy_document.test_policy.json # terrasec:ignore:aws-iam-enforce-mfa 200 } 201 202 # terrasec:ignore:aws-iam-enforce-mfa 203 resource "aws_iam_group_policy_attachment" "test_policy_attachment" { 204 group = data.aws_iam_group.externally_defined_group.group_name # terrasec:ignore:aws-iam-enforce-mfa 205 policy_arn = aws_iam_policy.test_policy.arn # terrasec:ignore:aws-iam-enforce-mfa 206 } 207 208 # terrasec:ignore:aws-iam-enforce-mfa 209 data "aws_iam_policy_document" "test_policy" { 210 statement { 211 sid = "PublishToCloudWatch" # terrasec:ignore:aws-iam-enforce-mfa 212 actions = [ 213 "cloudwatch:PutMetricData", # terrasec:ignore:aws-iam-enforce-mfa 214 ] 215 resources = ["*"] # terrasec:ignore:aws-iam-enforce-mfa 216 } 217 } 218 `, assertLength: 0}, 219 {name: "VulIgnoreAll", inputOptions: ` 220 resource "bad" "my-rule" { 221 secure = false // vul:ignore:* 222 } 223 `, assertLength: 0}, 224 {name: "VulIgnoreLineAboveTheBlock", inputOptions: ` 225 // vul:ignore:* 226 resource "bad" "my-rule" { 227 secure = false 228 } 229 `, assertLength: 0}, 230 {name: "VulIgnoreLineAboveTheBlockMatchingParamBool", inputOptions: ` 231 // vul:ignore:*[secure=false] 232 resource "bad" "my-rule" { 233 secure = false 234 } 235 `, assertLength: 0}, 236 {name: "VulIgnoreLineAboveTheBlockNotMatchingParamBool", inputOptions: ` 237 // vul:ignore:*[secure=true] 238 resource "bad" "my-rule" { 239 secure = false 240 } 241 `, assertLength: 1}, 242 {name: "VulIgnoreLineAboveTheBlockMatchingParamString", inputOptions: ` 243 // vul:ignore:*[name=myrule] 244 resource "bad" "my-rule" { 245 name = "myrule" 246 secure = false 247 } 248 `, assertLength: 0}, 249 {name: "VulIgnoreLineAboveTheBlockNotMatchingParamString", inputOptions: ` 250 // vul:ignore:*[name=myrule2] 251 resource "bad" "my-rule" { 252 name = "myrule" 253 secure = false 254 } 255 `, assertLength: 1}, 256 {name: "VulIgnoreLineAboveTheBlockMatchingParamInt", inputOptions: ` 257 // vul:ignore:*[port=123] 258 resource "bad" "my-rule" { 259 secure = false 260 port = 123 261 } 262 `, assertLength: 0}, 263 {name: "VulIgnoreLineAboveTheBlockNotMatchingParamInt", inputOptions: ` 264 // vul:ignore:*[port=456] 265 resource "bad" "my-rule" { 266 secure = false 267 port = 123 268 } 269 `, assertLength: 1}, 270 {name: "VulIgnoreLineStackedAboveTheBlock", inputOptions: ` 271 // vul:ignore:* 272 // vul:ignore:a 273 // vul:ignore:b 274 // vul:ignore:c 275 // vul:ignore:d 276 resource "bad" "my-rule" { 277 secure = false 278 } 279 `, assertLength: 0}, 280 {name: "VulIgnoreLineStackedAboveTheBlockWithoutMatch", inputOptions: ` 281 #vul:ignore:* 282 283 #vul:ignore:x 284 #vul:ignore:a 285 #vul:ignore:b 286 #vul:ignore:c 287 #vul:ignore:d 288 resource "bad" "my-rule" { 289 secure = false 290 } 291 `, assertLength: 1}, 292 {name: "VulIgnoreLineStackedAboveTheBlockWithHashesWithoutSpaces", inputOptions: ` 293 #vul:ignore:* 294 #vul:ignore:a 295 #vul:ignore:b 296 #vul:ignore:c 297 #vul:ignore:d 298 resource "bad" "my-rule" { 299 secure = false 300 } 301 `, assertLength: 0}, 302 {name: "VulIgnoreLineStackedAboveTheBlockWithoutSpaces", inputOptions: ` 303 //vul:ignore:* 304 //vul:ignore:a 305 //vul:ignore:b 306 //vul:ignore:c 307 //vul:ignore:d 308 resource "bad" "my-rule" { 309 secure = false 310 } 311 `, assertLength: 0}, 312 {name: "VulIgnoreLineAboveTheLine", inputOptions: ` 313 resource "bad" "my-rule" { 314 # vul:ignore:aws-service-abc123 315 secure = false 316 } 317 `, assertLength: 0}, 318 {name: "VulIgnoreWithExpDateIfDateBreachedThenDontIgnore", inputOptions: ` 319 resource "bad" "my-rule" { 320 secure = false # vul:ignore:aws-service-abc123:exp:2000-01-02 321 } 322 `, assertLength: 1}, 323 {name: "VulIgnoreWithExpDateIfDateNotBreachedThenIgnoreIgnore", inputOptions: ` 324 resource "bad" "my-rule" { 325 secure = false # vul:ignore:aws-service-abc123:exp:2221-01-02 326 } 327 `, assertLength: 0}, 328 {name: "VulIgnoreWithExpDateIfDateInvalidThenDropTheIgnore", inputOptions: ` 329 resource "bad" "my-rule" { 330 secure = false # vul:ignore:aws-service-abc123:exp:2221-13-02 331 } 332 `, assertLength: 1}, 333 {name: "VulIgnoreAboveResourceBlockWithExpDateIfDateNotBreachedThenIgnoreIgnore", inputOptions: ` 334 #vul:ignore:aws-service-abc123:exp:2221-01-02 335 resource "bad" "my-rule" { 336 } 337 `, assertLength: 0}, 338 {name: "VulIgnoreAboveResourceBlockWithExpDateAndMultipleIgnoresIfDateNotBreachedThenIgnoreIgnore", inputOptions: ` 339 # vul:ignore:aws-service-abc123:exp:2221-01-02 340 resource "bad" "my-rule" { 341 342 } 343 `, assertLength: 0}, 344 {name: "VulIgnoreForImpliedIAMResource", inputOptions: ` 345 terraform { 346 required_version = "~> 1.1.6" 347 348 required_providers { 349 aws = { 350 source = "hashicorp/aws" 351 version = "~> 3.48" 352 } 353 } 354 } 355 356 # Retrieve an IAM group defined outside of this Terraform config. 357 358 # vul:ignore:aws-iam-enforce-mfa 359 data "aws_iam_group" "externally_defined_group" { 360 group_name = "group-name" # vul:ignore:aws-iam-enforce-mfa 361 } 362 363 # Create an IAM policy and attach it to the group. 364 365 # vul:ignore:aws-iam-enforce-mfa 366 resource "aws_iam_policy" "test_policy" { 367 name = "test-policy" # vul:ignore:aws-iam-enforce-mfa 368 policy = data.aws_iam_policy_document.test_policy.json # vul:ignore:aws-iam-enforce-mfa 369 } 370 371 # vul:ignore:aws-iam-enforce-mfa 372 resource "aws_iam_group_policy_attachment" "test_policy_attachment" { 373 group = data.aws_iam_group.externally_defined_group.group_name # vul:ignore:aws-iam-enforce-mfa 374 policy_arn = aws_iam_policy.test_policy.arn # vul:ignore:aws-iam-enforce-mfa 375 } 376 377 # vul:ignore:aws-iam-enforce-mfa 378 data "aws_iam_policy_document" "test_policy" { 379 statement { 380 sid = "PublishToCloudWatch" # vul:ignore:aws-iam-enforce-mfa 381 actions = [ 382 "cloudwatch:PutMetricData", # vul:ignore:aws-iam-enforce-mfa 383 ] 384 resources = ["*"] # vul:ignore:aws-iam-enforce-mfa 385 } 386 } 387 `, assertLength: 0}} 388 389 reg := rules.Register(exampleRule, nil) 390 defer rules.Deregister(reg) 391 392 for _, tc := range testCases { 393 t.Run(tc.name, func(t *testing.T) { 394 results := scanHCL(t, tc.inputOptions) 395 assert.Len(t, results.GetFailed(), tc.assertLength) 396 }) 397 } 398 } 399 400 func Test_IgnoreIgnoreWithExpiryAndWorkspaceAndWorkspaceSupplied(t *testing.T) { 401 reg := rules.Register(exampleRule, nil) 402 defer rules.Deregister(reg) 403 404 results := scanHCLWithWorkspace(t, ` 405 # terrasec:ignore:aws-service-abc123:exp:2221-01-02:ws:testworkspace 406 resource "bad" "my-rule" { 407 } 408 `, "testworkspace") 409 assert.Len(t, results.GetFailed(), 0) 410 } 411 412 func Test_IgnoreInline(t *testing.T) { 413 reg := rules.Register(exampleRule, nil) 414 defer rules.Deregister(reg) 415 416 results := scanHCL(t, fmt.Sprintf(` 417 resource "bad" "sample" { 418 secure = false # terrasec:ignore:%s 419 } 420 `, exampleRule.LongID())) 421 assert.Len(t, results.GetFailed(), 0) 422 } 423 424 func Test_IgnoreIgnoreWithExpiryAndWorkspaceButWrongWorkspaceSupplied(t *testing.T) { 425 reg := rules.Register(exampleRule, nil) 426 defer rules.Deregister(reg) 427 428 results := scanHCLWithWorkspace(t, ` 429 # terrasec:ignore:aws-service-abc123:exp:2221-01-02:ws:otherworkspace 430 resource "bad" "my-rule" { 431 432 } 433 `, "testworkspace") 434 assert.Len(t, results.GetFailed(), 1) 435 } 436 437 func Test_IgnoreWithAliasCodeStillIgnored(t *testing.T) { 438 reg := rules.Register(exampleRule, nil) 439 defer rules.Deregister(reg) 440 441 results := scanHCLWithWorkspace(t, ` 442 # terrasec:ignore:aws-other-abc123 443 resource "bad" "my-rule" { 444 445 } 446 `, "testworkspace") 447 assert.Len(t, results.GetFailed(), 0) 448 } 449 450 func Test_VulIgnoreIgnoreWithExpiryAndWorkspaceAndWorkspaceSupplied(t *testing.T) { 451 reg := rules.Register(exampleRule, nil) 452 defer rules.Deregister(reg) 453 454 results := scanHCLWithWorkspace(t, ` 455 # vul:ignore:aws-service-abc123:exp:2221-01-02:ws:testworkspace 456 resource "bad" "my-rule" { 457 } 458 `, "testworkspace") 459 assert.Len(t, results.GetFailed(), 0) 460 } 461 462 func Test_VulIgnoreIgnoreWithExpiryAndWorkspaceButWrongWorkspaceSupplied(t *testing.T) { 463 reg := rules.Register(exampleRule, nil) 464 defer rules.Deregister(reg) 465 466 results := scanHCLWithWorkspace(t, ` 467 # vul:ignore:aws-service-abc123:exp:2221-01-02:ws:otherworkspace 468 resource "bad" "my-rule" { 469 470 } 471 `, "testworkspace") 472 assert.Len(t, results.GetFailed(), 1) 473 } 474 475 func Test_VulIgnoreWithAliasCodeStillIgnored(t *testing.T) { 476 reg := rules.Register(exampleRule, nil) 477 defer rules.Deregister(reg) 478 479 results := scanHCLWithWorkspace(t, ` 480 # vul:ignore:aws-other-abc123 481 resource "bad" "my-rule" { 482 483 } 484 `, "testworkspace") 485 assert.Len(t, results.GetFailed(), 0) 486 } 487 488 func Test_VulIgnoreInline(t *testing.T) { 489 reg := rules.Register(exampleRule, nil) 490 defer rules.Deregister(reg) 491 492 results := scanHCL(t, fmt.Sprintf(` 493 resource "bad" "sample" { 494 secure = false # vul:ignore:%s 495 } 496 `, exampleRule.LongID())) 497 assert.Len(t, results.GetFailed(), 0) 498 }