Repository: liamg/tfsec
Pull request #101 (2020-04-05 09:18:10)

Ensure ecr repository image scans are enabled
Adding check for ECR image scan enabled or disabled
#36 


Patch:
diff --git a/internal/app/tfsec/checks/aws_ecr_image_scan.go b/internal/app/tfsec/checks/aws_ecr_image_scan.go
new file mode 100644
index 000000000..39f761327
--- /dev/null
+++ b/internal/app/tfsec/checks/aws_ecr_image_scan.go
@@ -0,0 +1,47 @@
+package checks
+
+import (
+	"fmt"
+
+	"github.com/zclconf/go-cty/cty"
+
+	"github.com/liamg/tfsec/internal/app/tfsec/scanner"
+
+	"github.com/liamg/tfsec/internal/app/tfsec/parser"
+)
+
+// AWSEcrImageScanNotEnabled See https://github.com/liamg/tfsec#included-checks for check info
+const AWSEcrImageScanNotEnabled scanner.RuleID = "AWS023"
+
+func init() {
+	scanner.RegisterCheck(scanner.Check{
+		Code:           AWSEcrImageScanNotEnabled,
+		RequiredTypes:  []string{"resource"},
+		RequiredLabels: []string{"aws_ecr_repository"},
+		CheckFunc: func(check *scanner.Check, block *parser.Block, context *scanner.Context) []scanner.Result {
+
+			ecrScanStatusBlock := block.GetBlock("image_scanning_configuration")
+			ecrScanStatusAttr := ecrScanStatusBlock.GetAttribute("scan_on_push")
+
+			if ecrScanStatusAttr == nil  {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' defines a disabled ECR image scan.", block.Name()),
+						block.Range(),
+						scanner.SeverityError,
+					),
+				}
+			} else if ecrScanStatusAttr.Type() == cty.Bool && ecrScanStatusAttr.Value().False() {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' defines a disabled ECR image scan.", block.Name()),
+						ecrScanStatusAttr.Range(),
+						ecrScanStatusAttr,
+						scanner.SeverityError,
+					),
+				}
+			}
+			return nil
+		},
+	})
+}


Test patch:
diff --git a/internal/app/tfsec/aws_no_ecr_repository_scan_test.go b/internal/app/tfsec/aws_no_ecr_repository_scan_test.go
new file mode 100644
index 000000000..9e3b3873f
--- /dev/null
+++ b/internal/app/tfsec/aws_no_ecr_repository_scan_test.go
@@ -0,0 +1,57 @@
+package tfsec
+
+import (
+	"testing"
+
+	"github.com/liamg/tfsec/internal/app/tfsec/scanner"
+
+	"github.com/liamg/tfsec/internal/app/tfsec/checks"
+)
+
+func Test_AWSEcrImageScanNotEnabled(t *testing.T) {
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode scanner.RuleID
+		mustExcludeResultCode scanner.RuleID
+	}{
+		{
+			name:                  "check KMS Key with auto-rotation not set",
+			source:                `resource "aws_ecr_repository" "foo" {}`,
+			mustIncludeResultCode: checks.AWSEcrImageScanNotEnabled,
+		},
+		{
+			name: "check ECR Image Scan disabled",
+			source: `
+resource "aws_ecr_repository" "foo" {
+  name                 = "bar"
+  image_tag_mutability = "MUTABLE"
+
+  image_scanning_configuration {
+    scan_on_push = false
+  }
+}`,
+			mustIncludeResultCode: checks.AWSEcrImageScanNotEnabled,
+		},
+		{
+			name: "check ECR Image Scan disabled",
+			source: `
+resource "aws_ecr_repository" "foo" {
+  name                 = "bar"
+  image_tag_mutability = "MUTABLE"
+
+  image_scanning_configuration {
+    scan_on_push = true
+  }
+}`,
+			mustExcludeResultCode: checks.AWSEcrImageScanNotEnabled,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			results := scanSource(test.source)
+			assertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+}