From c544b1ae325641eba72e0c1f56319dece7e9a398 Mon Sep 17 00:00:00 2001 From: Devang Date: Mon, 14 Jun 2021 20:52:11 +0530 Subject: [PATCH 1/9] fixed incorrect file path reporting with -f flag --- pkg/utils/dir.go | 2 +- pkg/utils/file.go | 19 +++++++++++++++++++ pkg/writer/sarif.go | 12 ++++++++---- pkg/writer/sarif_test.go | 2 +- pkg/writer/test/dummy | 0 5 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 pkg/utils/file.go create mode 100644 pkg/writer/test/dummy diff --git a/pkg/utils/dir.go b/pkg/utils/dir.go index b3111385f..e10f09c54 100644 --- a/pkg/utils/dir.go +++ b/pkg/utils/dir.go @@ -30,7 +30,7 @@ func GenerateTempDir() string { func IsDirExists(dir string) bool { _, err := os.Stat(dir) if os.IsNotExist(err) { - zap.S().Debug("Directory %s does not exist.", dir) + zap.S().Errorf("Directory %s does not exist.", dir) return false } return true diff --git a/pkg/utils/file.go b/pkg/utils/file.go new file mode 100644 index 000000000..21c794347 --- /dev/null +++ b/pkg/utils/file.go @@ -0,0 +1,19 @@ +package utils + +import ( + "go.uber.org/zap" + "os" +) + +// GetFileMode fetches the filemode from a file path +func GetFileMode(path string) os.FileMode { + fi, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + zap.S().Errorf("file %s does not exist.", path) + } else { + zap.S().Errorf("unable to fetch file info for path %s.", path) + } + } + return fi.Mode() +} diff --git a/pkg/writer/sarif.go b/pkg/writer/sarif.go index 4bea5b460..18cf3322f 100644 --- a/pkg/writer/sarif.go +++ b/pkg/writer/sarif.go @@ -19,6 +19,7 @@ package writer import ( "fmt" "github.com/accurics/terrascan/pkg/policy" + "github.com/accurics/terrascan/pkg/utils" "github.com/accurics/terrascan/pkg/version" "github.com/owenrumney/go-sarif/sarif" "io" @@ -56,7 +57,7 @@ func SarifWriter(data interface{}, writer io.Writer) error { run.AddRule(string(passedRule.RuleID)). WithDescription(passedRule.Description).WithName(passedRule.RuleName).WithProperties(m) } - resourcePath := outputData.Summary.ResourcePath + // for each result add the rule, location and result to the report for _, violation := range outputData.Violations { m := make(map[string]string) @@ -66,9 +67,12 @@ func SarifWriter(data interface{}, writer io.Writer) error { rule := run.AddRule(string(violation.RuleID)). WithDescription(violation.Description).WithName(violation.RuleName).WithProperties(m) - absFilePath := violation.File - if !filepath.IsAbs(violation.File) { - absFilePath = filepath.Join(resourcePath, violation.File) + absFilePath := outputData.Summary.ResourcePath + if !filepath.IsAbs(absFilePath) { + absFilePath, _ = filepath.Abs(absFilePath) + } + if utils.GetFileMode(absFilePath).IsDir() { + absFilePath = filepath.Join(absFilePath, violation.File) } location := sarif.NewLocation(). diff --git a/pkg/writer/sarif_test.go b/pkg/writer/sarif_test.go index 4996b243a..60de456e0 100644 --- a/pkg/writer/sarif_test.go +++ b/pkg/writer/sarif_test.go @@ -48,7 +48,7 @@ var expectedSarifOutput1 = fmt.Sprintf(`{ { "physicalLocation": { "artifactLocation": { - "uri": "file://test/modules/m1/main.tf" + "uri": "file:///Users/dev-gaur/go/src/github.com/accurics/terrascan/pkg/writer/test/modules/m1/main.tf" }, "region": { "startLine": 20 diff --git a/pkg/writer/test/dummy b/pkg/writer/test/dummy new file mode 100644 index 000000000..e69de29bb From 599beda7d004eca2951bff00e80c11d7e1760f5c Mon Sep 17 00:00:00 2001 From: Devang Date: Mon, 14 Jun 2021 20:52:34 +0530 Subject: [PATCH 2/9] added tests for sarif formatted output --- .../kubernetes_ingress_sarif.txt | 55 +++++++++++ .../aws_ami_violation_sarif.txt | 55 +++++++++++ test/e2e/scan/scan_k8s_files_test.go | 95 +++++++++++++++++-- test/e2e/scan/scan_tf_files_test.go | 7 ++ 4 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 test/e2e/scan/golden/k8s_scans/k8s/kubernetes_ingress_violations/kubernetes_ingress_sarif.txt create mode 100644 test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_sarif.txt diff --git a/test/e2e/scan/golden/k8s_scans/k8s/kubernetes_ingress_violations/kubernetes_ingress_sarif.txt b/test/e2e/scan/golden/k8s_scans/k8s/kubernetes_ingress_violations/kubernetes_ingress_sarif.txt new file mode 100644 index 000000000..f243d67b5 --- /dev/null +++ b/test/e2e/scan/golden/k8s_scans/k8s/kubernetes_ingress_violations/kubernetes_ingress_sarif.txt @@ -0,0 +1,55 @@ +{ + "version": "2.1.0", + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "runs": [ + { + "tool": { + "driver": { + "name": "terrascan", + "version": "1.7.0", + "informationUri": "https://github.com/accurics/terrascan", + "rules": [ + { + "id": "AC-K8-NS-IN-H-0020", + "name": "noHttps", + "shortDescription": { + "text": "TLS disabled can affect the confidentiality of the data in transit" + }, + "properties": { + "category": "Network Security", + "severity": "HIGH" + } + } + ] + } + }, + "results": [ + { + "ruleId": "AC-K8-NS-IN-H-0020", + "level": "error", + "message": { + "text": "TLS disabled can affect the confidentiality of the data in transit" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/dev-gaur/go/src/github.com/accurics/terrascan/test/e2e/test_data/iac/k8s/kubernetes_ingress_violation/config.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "ingress-demo-disallowed", + "kind": "kubernetes_ingress" + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_sarif.txt b/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_sarif.txt new file mode 100644 index 000000000..40586c667 --- /dev/null +++ b/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_sarif.txt @@ -0,0 +1,55 @@ +{ + "version": "2.1.0", + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "runs": [ + { + "tool": { + "driver": { + "name": "terrascan", + "version": "1.7.0", + "informationUri": "https://github.com/accurics/terrascan", + "rules": [ + { + "id": "AWS.EC2.Encryption\u0026KeyManagement.Medium.0688", + "name": "amiNotEncrypted", + "shortDescription": { + "text": "Enable AWS AMI Encryption" + }, + "properties": { + "category": "Encryption \u0026 KeyManagement", + "severity": "MEDIUM" + } + } + ] + } + }, + "results": [ + { + "ruleId": "AWS.EC2.Encryption\u0026KeyManagement.Medium.0688", + "level": "warning", + "message": { + "text": "Enable AWS AMI Encryption" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///Users/dev-gaur/go/src/github.com/accurics/terrascan/test/e2e/test_data/iac/aws/aws_ami_violation/main.tf" + }, + "region": { + "startLine": 5 + } + }, + "logicalLocations": [ + { + "name": "awsAmiEncrypted", + "kind": "aws_ami" + } + ] + } + ] + } + ] + } + ] +} diff --git a/test/e2e/scan/scan_k8s_files_test.go b/test/e2e/scan/scan_k8s_files_test.go index b6c49a9e9..c2a8d8546 100644 --- a/test/e2e/scan/scan_k8s_files_test.go +++ b/test/e2e/scan/scan_k8s_files_test.go @@ -26,7 +26,7 @@ import ( "github.com/onsi/gomega/gbytes" ) -var _ = Describe("Scan is run for k8s files", func() { +var _ = Describe("Scan is run for k8s directories and files", func() { BeforeEach(func() { outWriter = gbytes.NewBuffer() @@ -38,16 +38,16 @@ var _ = Describe("Scan is run for k8s files", func() { errWriter = nil }) - Context("scan iac files violating k8s policies", func() { - var policyDir, iacDir string - policyDir, err1 := filepath.Abs(policyRootRelPath) - iacDir, err2 := filepath.Abs(filepath.Join(k8sIacRelPath, "kubernetes_ingress_violation")) + var policyDir, iacDir string + policyDir, err1 := filepath.Abs(policyRootRelPath) + iacDir, err2 := filepath.Abs(filepath.Join(k8sIacRelPath, "kubernetes_ingress_violation")) - It("should not error out while getting absolute path", func() { - Expect(err1).NotTo(HaveOccurred()) - Expect(err2).NotTo(HaveOccurred()) - }) + It("should not error out while getting absolute path", func() { + Expect(err1).NotTo(HaveOccurred()) + Expect(err2).NotTo(HaveOccurred()) + }) + Context("scan iac directories violating k8s policies", func() { Context("iac type k8s will be part of all iac", func() { When("k8s files are scanned but iac type is not specified", func() { It("should scan will all iac and display violations", func() { @@ -74,6 +74,13 @@ var _ = Describe("Scan is run for k8s files", func() { }) }) + When("when output type is sarif", func() { + It("should display violations in sarif format", func() { + scanArgs := []string{"-i", "k8s", "-p", policyDir, "-d", iacDir, "-o", "sarif"} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_sarif.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + When("when output type is json", func() { It("should display violations in json format", func() { scanArgs := []string{"-i", "k8s", "-p", policyDir, "-d", iacDir, "-o", "json"} @@ -103,4 +110,74 @@ var _ = Describe("Scan is run for k8s files", func() { }) }) }) + + Context("scan iac files violating k8s policies", func() { + iacFile := filepath.Join(iacDir, "config.yaml") + It("should not error out while getting absolute path", func() { + Expect(err1).NotTo(HaveOccurred()) + Expect(err2).NotTo(HaveOccurred()) + }) + + Context("iac type k8s will be part of all iac", func() { + When("k8s files are scanned but iac type is not specified", func() { + It("should scan will all iac and display violations", func() { + scanArgs := []string{scanUtils.ScanCommand, "-f", iacFile} + session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, scanArgs...) + // exit code is 3 because iac files in directory has violations + helper.ValidateExitCode(session, scanUtils.ScanTimeout, helper.ExitCodeThree) + }) + }) + }) + + k8sGoldenRelPath := filepath.Join("golden", "k8s_scans", "k8s", "kubernetes_ingress_violations") + + Context("iac type is specified as k8s", func() { + It("should scan and display violations in human output format", func() { + scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_human.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + + When("-v flag is used for verbose output", func() { + It("should display verbose output for human output format", func() { + scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile, "-v"} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_human_verbose.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + + When("when output type is sarif", func() { + It("should display violations in sarif format", func() { + scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile, "-o", "sarif"} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_sarif.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + + When("when output type is json", func() { + It("should display violations in json format", func() { + scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile, "-o", "json"} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_json.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + + When("when output type is yaml", func() { + It("should display violations in yaml format", func() { + scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile, "-o", "yaml"} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_yaml.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + + When("when output type is xml", func() { + It("should display violations in xml format", func() { + scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile, "-o", "xml"} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_xml.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + + When("when output type is junit-xml", func() { + It("should display violations in junit-xml format", func() { + scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile, "-o", "junit-xml"} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_junit_xml.txt"), helper.ExitCodeThree, true, true, outWriter, errWriter, scanArgs...) + }) + }) + }) + }) }) diff --git a/test/e2e/scan/scan_tf_files_test.go b/test/e2e/scan/scan_tf_files_test.go index d2308b9a7..db844a18e 100644 --- a/test/e2e/scan/scan_tf_files_test.go +++ b/test/e2e/scan/scan_tf_files_test.go @@ -117,6 +117,13 @@ var _ = Describe("Scan is run for terraform files", func() { }) }) + When("output type is sarif", func() { + It("should display violations in sarif format", func() { + scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "-o", "sarif"} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(tfAwsAmiGoldenRelPath, "aws_ami_violation_sarif.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + When("output type is json and no iac type is specified", func() { Context("when iac type is not specified and a directory is specified, it will be scanned will all iac providers", func() { It("should display violations in json format, and should have iac type as 'all'", func() { From f6b03f4ed5b624a8c3f0447ae07fd17951e62d52 Mon Sep 17 00:00:00 2001 From: Devang Date: Mon, 14 Jun 2021 21:37:02 +0530 Subject: [PATCH 3/9] fixed filepath hardcoding in unit test --- pkg/writer/sarif.go | 18 +++++++++++------- pkg/writer/sarif_test.go | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pkg/writer/sarif.go b/pkg/writer/sarif.go index 18cf3322f..16116f77c 100644 --- a/pkg/writer/sarif.go +++ b/pkg/writer/sarif.go @@ -67,13 +67,7 @@ func SarifWriter(data interface{}, writer io.Writer) error { rule := run.AddRule(string(violation.RuleID)). WithDescription(violation.Description).WithName(violation.RuleName).WithProperties(m) - absFilePath := outputData.Summary.ResourcePath - if !filepath.IsAbs(absFilePath) { - absFilePath, _ = filepath.Abs(absFilePath) - } - if utils.GetFileMode(absFilePath).IsDir() { - absFilePath = filepath.Join(absFilePath, violation.File) - } + absFilePath := getAbsoluteFilePath(outputData.Summary.ResourcePath, violation.File) location := sarif.NewLocation(). WithPhysicalLocation(sarif.NewPhysicalLocation(). @@ -103,3 +97,13 @@ func getSarifLevel(severity string) string { return m[strings.ToLower(severity)] } + +func getAbsoluteFilePath(resourcePath, filePath string) string { + if !filepath.IsAbs(resourcePath) { + resourcePath, _ = filepath.Abs(resourcePath) + } + if utils.GetFileMode(resourcePath).IsDir() { + return filepath.Join(resourcePath, filePath) + } + return resourcePath +} diff --git a/pkg/writer/sarif_test.go b/pkg/writer/sarif_test.go index 60de456e0..71a7043df 100644 --- a/pkg/writer/sarif_test.go +++ b/pkg/writer/sarif_test.go @@ -48,7 +48,7 @@ var expectedSarifOutput1 = fmt.Sprintf(`{ { "physicalLocation": { "artifactLocation": { - "uri": "file:///Users/dev-gaur/go/src/github.com/accurics/terrascan/pkg/writer/test/modules/m1/main.tf" + "uri": "%s" }, "region": { "startLine": 20 @@ -66,7 +66,7 @@ var expectedSarifOutput1 = fmt.Sprintf(`{ ] } ] - }`, version.GetNumeric()) + }`, version.GetNumeric(), fmt.Sprintf("file://%s", getAbsoluteFilePath(violationsInput.Summary.ResourcePath, violationsInput.Violations[0].File))) var expectedSarifOutput2 = fmt.Sprintf(`{ "version": "2.1.0", From 83a4c5301ad5453ef6bcb981e38579d6f9641f46 Mon Sep 17 00:00:00 2001 From: Devang Date: Mon, 14 Jun 2021 23:16:53 +0530 Subject: [PATCH 4/9] fixed tests --- go.sum | 3 + .../kubernetes_ingress_sarif.txt | 55 -------- .../aws_ami_violation_sarif.txt | 55 -------- test/e2e/scan/scan_k8s_files_test.go | 7 +- test/e2e/scan/scan_tf_files_test.go | 4 +- test/e2e/scan/scan_utils.go | 130 ++++++++++++++++++ test/helper/helper.go | 37 +++++ 7 files changed, 178 insertions(+), 113 deletions(-) delete mode 100644 test/e2e/scan/golden/k8s_scans/k8s/kubernetes_ingress_violations/kubernetes_ingress_sarif.txt delete mode 100644 test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_sarif.txt diff --git a/go.sum b/go.sum index 6bc42f736..f6edb1f9f 100644 --- a/go.sum +++ b/go.sum @@ -1177,8 +1177,11 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b h1:qh4f65QIVFjq9eBURLEYWqaEXmOyqdUyiBSgaXWccWk= golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +<<<<<<< HEAD golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 h1:C+AwYEtBp/VQwoLntUmQ/yx3MS9vmZaKNdw5eOpoQe8= golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +======= +>>>>>>> fixed tests golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 h1:faDu4veV+8pcThn4fewv6TVlNCezafGoC1gM/mxQLbQ= golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/test/e2e/scan/golden/k8s_scans/k8s/kubernetes_ingress_violations/kubernetes_ingress_sarif.txt b/test/e2e/scan/golden/k8s_scans/k8s/kubernetes_ingress_violations/kubernetes_ingress_sarif.txt deleted file mode 100644 index f243d67b5..000000000 --- a/test/e2e/scan/golden/k8s_scans/k8s/kubernetes_ingress_violations/kubernetes_ingress_sarif.txt +++ /dev/null @@ -1,55 +0,0 @@ -{ - "version": "2.1.0", - "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", - "runs": [ - { - "tool": { - "driver": { - "name": "terrascan", - "version": "1.7.0", - "informationUri": "https://github.com/accurics/terrascan", - "rules": [ - { - "id": "AC-K8-NS-IN-H-0020", - "name": "noHttps", - "shortDescription": { - "text": "TLS disabled can affect the confidentiality of the data in transit" - }, - "properties": { - "category": "Network Security", - "severity": "HIGH" - } - } - ] - } - }, - "results": [ - { - "ruleId": "AC-K8-NS-IN-H-0020", - "level": "error", - "message": { - "text": "TLS disabled can affect the confidentiality of the data in transit" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "file:///Users/dev-gaur/go/src/github.com/accurics/terrascan/test/e2e/test_data/iac/k8s/kubernetes_ingress_violation/config.yaml" - }, - "region": { - "startLine": 1 - } - }, - "logicalLocations": [ - { - "name": "ingress-demo-disallowed", - "kind": "kubernetes_ingress" - } - ] - } - ] - } - ] - } - ] -} diff --git a/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_sarif.txt b/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_sarif.txt deleted file mode 100644 index 40586c667..000000000 --- a/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_sarif.txt +++ /dev/null @@ -1,55 +0,0 @@ -{ - "version": "2.1.0", - "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", - "runs": [ - { - "tool": { - "driver": { - "name": "terrascan", - "version": "1.7.0", - "informationUri": "https://github.com/accurics/terrascan", - "rules": [ - { - "id": "AWS.EC2.Encryption\u0026KeyManagement.Medium.0688", - "name": "amiNotEncrypted", - "shortDescription": { - "text": "Enable AWS AMI Encryption" - }, - "properties": { - "category": "Encryption \u0026 KeyManagement", - "severity": "MEDIUM" - } - } - ] - } - }, - "results": [ - { - "ruleId": "AWS.EC2.Encryption\u0026KeyManagement.Medium.0688", - "level": "warning", - "message": { - "text": "Enable AWS AMI Encryption" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "file:///Users/dev-gaur/go/src/github.com/accurics/terrascan/test/e2e/test_data/iac/aws/aws_ami_violation/main.tf" - }, - "region": { - "startLine": 5 - } - }, - "logicalLocations": [ - { - "name": "awsAmiEncrypted", - "kind": "aws_ami" - } - ] - } - ] - } - ] - } - ] -} diff --git a/test/e2e/scan/scan_k8s_files_test.go b/test/e2e/scan/scan_k8s_files_test.go index c2a8d8546..c1711c78d 100644 --- a/test/e2e/scan/scan_k8s_files_test.go +++ b/test/e2e/scan/scan_k8s_files_test.go @@ -17,6 +17,7 @@ package scan_test import ( + "github.com/accurics/terrascan/pkg/version" "path/filepath" scanUtils "github.com/accurics/terrascan/test/e2e/scan" @@ -77,7 +78,8 @@ var _ = Describe("Scan is run for k8s directories and files", func() { When("when output type is sarif", func() { It("should display violations in sarif format", func() { scanArgs := []string{"-i", "k8s", "-p", policyDir, "-d", iacDir, "-o", "sarif"} - scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_sarif.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateK8sTLSViolation, version.GetNumeric(), helper.GetAbsoluteFilePathForSarif(iacDir, "config.yaml")) + scanUtils.RunScanAndAssertJSONOutputString(terrascanBinaryPath, golden, helper.ExitCodeThree, true, outWriter, errWriter, scanArgs...) }) }) @@ -147,7 +149,8 @@ var _ = Describe("Scan is run for k8s directories and files", func() { When("when output type is sarif", func() { It("should display violations in sarif format", func() { scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile, "-o", "sarif"} - scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(k8sGoldenRelPath, "kubernetes_ingress_sarif.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateK8sTLSViolation, version.GetNumeric(), helper.GetAbsoluteFilePathForSarif(iacFile, "config.yaml")) + scanUtils.RunScanAndAssertJSONOutputString(terrascanBinaryPath, golden, helper.ExitCodeThree, true, outWriter, errWriter, scanArgs...) }) }) diff --git a/test/e2e/scan/scan_tf_files_test.go b/test/e2e/scan/scan_tf_files_test.go index db844a18e..3003010a2 100644 --- a/test/e2e/scan/scan_tf_files_test.go +++ b/test/e2e/scan/scan_tf_files_test.go @@ -17,6 +17,7 @@ package scan_test import ( + "github.com/accurics/terrascan/pkg/version" "path/filepath" scanUtils "github.com/accurics/terrascan/test/e2e/scan" @@ -120,7 +121,8 @@ var _ = Describe("Scan is run for terraform files", func() { When("output type is sarif", func() { It("should display violations in sarif format", func() { scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "-o", "sarif"} - scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(tfAwsAmiGoldenRelPath, "aws_ami_violation_sarif.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateK8sTLSViolation, version.GetNumeric(), helper.GetAbsoluteFilePathForSarif(iacDir, "main.tf")) + scanUtils.RunScanAndAssertJSONOutputString(terrascanBinaryPath, golden, helper.ExitCodeThree, true, outWriter, errWriter, scanArgs...) }) }) diff --git a/test/e2e/scan/scan_utils.go b/test/e2e/scan/scan_utils.go index 1fa41f711..62687146e 100644 --- a/test/e2e/scan/scan_utils.go +++ b/test/e2e/scan/scan_utils.go @@ -17,6 +17,7 @@ package scan import ( + "fmt" "io" "path/filepath" @@ -55,6 +56,15 @@ func RunScanAndAssertJSONOutput(terrascanBinaryPath, relGoldenFilePath string, e helper.CompareActualWithGoldenJSON(session, goldenFileAbsPath, isStdOut) } +// RunScanAndAssertJSONOutputString runs the scan command with supplied paramters and compares actual and golden output +func RunScanAndAssertJSONOutputString(terrascanBinaryPath, goldenString string, exitCode int, isStdOut bool, outWriter, errWriter io.Writer, args ...string) { + argList := []string{ScanCommand} + argList = append(argList, args...) + session := helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, argList...) + gomega.Eventually(session, ScanTimeout).Should(gexec.Exit(exitCode)) + helper.CompareActualWithGoldenJSONString(session, goldenString, isStdOut) +} + // RunScanAndAssertYAMLOutput runs the scan command with supplied paramters and compares actual and golden output func RunScanAndAssertYAMLOutput(terrascanBinaryPath, relGoldenFilePath string, exitCode int, isJunitXML, isStdOut bool, outWriter, errWriter io.Writer, args ...string) { session, goldenFileAbsPath := RunScanCommand(terrascanBinaryPath, relGoldenFilePath, exitCode, outWriter, errWriter, args...) @@ -84,3 +94,123 @@ func RunScanCommand(terrascanBinaryPath, relGoldenFilePath string, exitCode int, gomega.Expect(err).NotTo(gomega.HaveOccurred()) return session, goldenFileAbsPath } + +// GetSarifGoldenString gives out golden sarif format string +func GetSarifGoldenString(template, terrascanVersion string, absfilepath string) string { + return fmt.Sprintf(template, terrascanVersion, absfilepath) +} + +// SarifTemplateAWSAMIViolation string +const SarifTemplateAWSAMIViolation = `{ + "version": "2.1.0", + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "runs": [ + { + "tool": { + "driver": { + "name": "terrascan", + "version": "%s", + "informationUri": "https://github.com/accurics/terrascan", + "rules": [ + { + "id": "AWS.EC2.Encryption\u0026KeyManagement.Medium.0688", + "name": "amiNotEncrypted", + "shortDescription": { + "text": "Enable AWS AMI Encryption" + }, + "properties": { + "category": "Encryption \u0026 KeyManagement", + "severity": "MEDIUM" + } + } + ] + } + }, + "results": [ + { + "ruleId": "AWS.EC2.Encryption\u0026KeyManagement.Medium.0688", + "level": "warning", + "message": { + "text": "Enable AWS AMI Encryption" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "%s" + }, + "region": { + "startLine": 5 + } + }, + "logicalLocations": [ + { + "name": "awsAmiEncrypted", + "kind": "aws_ami" + } + ] + } + ] + } + ] + } + ] +}` + +// SarifTemplateK8sTLSViolation string template +const SarifTemplateK8sTLSViolation = `{ + "version": "2.1.0", + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "runs": [ + { + "tool": { + "driver": { + "name": "terrascan", + "version": "%s", + "informationUri": "https://github.com/accurics/terrascan", + "rules": [ + { + "id": "AC-K8-NS-IN-H-0020", + "name": "noHttps", + "shortDescription": { + "text": "TLS disabled can affect the confidentiality of the data in transit" + }, + "properties": { + "category": "Network Security", + "severity": "HIGH" + } + } + ] + } + }, + "results": [ + { + "ruleId": "AC-K8-NS-IN-H-0020", + "level": "error", + "message": { + "text": "TLS disabled can affect the confidentiality of the data in transit" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "%s" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "ingress-demo-disallowed", + "kind": "kubernetes_ingress" + } + ] + } + ] + } + ] + } + ] +} +` diff --git a/test/helper/helper.go b/test/helper/helper.go index f486ad768..80cc73b80 100644 --- a/test/helper/helper.go +++ b/test/helper/helper.go @@ -24,6 +24,7 @@ import ( "io/ioutil" "os" "os/exec" + "path/filepath" "reflect" "regexp" "sort" @@ -186,6 +187,31 @@ func CompareActualWithGoldenJSON(session *gexec.Session, goldenFileAbsPath strin CompareSummaryAndViolations(sessionEngineOutput, fileDataEngineOutput) } +// CompareActualWithGoldenJSONString compares actual data with golden json string passed as parameter +func CompareActualWithGoldenJSONString(session *gexec.Session, golden string, isStdOut bool) { + goldenBytes := []byte(golden) + + var sessionBytes []byte + + if isStdOut { + sessionBytes = session.Wait().Out.Contents() + } else { + sessionBytes = session.Wait().Err.Contents() + } + + sessionBytes = bytes.TrimSpace(sessionBytes) + goldenBytes = bytes.TrimSpace(goldenBytes) + + var sessionEngineOutput, goldenDataEngineOutput policy.EngineOutput + + err := json.Unmarshal(sessionBytes, &sessionEngineOutput) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + err = json.Unmarshal(goldenBytes, &goldenDataEngineOutput) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + CompareSummaryAndViolations(sessionEngineOutput, goldenDataEngineOutput) +} + // CompareActualWithGoldenYAML compares actual data with contents of golden file passed as parameter func CompareActualWithGoldenYAML(session *gexec.Session, goldenFileAbsPath string, isStdOut bool) { sessionBytes, fileBytes := GetByteData(session, goldenFileAbsPath, isStdOut) @@ -352,3 +378,14 @@ func removeFileAndRoothFromViolations(v violations) { violation.PlanRoot = "" } } + +// GetAbsoluteFilePathForSarif helper for sarif path +func GetAbsoluteFilePathForSarif(resourcePath, filePath string) string { + if !filepath.IsAbs(resourcePath) { + resourcePath, _ = filepath.Abs(resourcePath) + } + if utils.GetFileMode(resourcePath).IsDir() { + return filepath.Join(resourcePath, filePath) + } + return resourcePath +} From 418d01bb9aaf44d0f3cc86f6efc4cc6a882be1ad Mon Sep 17 00:00:00 2001 From: Devang Date: Tue, 15 Jun 2021 16:18:09 +0530 Subject: [PATCH 5/9] fixed test --- pkg/utils/json.go | 20 ++++++++++++++++++++ test/e2e/scan/scan_k8s_files_test.go | 4 ++-- test/e2e/scan/scan_tf_files_test.go | 2 +- test/e2e/scan/scan_utils.go | 2 +- test/helper/helper.go | 9 +-------- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/pkg/utils/json.go b/pkg/utils/json.go index 138f6da99..66968bf55 100644 --- a/pkg/utils/json.go +++ b/pkg/utils/json.go @@ -73,3 +73,23 @@ func AreEqualJSON(s1, s2 string) (bool, error) { return reflect.DeepEqual(o1, o2), nil } + +// AreEqualJSONBytes validate if two json byte arrays are equal +func AreEqualJSONBytes(b1, b2 []byte) (bool, error) { + var o1 interface{} + var o2 interface{} + + errmsg := "error json unmarshalling bytes: %s. error: %v" + + var err error + err = json.Unmarshal(b1, &o1) + if err != nil { + return false, fmt.Errorf(errmsg, b1, err.Error()) + } + err = json.Unmarshal(b2, &o2) + if err != nil{ + return false, fmt.Errorf(errmsg, b2, err.Error()) + } + + return reflect.DeepEqual(o1, o2), nil +} diff --git a/test/e2e/scan/scan_k8s_files_test.go b/test/e2e/scan/scan_k8s_files_test.go index c1711c78d..770ecfaf4 100644 --- a/test/e2e/scan/scan_k8s_files_test.go +++ b/test/e2e/scan/scan_k8s_files_test.go @@ -125,8 +125,8 @@ var _ = Describe("Scan is run for k8s directories and files", func() { It("should scan will all iac and display violations", func() { scanArgs := []string{scanUtils.ScanCommand, "-f", iacFile} session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, scanArgs...) - // exit code is 3 because iac files in directory has violations - helper.ValidateExitCode(session, scanUtils.ScanTimeout, helper.ExitCodeThree) + // exit code is 1 because iac file is expected to be of terraform iac type by default, not k8s yaml + helper.ValidateExitCode(session, scanUtils.ScanTimeout, helper.ExitCodeOne) }) }) }) diff --git a/test/e2e/scan/scan_tf_files_test.go b/test/e2e/scan/scan_tf_files_test.go index 3003010a2..964bee9f9 100644 --- a/test/e2e/scan/scan_tf_files_test.go +++ b/test/e2e/scan/scan_tf_files_test.go @@ -121,7 +121,7 @@ var _ = Describe("Scan is run for terraform files", func() { When("output type is sarif", func() { It("should display violations in sarif format", func() { scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "-o", "sarif"} - golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateK8sTLSViolation, version.GetNumeric(), helper.GetAbsoluteFilePathForSarif(iacDir, "main.tf")) + golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateAWSAMIViolation, version.GetNumeric(), helper.GetAbsoluteFilePathForSarif(iacDir, "main.tf")) scanUtils.RunScanAndAssertJSONOutputString(terrascanBinaryPath, golden, helper.ExitCodeThree, true, outWriter, errWriter, scanArgs...) }) }) diff --git a/test/e2e/scan/scan_utils.go b/test/e2e/scan/scan_utils.go index 62687146e..362a28f12 100644 --- a/test/e2e/scan/scan_utils.go +++ b/test/e2e/scan/scan_utils.go @@ -97,7 +97,7 @@ func RunScanCommand(terrascanBinaryPath, relGoldenFilePath string, exitCode int, // GetSarifGoldenString gives out golden sarif format string func GetSarifGoldenString(template, terrascanVersion string, absfilepath string) string { - return fmt.Sprintf(template, terrascanVersion, absfilepath) + return fmt.Sprintf(template, terrascanVersion, fmt.Sprintf("file://%s", absfilepath)) } // SarifTemplateAWSAMIViolation string diff --git a/test/helper/helper.go b/test/helper/helper.go index 80cc73b80..b3b3abf76 100644 --- a/test/helper/helper.go +++ b/test/helper/helper.go @@ -202,14 +202,7 @@ func CompareActualWithGoldenJSONString(session *gexec.Session, golden string, is sessionBytes = bytes.TrimSpace(sessionBytes) goldenBytes = bytes.TrimSpace(goldenBytes) - var sessionEngineOutput, goldenDataEngineOutput policy.EngineOutput - - err := json.Unmarshal(sessionBytes, &sessionEngineOutput) - gomega.Expect(err).NotTo(gomega.HaveOccurred()) - err = json.Unmarshal(goldenBytes, &goldenDataEngineOutput) - gomega.Expect(err).NotTo(gomega.HaveOccurred()) - - CompareSummaryAndViolations(sessionEngineOutput, goldenDataEngineOutput) + gomega.Expect(utils.AreEqualJSONBytes(sessionBytes, goldenBytes)).To(gomega.BeTrue()) } // CompareActualWithGoldenYAML compares actual data with contents of golden file passed as parameter From acab923eeca93252461ba4a8788c6dee24c5915d Mon Sep 17 00:00:00 2001 From: Devang Date: Tue, 15 Jun 2021 18:15:57 +0530 Subject: [PATCH 6/9] fix gofmt --- pkg/utils/json.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/utils/json.go b/pkg/utils/json.go index 66968bf55..7f7647a10 100644 --- a/pkg/utils/json.go +++ b/pkg/utils/json.go @@ -87,7 +87,7 @@ func AreEqualJSONBytes(b1, b2 []byte) (bool, error) { return false, fmt.Errorf(errmsg, b1, err.Error()) } err = json.Unmarshal(b2, &o2) - if err != nil{ + if err != nil { return false, fmt.Errorf(errmsg, b2, err.Error()) } From 8d11516e2f0d4ac25e2af95786ecac4e3fffd420 Mon Sep 17 00:00:00 2001 From: Devang Date: Fri, 25 Jun 2021 01:03:46 +0530 Subject: [PATCH 7/9] incorporated pr reviews --- go.mod | 4 ++-- go.sum | 4 ++++ pkg/utils/dir.go | 18 ++++++++++++++- pkg/utils/file.go | 22 +++++++++++++++++-- pkg/utils/json.go | 33 ++++++++++++++-------------- pkg/writer/sarif.go | 22 ++++++++++++++----- pkg/writer/sarif_test.go | 4 +++- test/e2e/scan/scan_k8s_files_test.go | 6 +++-- test/e2e/scan/scan_tf_files_test.go | 3 ++- test/helper/helper.go | 16 +++++++++----- 10 files changed, 96 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index bbddf9d18..eaa1eed38 100644 --- a/go.mod +++ b/go.mod @@ -38,8 +38,8 @@ require ( github.com/spf13/cobra v1.1.1 github.com/zclconf/go-cty v1.8.2 go.uber.org/zap v1.16.0 - golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 - golang.org/x/tools v0.1.3 // indirect + golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 + golang.org/x/tools v0.1.4 // indirect gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b helm.sh/helm/v3 v3.4.0 diff --git a/go.sum b/go.sum index f6edb1f9f..e08c08c38 100644 --- a/go.sum +++ b/go.sum @@ -1184,6 +1184,8 @@ golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBc >>>>>>> fixed tests golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 h1:faDu4veV+8pcThn4fewv6TVlNCezafGoC1gM/mxQLbQ= golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1263,6 +1265,8 @@ golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4 h1:cVngSRcfgyZCzys3KYOpCFa+4dqX/Oub9tAq00ttGVs= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/utils/dir.go b/pkg/utils/dir.go index e10f09c54..4c609a3f3 100644 --- a/pkg/utils/dir.go +++ b/pkg/utils/dir.go @@ -1,3 +1,19 @@ +/* + Copyright (C) 2020 Accurics, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + package utils import ( @@ -30,7 +46,7 @@ func GenerateTempDir() string { func IsDirExists(dir string) bool { _, err := os.Stat(dir) if os.IsNotExist(err) { - zap.S().Errorf("Directory %s does not exist.", dir) + zap.S().Errorf("directory %s does not exist.", dir) return false } return true diff --git a/pkg/utils/file.go b/pkg/utils/file.go index 21c794347..e05e4b4af 100644 --- a/pkg/utils/file.go +++ b/pkg/utils/file.go @@ -1,3 +1,19 @@ +/* + Copyright (C) 2020 Accurics, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + package utils import ( @@ -6,7 +22,7 @@ import ( ) // GetFileMode fetches the filemode from a file path -func GetFileMode(path string) os.FileMode { +func GetFileMode(path string) *os.FileMode { fi, err := os.Stat(path) if err != nil { if os.IsNotExist(err) { @@ -14,6 +30,8 @@ func GetFileMode(path string) os.FileMode { } else { zap.S().Errorf("unable to fetch file info for path %s.", path) } + return nil } - return fi.Mode() + mode := fi.Mode() + return &mode } diff --git a/pkg/utils/json.go b/pkg/utils/json.go index 7f7647a10..95d125f0b 100644 --- a/pkg/utils/json.go +++ b/pkg/utils/json.go @@ -1,3 +1,19 @@ +/* + Copyright (C) 2020 Accurics, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + package utils import ( @@ -56,22 +72,7 @@ func LoadJSON(filePath string) ([]*IacDocument, error) { // AreEqualJSON validate if two json strings are equal func AreEqualJSON(s1, s2 string) (bool, error) { - var o1 interface{} - var o2 interface{} - - errmsg := "error json unmarshalling string: %s. error: %v" - - var err error - err = json.Unmarshal([]byte(s1), &o1) - if err != nil { - return false, fmt.Errorf(errmsg, s1, err.Error()) - } - err = json.Unmarshal([]byte(s2), &o2) - if err != nil { - return false, fmt.Errorf(errmsg, s2, err.Error()) - } - - return reflect.DeepEqual(o1, o2), nil + return AreEqualJSONBytes([]byte(s1), []byte(s2)) } // AreEqualJSONBytes validate if two json byte arrays are equal diff --git a/pkg/writer/sarif.go b/pkg/writer/sarif.go index 16116f77c..d25bad505 100644 --- a/pkg/writer/sarif.go +++ b/pkg/writer/sarif.go @@ -22,6 +22,7 @@ import ( "github.com/accurics/terrascan/pkg/utils" "github.com/accurics/terrascan/pkg/version" "github.com/owenrumney/go-sarif/sarif" + "go.uber.org/zap" "io" "path/filepath" "strings" @@ -67,7 +68,11 @@ func SarifWriter(data interface{}, writer io.Writer) error { rule := run.AddRule(string(violation.RuleID)). WithDescription(violation.Description).WithName(violation.RuleName).WithProperties(m) - absFilePath := getAbsoluteFilePath(outputData.Summary.ResourcePath, violation.File) + absFilePath, err := getAbsoluteFilePath(outputData.Summary.ResourcePath, violation.File) + + if err != nil { + return err + } location := sarif.NewLocation(). WithPhysicalLocation(sarif.NewPhysicalLocation(). @@ -98,12 +103,17 @@ func getSarifLevel(severity string) string { return m[strings.ToLower(severity)] } -func getAbsoluteFilePath(resourcePath, filePath string) string { +func getAbsoluteFilePath(resourcePath, filePath string) (string, error) { if !filepath.IsAbs(resourcePath) { - resourcePath, _ = filepath.Abs(resourcePath) + resourcePath, err := filepath.Abs(resourcePath) + if err != nil { + zap.S().Errorf("unable to get absolute path for %s, error: %v", resourcePath, err) + return "", err + } } - if utils.GetFileMode(resourcePath).IsDir() { - return filepath.Join(resourcePath, filePath) + fileMode := utils.GetFileMode(resourcePath) + if fileMode != nil && (*fileMode).IsDir() { + return filepath.Join(resourcePath, filePath), nil } - return resourcePath + return resourcePath, nil } diff --git a/pkg/writer/sarif_test.go b/pkg/writer/sarif_test.go index 71a7043df..93a99970d 100644 --- a/pkg/writer/sarif_test.go +++ b/pkg/writer/sarif_test.go @@ -12,6 +12,8 @@ import ( "github.com/accurics/terrascan/pkg/version" ) +var testpath, _ = getAbsoluteFilePath(violationsInput.Summary.ResourcePath, violationsInput.Violations[0].File) + var expectedSarifOutput1 = fmt.Sprintf(`{ "version": "2.1.0", "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", @@ -66,7 +68,7 @@ var expectedSarifOutput1 = fmt.Sprintf(`{ ] } ] - }`, version.GetNumeric(), fmt.Sprintf("file://%s", getAbsoluteFilePath(violationsInput.Summary.ResourcePath, violationsInput.Violations[0].File))) + }`, version.GetNumeric(), fmt.Sprintf("file://%s", testpath)) var expectedSarifOutput2 = fmt.Sprintf(`{ "version": "2.1.0", diff --git a/test/e2e/scan/scan_k8s_files_test.go b/test/e2e/scan/scan_k8s_files_test.go index 770ecfaf4..f73d1615f 100644 --- a/test/e2e/scan/scan_k8s_files_test.go +++ b/test/e2e/scan/scan_k8s_files_test.go @@ -78,7 +78,8 @@ var _ = Describe("Scan is run for k8s directories and files", func() { When("when output type is sarif", func() { It("should display violations in sarif format", func() { scanArgs := []string{"-i", "k8s", "-p", policyDir, "-d", iacDir, "-o", "sarif"} - golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateK8sTLSViolation, version.GetNumeric(), helper.GetAbsoluteFilePathForSarif(iacDir, "config.yaml")) + path, _ := helper.GetAbsoluteFilePathForSarif(iacDir, "config.yaml") + golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateK8sTLSViolation, version.GetNumeric(), path) scanUtils.RunScanAndAssertJSONOutputString(terrascanBinaryPath, golden, helper.ExitCodeThree, true, outWriter, errWriter, scanArgs...) }) }) @@ -149,7 +150,8 @@ var _ = Describe("Scan is run for k8s directories and files", func() { When("when output type is sarif", func() { It("should display violations in sarif format", func() { scanArgs := []string{"-i", "k8s", "-p", policyDir, "-f", iacFile, "-o", "sarif"} - golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateK8sTLSViolation, version.GetNumeric(), helper.GetAbsoluteFilePathForSarif(iacFile, "config.yaml")) + path, _ := helper.GetAbsoluteFilePathForSarif(iacFile, "config.yaml") + golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateK8sTLSViolation, version.GetNumeric(), path) scanUtils.RunScanAndAssertJSONOutputString(terrascanBinaryPath, golden, helper.ExitCodeThree, true, outWriter, errWriter, scanArgs...) }) }) diff --git a/test/e2e/scan/scan_tf_files_test.go b/test/e2e/scan/scan_tf_files_test.go index 964bee9f9..1eba8579e 100644 --- a/test/e2e/scan/scan_tf_files_test.go +++ b/test/e2e/scan/scan_tf_files_test.go @@ -121,7 +121,8 @@ var _ = Describe("Scan is run for terraform files", func() { When("output type is sarif", func() { It("should display violations in sarif format", func() { scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "-o", "sarif"} - golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateAWSAMIViolation, version.GetNumeric(), helper.GetAbsoluteFilePathForSarif(iacDir, "main.tf")) + path, _ := helper.GetAbsoluteFilePathForSarif(iacDir, "main.tf") + golden := scanUtils.GetSarifGoldenString(scanUtils.SarifTemplateAWSAMIViolation, version.GetNumeric(), path) scanUtils.RunScanAndAssertJSONOutputString(terrascanBinaryPath, golden, helper.ExitCodeThree, true, outWriter, errWriter, scanArgs...) }) }) diff --git a/test/helper/helper.go b/test/helper/helper.go index b3b3abf76..f57c8d3e0 100644 --- a/test/helper/helper.go +++ b/test/helper/helper.go @@ -20,6 +20,7 @@ import ( "bytes" "encoding/json" "encoding/xml" + "go.uber.org/zap" "io" "io/ioutil" "os" @@ -373,12 +374,17 @@ func removeFileAndRoothFromViolations(v violations) { } // GetAbsoluteFilePathForSarif helper for sarif path -func GetAbsoluteFilePathForSarif(resourcePath, filePath string) string { +func GetAbsoluteFilePathForSarif(resourcePath, filePath string) (string, error) { if !filepath.IsAbs(resourcePath) { - resourcePath, _ = filepath.Abs(resourcePath) + resourcePath, err := filepath.Abs(resourcePath) + if err != nil { + zap.S().Errorf("unable to get absolute path for %s, error: %v", resourcePath, err) + return "", err + } } - if utils.GetFileMode(resourcePath).IsDir() { - return filepath.Join(resourcePath, filePath) + mode := utils.GetFileMode(resourcePath) + if mode != nil && (*mode).IsDir() { + return filepath.Join(resourcePath, filePath), nil } - return resourcePath + return resourcePath, nil } From 33bf96ab9e705fc86c3ed8794c54a4bbb9418ef6 Mon Sep 17 00:00:00 2001 From: Devang Date: Sat, 26 Jun 2021 06:38:43 +0530 Subject: [PATCH 8/9] fixed go.sum --- go.sum | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/go.sum b/go.sum index e08c08c38..dcc81ceab 100644 --- a/go.sum +++ b/go.sum @@ -1177,13 +1177,6 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b h1:qh4f65QIVFjq9eBURLEYWqaEXmOyqdUyiBSgaXWccWk= golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -<<<<<<< HEAD -golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 h1:C+AwYEtBp/VQwoLntUmQ/yx3MS9vmZaKNdw5eOpoQe8= -golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -======= ->>>>>>> fixed tests -golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 h1:faDu4veV+8pcThn4fewv6TVlNCezafGoC1gM/mxQLbQ= -golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1261,10 +1254,6 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4 h1:cVngSRcfgyZCzys3KYOpCFa+4dqX/Oub9tAq00ttGVs= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1372,7 +1361,6 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= @@ -1390,7 +1378,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= From 72638fbcb242d57b16e5e9af23bd888dfaff2345 Mon Sep 17 00:00:00 2001 From: Devang Date: Sat, 26 Jun 2021 07:33:03 +0530 Subject: [PATCH 9/9] updated golden templates with ne rule ids --- test/e2e/scan/scan_utils.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/scan/scan_utils.go b/test/e2e/scan/scan_utils.go index 362a28f12..e4f549a37 100644 --- a/test/e2e/scan/scan_utils.go +++ b/test/e2e/scan/scan_utils.go @@ -113,7 +113,7 @@ const SarifTemplateAWSAMIViolation = `{ "informationUri": "https://github.com/accurics/terrascan", "rules": [ { - "id": "AWS.EC2.Encryption\u0026KeyManagement.Medium.0688", + "id": "AC_AWS_0001", "name": "amiNotEncrypted", "shortDescription": { "text": "Enable AWS AMI Encryption" @@ -128,7 +128,7 @@ const SarifTemplateAWSAMIViolation = `{ }, "results": [ { - "ruleId": "AWS.EC2.Encryption\u0026KeyManagement.Medium.0688", + "ruleId": "AC_AWS_0001", "level": "warning", "message": { "text": "Enable AWS AMI Encryption" @@ -170,7 +170,7 @@ const SarifTemplateK8sTLSViolation = `{ "informationUri": "https://github.com/accurics/terrascan", "rules": [ { - "id": "AC-K8-NS-IN-H-0020", + "id": "AC_K8S_0001", "name": "noHttps", "shortDescription": { "text": "TLS disabled can affect the confidentiality of the data in transit" @@ -185,7 +185,7 @@ const SarifTemplateK8sTLSViolation = `{ }, "results": [ { - "ruleId": "AC-K8-NS-IN-H-0020", + "ruleId": "AC_K8S_0001", "level": "error", "message": { "text": "TLS disabled can affect the confidentiality of the data in transit"