diff --git a/docs/usage/command_line_mode.md b/docs/usage/command_line_mode.md index d79b4c28a..bc0af0cae 100644 --- a/docs/usage/command_line_mode.md +++ b/docs/usage/command_line_mode.md @@ -280,7 +280,9 @@ aws_ecr_repository: |--webhook-token string| Token used for sending authenticated requests to the notification webhook | This flag is optional when using the notification webhook| |--webhook-url | A webhook URL where Terrascan will send JSON scan report and normalized IaC JSON | This overrides any notification webhook URLs configured in config TOML file specified with the `-c` flag| |--use-terraform-cache |Use this to refer terraform remote modules from terraform init cache rather than downloading | By default remote module will be downloaded in temporary directory. If this flag is set then modules will be refered from terraform init cache if module is not present in terraform init cache it will be downloaded. Directory will be scanned non recurively if this flag is used.(applicable only with terraform IaC provider)| -| --find-vuln | find vulnerbilities | Use this to fetch vulnerabilities identified on the registry for docker images present in IaC the files scanned | +| --find-vuln | find vulnerabilities | Use this to fetch vulnerabilities identified on the registry for docker images present in IaC the files scanned | +| --repo-url | repository url | This flag can be used to include the repository URL as part of scan results and notifications | +| --repo-ref | repository branch name | This flag can be used to include the repository branch name as part of scan results and notifications | | -v | verbose | Displays violations with all details | | Global flags | Description | Options | @@ -319,7 +321,9 @@ Flags: -p, --policy-path stringArray policy path directory -t, --policy-type strings policy type (all, aws, azure, docker, gcp, github, k8s) (default [all]) -r, --remote-type string type of remote backend (git, s3, gcs, http, terraform-registry) - -u, --remote-url string url pointing to remote IaC repository + -u, --remote-url string url pointing to remote IaC repository + --repo-ref string branch of the repo being scanned + --repo-url string URL of the repo being scanned, will be reflected in scan summary --scan-rules strings one or more rules to scan (example: --scan-rules="ruleID1,ruleID2") --severity string minimum severity level of the policy violations to be reported by terrascan --show-passed display passed rules, along with violations diff --git a/pkg/cli/run.go b/pkg/cli/run.go index 8683676e6..0f6932f0a 100644 --- a/pkg/cli/run.go +++ b/pkg/cli/run.go @@ -108,6 +108,12 @@ type ScanOptions struct { // notificationWebhookToken is the auth token to call the notification webhook URL notificationWebhookToken string + + // repoURL lets us specify URL of the repository being scanned + repoURL string + + // repoRef lets us specify the branch of the repository being scanned + repoRef string } // NewScanOptions returns a new pointer to ScanOptions @@ -192,8 +198,10 @@ func (s *ScanOptions) Run() error { } // create a new runtime executor for processing IaC - executor, err := runtime.NewExecutor(s.iacType, s.iacVersion, s.policyType, - s.iacFilePath, s.iacDirPath, s.policyPath, s.scanRules, s.skipRules, s.categories, s.severity, s.nonRecursive, s.useTerraformCache, s.findVulnerabilities, s.notificationWebhookURL, s.notificationWebhookToken) + executor, err := runtime.NewExecutor(s.iacType, s.iacVersion, s.policyType, s.iacFilePath, s.iacDirPath, + s.policyPath, s.scanRules, s.skipRules, s.categories, s.severity, s.nonRecursive, s.useTerraformCache, + s.findVulnerabilities, s.notificationWebhookURL, s.notificationWebhookToken, s.repoURL, s.repoRef, + ) if err != nil { return err } diff --git a/pkg/cli/scan.go b/pkg/cli/scan.go index d7ce95637..7291b67e7 100644 --- a/pkg/cli/scan.go +++ b/pkg/cli/scan.go @@ -76,5 +76,7 @@ func init() { scanCmd.Flags().BoolVarP(&scanOptions.findVulnerabilities, "find-vuln", "", false, "fetches vulnerabilities identified in Docker images") scanCmd.Flags().StringVarP(&scanOptions.notificationWebhookURL, "webhook-url", "", "", "webhook URL where Terrascan will send JSON scan report and normalized IaC JSON") scanCmd.Flags().StringVarP(&scanOptions.notificationWebhookToken, "webhook-token", "", "", "optional token used when sending authenticated requests to the notification webhook") + scanCmd.Flags().StringVarP(&scanOptions.repoURL, "repo-url", "", "", "URL of the repo being scanned, will be reflected in scan summary") + scanCmd.Flags().StringVarP(&scanOptions.repoRef, "repo-ref", "", "", "branch of the repo being scanned") RegisterCommand(rootCmd, scanCmd) } diff --git a/pkg/http-server/file-scan.go b/pkg/http-server/file-scan.go index b5c8ce111..56b982a0e 100644 --- a/pkg/http-server/file-scan.go +++ b/pkg/http-server/file-scan.go @@ -166,10 +166,10 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) { var executor *runtime.Executor if g.test { executor, err = runtime.NewExecutor(iacType, iacVersion, cloudType, - tempFile.Name(), "", []string{"./testdata/testpolicies"}, scanRules, skipRules, categories, severity, false, false, false, notificationWebhookURL, notificationWebhookToken) + tempFile.Name(), "", []string{"./testdata/testpolicies"}, scanRules, skipRules, categories, severity, false, false, false, notificationWebhookURL, notificationWebhookToken, "", "") } else { executor, err = runtime.NewExecutor(iacType, iacVersion, cloudType, - tempFile.Name(), "", getPolicyPathFromConfig(), scanRules, skipRules, categories, severity, false, false, findVulnerabilities, notificationWebhookURL, notificationWebhookToken) + tempFile.Name(), "", getPolicyPathFromConfig(), scanRules, skipRules, categories, severity, false, false, findVulnerabilities, notificationWebhookURL, notificationWebhookToken, "", "") } if err != nil { zap.S().Error(err) diff --git a/pkg/http-server/remote-repo.go b/pkg/http-server/remote-repo.go index dc1737e62..b57f05996 100644 --- a/pkg/http-server/remote-repo.go +++ b/pkg/http-server/remote-repo.go @@ -48,6 +48,7 @@ type scanRemoteRepoReq struct { d downloader.Downloader NotificationWebhookURL string `json:"webhook_url"` NotificationWebhookToken string `json:"webhook_token"` + RepoRef string `json:"repo-ref"` } // scanRemoteRepo downloads the remote Iac repository and scans it for @@ -131,7 +132,7 @@ func (s *scanRemoteRepoReq) ScanRemoteRepo(iacType, iacVersion string, cloudType // create a new runtime executor for scanning the remote repo executor, err := runtime.NewExecutor(iacType, iacVersion, cloudType, - "", iacDirPath, policyPath, s.ScanRules, s.SkipRules, s.Categories, s.Severity, s.NonRecursive, false, s.FindVulnerabilities, s.NotificationWebhookURL, s.NotificationWebhookToken) + "", iacDirPath, policyPath, s.ScanRules, s.SkipRules, s.Categories, s.Severity, s.NonRecursive, false, s.FindVulnerabilities, s.NotificationWebhookURL, s.NotificationWebhookToken, s.RemoteURL, s.RepoRef) if err != nil { zap.S().Error(err) return output, isAdmissionDenied, err diff --git a/pkg/http-server/webhook-scan-logs.go b/pkg/http-server/webhook-scan-logs.go index 3372a0f69..2752110ae 100644 --- a/pkg/http-server/webhook-scan-logs.go +++ b/pkg/http-server/webhook-scan-logs.go @@ -82,7 +82,7 @@ func (g *APIHandler) getLogs(w http.ResponseWriter, r *http.Request) { ) // Validate if authorized (API key is specified and matched the server one (saved in an environment variable) - validatingWebhook := admissionWebhook.NewValidatingWebhook([]byte(""), "", "") + validatingWebhook := admissionWebhook.NewValidatingWebhook([]byte(""), "", "", "", "") if err := validatingWebhook.Authorize(apiKey); err != nil { switch err { case admissionWebhook.ErrAPIKeyMissing: diff --git a/pkg/http-server/webhook-scan.go b/pkg/http-server/webhook-scan.go index 28720ce04..40ea1383b 100644 --- a/pkg/http-server/webhook-scan.go +++ b/pkg/http-server/webhook-scan.go @@ -39,6 +39,8 @@ func (g *APIHandler) validateK8SWebhook(w http.ResponseWriter, r *http.Request) qP = r.URL.Query() notificationWebhookURL = qP.Get("webhook-url") notificationWebhookToken = qP.Get("webhook-token") + repoURL = qP.Get("repo-url") + repoRef = qP.Get("repo-ref") ) // Read the request into byte array @@ -50,7 +52,7 @@ func (g *APIHandler) validateK8SWebhook(w http.ResponseWriter, r *http.Request) } zap.S().Debugf("scanning configuration webhook request: %+v", string(body)) - validatingWebhook := admissionWebhook.NewValidatingWebhook(body, notificationWebhookURL, notificationWebhookToken) + validatingWebhook := admissionWebhook.NewValidatingWebhook(body, notificationWebhookURL, notificationWebhookToken, repoURL, repoRef) // Validate if authorized (API key is specified and matched the server one (saved in an environment variable) if err := validatingWebhook.Authorize(apiKey); err != nil { switch err { diff --git a/pkg/k8s/admission-webhook/validating-webhook.go b/pkg/k8s/admission-webhook/validating-webhook.go index 2b16fbecf..72ae1a7f9 100644 --- a/pkg/k8s/admission-webhook/validating-webhook.go +++ b/pkg/k8s/admission-webhook/validating-webhook.go @@ -46,15 +46,19 @@ type ValidatingWebhook struct { dblogger *dblogs.WebhookScanLogger notificationWebhookURL string notificationWebhookToken string + repoURL string + repoRef string } // NewValidatingWebhook returns a new, empty ValidatingWebhook struct -func NewValidatingWebhook(body []byte, notificationWebhookURL, notificationWebhookToken string) AdmissionWebhook { +func NewValidatingWebhook(body []byte, notificationWebhookURL, notificationWebhookToken, repoURL, repoRef string) AdmissionWebhook { return ValidatingWebhook{ dblogger: dblogs.NewWebhookScanLogger(), requestBody: body, notificationWebhookURL: notificationWebhookURL, notificationWebhookToken: notificationWebhookToken, + repoURL: repoURL, + repoRef: repoRef, } } @@ -195,10 +199,10 @@ func (w ValidatingWebhook) scanK8sFile(filePath string) (runtime.Output, error) if flag.Lookup("test.v") != nil { executor, err = runtime.NewExecutor("k8s", "v1", []string{"k8s"}, - filePath, "", []string{testPoliciesPath}, []string{}, []string{}, []string{}, "", false, false, false, w.notificationWebhookURL, w.notificationWebhookToken) + filePath, "", []string{testPoliciesPath}, []string{}, []string{}, []string{}, "", false, false, false, w.notificationWebhookURL, w.notificationWebhookToken, w.repoURL, w.repoRef) } else { executor, err = runtime.NewExecutor("k8s", "v1", []string{"k8s"}, - filePath, "", []string{}, []string{}, []string{}, []string{}, "", false, false, false, w.notificationWebhookURL, w.notificationWebhookToken) + filePath, "", []string{}, []string{}, []string{}, []string{}, "", false, false, false, w.notificationWebhookURL, w.notificationWebhookToken, w.repoURL, w.repoRef) } if err != nil { zap.S().Errorf("failed to create runtime executer: '%v'", err) diff --git a/pkg/results/types.go b/pkg/results/types.go index bfb2bc3ed..bcac27a12 100644 --- a/pkg/results/types.go +++ b/pkg/results/types.go @@ -62,6 +62,7 @@ type ViolationStore struct { // ScanSummary will hold the default scan summary data type ScanSummary struct { ResourcePath string `json:"file/folder" yaml:"file/folder" xml:"file_folder,attr"` + Branch string `json:"branch,omitempty" yaml:"branch,omitempty" xml:"branch,attr,omitempty"` IacType string `json:"iac_type" yaml:"iac_type" xml:"iac_type,attr"` Timestamp string `json:"scanned_at" yaml:"scanned_at" xml:"scanned_at,attr"` ShowViolationDetails bool `json:"-" yaml:"-" xml:"-"` diff --git a/pkg/runtime/executor.go b/pkg/runtime/executor.go index 1119f9327..916b84637 100644 --- a/pkg/runtime/executor.go +++ b/pkg/runtime/executor.go @@ -59,10 +59,12 @@ type Executor struct { vulnerabilityEngine vulnerability.Engine notificationWebhookURL string notificationWebhookToken string + repoURL string + repoRef string } // NewExecutor creates a runtime object -func NewExecutor(iacType, iacVersion string, policyTypes []string, filePath, dirPath string, policyPath, scanRules, skipRules, categories []string, severity string, nonRecursive, useTerraformCache, findVulnerabilities bool, notificationWebhookURL, notificationWebhookToken string) (e *Executor, err error) { +func NewExecutor(iacType, iacVersion string, policyTypes []string, filePath, dirPath string, policyPath, scanRules, skipRules, categories []string, severity string, nonRecursive, useTerraformCache, findVulnerabilities bool, notificationWebhookURL, notificationWebhookToken, repoURL, repoRef string) (e *Executor, err error) { e = &Executor{ filePath: filePath, dirPath: dirPath, @@ -76,6 +78,8 @@ func NewExecutor(iacType, iacVersion string, policyTypes []string, filePath, dir findVulnerabilities: findVulnerabilities, notificationWebhookURL: notificationWebhookURL, notificationWebhookToken: notificationWebhookToken, + repoURL: repoURL, + repoRef: repoRef, } // assigning vulnerabilityEngine @@ -266,6 +270,10 @@ func (e *Executor) Execute(configOnly bool) (results Output, err error) { } // send notifications, if configured + if e.repoURL != "" { + results.Violations.Summary.ResourcePath = e.repoURL + results.Violations.Summary.Branch = e.repoRef + } e.SendNotifications(results) // successful diff --git a/pkg/runtime/executor_test.go b/pkg/runtime/executor_test.go index 1f3a90469..871060d8a 100644 --- a/pkg/runtime/executor_test.go +++ b/pkg/runtime/executor_test.go @@ -468,6 +468,8 @@ type flagSet struct { skipRules []string notificationWebhookURL string notificationWebhookToken string + repoURL string + repoRef string } func TestNewExecutor(t *testing.T) { @@ -596,7 +598,7 @@ func TestNewExecutor(t *testing.T) { t.Run(tt.name, func(t *testing.T) { config.LoadGlobalConfig(tt.configfile) - gotExecutor, gotErr := NewExecutor(tt.flags.iacType, tt.flags.iacVersion, tt.flags.policyTypes, tt.flags.filePath, tt.flags.dirPath, tt.flags.policyPath, tt.flags.scanRules, tt.flags.skipRules, tt.flags.categories, tt.flags.severity, false, false, false, tt.flags.notificationWebhookURL, tt.flags.notificationWebhookToken) + gotExecutor, gotErr := NewExecutor(tt.flags.iacType, tt.flags.iacVersion, tt.flags.policyTypes, tt.flags.filePath, tt.flags.dirPath, tt.flags.policyPath, tt.flags.scanRules, tt.flags.skipRules, tt.flags.categories, tt.flags.severity, false, false, false, tt.flags.notificationWebhookURL, tt.flags.notificationWebhookToken, tt.flags.repoURL, tt.flags.repoRef) if !reflect.DeepEqual(tt.wantErr, gotErr) { t.Errorf("Mismatch in error => got: '%v', want: '%v'", gotErr, tt.wantErr) diff --git a/pkg/writer/human_readable.go b/pkg/writer/human_readable.go index d19fe7616..68c061ad5 100644 --- a/pkg/writer/human_readable.go +++ b/pkg/writer/human_readable.go @@ -143,15 +143,23 @@ func detailedViolations(v results.Violation) string { } func scanSummary(s results.ScanSummary) string { - out := fmt.Sprintf("%-20v:\t%s\n\t%-20v:\t%s\n\t%-20v:\t%s\n\t%-20v:\t%d\n\t%-20v:\t%d\n\t%-20v:\t%d\n\t%-20v:\t%d\n\t%-20v:\t%d\n\t", - "File/Folder", s.ResourcePath, + + out := fmt.Sprintf("%-20v:\t%s\n\t", + "File/Folder", s.ResourcePath) + + if s.Branch != "" { + out += fmt.Sprintf("%-20v:\t%s\n\t", "Branch", s.Branch) + } + + out += fmt.Sprintf("%-20v:\t%s\n\t%-20v:\t%s\n\t%-20v:\t%d\n\t%-20v:\t%d\n\t%-20v:\t%d\n\t%-20v:\t%d\n\t%-20v:\t%d\n\t", "IaC Type", s.IacType, "Scanned At", s.Timestamp, "Policies Validated", s.TotalPolicies, "Violated Policies", s.ViolatedPolicies, "Low", s.LowCount, "Medium", s.MediumCount, - "High", s.HighCount) + "High", s.HighCount, + ) if s.Vulnerabilities != nil { out += fmt.Sprintf("%-20v:\t%d\n\t", "Vulnerabilities", *s.Vulnerabilities) diff --git a/pkg/writer/human_readable_test.go b/pkg/writer/human_readable_test.go index 9cad0d1ab..35f9cd3ac 100644 --- a/pkg/writer/human_readable_test.go +++ b/pkg/writer/human_readable_test.go @@ -61,6 +61,17 @@ var ( }, }, } + summaryWithRepoURLRepoRef = results.ScanSummary{ + ResourcePath: "https://github.com/user/repository.git", + Branch: "main", + IacType: "terraform", + Timestamp: "2020-12-12 11:21:29.902796 +0000 UTC", + TotalPolicies: 566, + LowCount: 0, + MediumCount: 0, + HighCount: 1, + ViolatedPolicies: 1, + } ) const ( @@ -165,6 +176,18 @@ Scan Summary - Medium : 0 High : 1 Vulnerabilities : 1` + + expectedOutput4 = `Scan Summary - + + File/Folder : https://github.com/user/repository.git + Branch : main + IaC Type : terraform + Scanned At : 2020-12-12 11:21:29.902796 +0000 UTC + Policies Validated : 566 + Violated Policies : 1 + Low : 0 + Medium : 0 + High : 1` ) func TestHumanReadbleWriter(t *testing.T) { @@ -200,6 +223,15 @@ func TestHumanReadbleWriter(t *testing.T) { input: vulnerabilitiesInputHumanReadable, expectedOutput: vulnerabilityScanOutputHumanReadable, }, + { + name: "Human Readable Writer: with repository url and branch", + input: policy.EngineOutput{ + ViolationStore: &results.ViolationStore{ + Summary: summaryWithRepoURLRepoRef, + }, + }, + expectedOutput: expectedOutput4, + }, } for _, tt := range tests { diff --git a/pkg/writer/junit_xml.go b/pkg/writer/junit_xml.go index 8425c06bd..0d2717fe8 100644 --- a/pkg/writer/junit_xml.go +++ b/pkg/writer/junit_xml.go @@ -52,6 +52,7 @@ type JUnitTestSuite struct { Time string `xml:"time,attr"` Name string `xml:"name,attr"` Package string `xml:"package,attr"` + Branch string `xml:"branch,attr,omitempty"` Properties []JUnitProperty `xml:"properties>property,omitempty"` TestCases []JUnitTestCase } @@ -103,6 +104,7 @@ func newJunitTestSuite(summary results.ScanSummary) JUnitTestSuite { Time: fmt.Sprint(summary.TotalTime), Failures: summary.ViolatedPolicies, Package: summary.ResourcePath, + Branch: summary.Branch, Properties: []JUnitProperty{ { Name: "Terrascan Version", diff --git a/pkg/writer/junit_xml_test.go b/pkg/writer/junit_xml_test.go index e3f15a383..c563edbdc 100644 --- a/pkg/writer/junit_xml_test.go +++ b/pkg/writer/junit_xml_test.go @@ -66,6 +66,16 @@ func TestJUnitXMLWriter(t *testing.T) { `, version.Get()) + testOutputRepoURLRepoRef := fmt.Sprintf(` + + + + + + + + `, version.Get()) + type args struct { data interface{} } @@ -108,6 +118,17 @@ func TestJUnitXMLWriter(t *testing.T) { }, wantWriter: testOutputPassedRules, }, + { + name: "data with repository url and branch", + args: args{ + policy.EngineOutput{ + ViolationStore: &results.ViolationStore{ + Summary: summaryWithRepoURLRepoRef, + }, + }, + }, + wantWriter: testOutputRepoURLRepoRef, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/test/e2e/help/golden/help_scan.txt b/test/e2e/help/golden/help_scan.txt index 3b214c27d..51d152f32 100644 --- a/test/e2e/help/golden/help_scan.txt +++ b/test/e2e/help/golden/help_scan.txt @@ -19,6 +19,8 @@ Flags: -t, --policy-type strings policy type (all, aws, azure, docker, gcp, github, k8s) (default [all]) -r, --remote-type string type of remote backend (git, s3, gcs, http, terraform-registry) -u, --remote-url string url pointing to remote IaC repository + --repo-ref string branch of the repo being scanned + --repo-url string URL of the repo being scanned, will be reflected in scan summary --scan-rules strings one or more rules to scan (example: --scan-rules="ruleID1,ruleID2") --severity string minimum severity level of the policy violations to be reported by terrascan --show-passed display passed rules, along with violations diff --git a/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_human_with_repo_detail.txt b/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_human_with_repo_detail.txt new file mode 100644 index 000000000..02150290d --- /dev/null +++ b/test/e2e/scan/golden/terraform_scans/aws/aws_ami_violations/aws_ami_violation_human_with_repo_detail.txt @@ -0,0 +1,23 @@ +Violation Details - + + Description : Enable AWS AMI Encryption + File : main.tf + Module Name : root + Plan Root : ./ + Line : 5 + Severity : MEDIUM + + ----------------------------------------------------------------------- + + +Scan Summary - + + File/Folder : https://github.com/accurics/terrascan.git + Branch : main + IaC Type : terraform + Scanned At : 2021-03-02 15:45:17.636568 +0000 UTC + Policies Validated : 8 + Violated Policies : 1 + Low : 0 + Medium : 1 + High : 0 \ No newline at end of file diff --git a/test/e2e/scan/scan_test.go b/test/e2e/scan/scan_test.go index b082170f7..fdd5f140f 100644 --- a/test/e2e/scan/scan_test.go +++ b/test/e2e/scan/scan_test.go @@ -17,11 +17,14 @@ package scan_test import ( + "bytes" + "encoding/json" "fmt" "io" "os" "path/filepath" + "github.com/accurics/terrascan/pkg/policy" "github.com/accurics/terrascan/pkg/utils" scanUtils "github.com/accurics/terrascan/test/e2e/scan" "github.com/accurics/terrascan/test/helper" @@ -295,4 +298,51 @@ var _ = Describe("Scan", func() { }) }) }) + + Describe("terrascan scan command is run with notification webhook and repo detail flags", func() { + + notificationURL := "https://httpbin.org/post" + notificationToken := "token" + + tfGoldenRelPath := filepath.Join("golden", "terraform_scans") + tfAwsAmiGoldenRelPath := filepath.Join(tfGoldenRelPath, "aws", "aws_ami_violations") + + iacDir, err1 := filepath.Abs(filepath.Join(awsIacRelPath, "aws_ami_violation")) + policyDir, err2 := filepath.Abs(policyRootRelPath) + It("should not error out while getting absolute path", func() { + Expect(err1).NotTo(HaveOccurred()) + Expect(err2).NotTo(HaveOccurred()) + }) + Context("valid --webhook-url and --webhook-token flag is supplied", func() { + It("should scan and display violations in human output format and exit with status code 3", func() { + scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "--webhook-url", notificationURL, "--webhook-token", notificationToken} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(tfAwsAmiGoldenRelPath, "aws_ami_violation_human.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + + }) + }) + + Context("only --webhook-url flag is supplied", func() { + It("should scan and display violations in human output format and exit with status code 3", func() { + scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "--webhook-url", notificationURL} + scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(tfAwsAmiGoldenRelPath, "aws_ami_violation_human.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + + }) + }) + Context("terrascan scan command is run with --repo-url and --repo-ref flag", func() { + It("should scan and result in json output format and exit with status code 3", func() { + scanArgs := []string{"scan", "-p", policyDir, "-i", "terraform", "-d", iacDir, "--repo-url", "https://github.com/accurics/terrascan.git", "--repo-ref", "main", "-o", "json"} + // scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(tfAwsAmiGoldenRelPath, "aws_ami_violation_human_with_repo_detail.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + session := helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, scanArgs...) + Eventually(session, 3).Should(gexec.Exit(helper.ExitCodeThree)) + sessionBytes := session.Wait().Out.Contents() + sessionBytes = bytes.TrimSpace(sessionBytes) + var sessionEngineOutput policy.EngineOutput + + err := json.Unmarshal(sessionBytes, &sessionEngineOutput) + Expect(err).NotTo(HaveOccurred()) + Expect(sessionEngineOutput.Summary.ResourcePath).To((Equal("https://github.com/accurics/terrascan.git"))) + Expect(sessionEngineOutput.Summary.Branch).To((Equal("main"))) + }) + }) + }) }) diff --git a/test/e2e/scan/scan_webhook_test.go b/test/e2e/scan/scan_webhook_test.go deleted file mode 100644 index 941d344ed..000000000 --- a/test/e2e/scan/scan_webhook_test.go +++ /dev/null @@ -1,77 +0,0 @@ -/* - 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 scan_test - -import ( - "path/filepath" - - scanUtils "github.com/accurics/terrascan/test/e2e/scan" - "github.com/accurics/terrascan/test/helper" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/onsi/gomega/gbytes" -) - -var _ = Describe("Scan Command using webhook args", func() { - BeforeEach(func() { - outWriter = gbytes.NewBuffer() - errWriter = gbytes.NewBuffer() - }) - - AfterEach(func() { - outWriter = nil - errWriter = nil - }) - - var policyDir, iacDir string - var err error - - notificationURL := "https://httpbin.org/post" - notificationToken := "token" - - Describe("terrascan scan command is run with --webhook-url and --webhook-token flag", func() { - tfGoldenRelPath := filepath.Join("golden", "terraform_scans") - tfAwsAmiGoldenRelPath := filepath.Join(tfGoldenRelPath, "aws", "aws_ami_violations") - - iacDir, err = filepath.Abs(filepath.Join(awsIacRelPath, "aws_ami_violation")) - It("should not error out while getting absolute path", func() { - Expect(err).NotTo(HaveOccurred()) - }) - - policyDir, err = filepath.Abs(policyRootRelPath) - It("should not error out while getting absolute path", func() { - Expect(err).NotTo(HaveOccurred()) - }) - - Context("valid --webhook-url and --webhook-token flag is supplied", func() { - It("should exit with status code 5", func() { - scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "--webhook-url", notificationURL, "--webhook-token", notificationToken} - scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(tfAwsAmiGoldenRelPath, "aws_ami_violation_human.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) - - }) - }) - - Context("only --webhook-url flag is supplied", func() { - It("should exit with status code 5", func() { - scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "--webhook-url", notificationURL} - scanUtils.RunScanAndAssertGoldenOutputRegex(terrascanBinaryPath, filepath.Join(tfAwsAmiGoldenRelPath, "aws_ami_violation_human.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) - - }) - }) - }) - -})