diff --git a/pkg/iac-providers/kubernetes/v1/normalize.go b/pkg/iac-providers/kubernetes/v1/normalize.go index ef1cd08ee..818a43b64 100644 --- a/pkg/iac-providers/kubernetes/v1/normalize.go +++ b/pkg/iac-providers/kubernetes/v1/normalize.go @@ -191,13 +191,13 @@ func readMinMaxSeverityFromAnnotations(annotations map[string]interface{}, resou ) if minSeverityAnnotation, ok = annotations[terrascanMinSeverity]; !ok { zap.S().Debugf(infileInstructionNotPresentLog, terrascanMinSeverity, resourceID) - } else { - minSeverity = minSeverityAnnotation.(string) + } else if minSeverity, ok = minSeverityAnnotation.(string); !ok { + zap.S().Debugf("%s must be a string cantaining value as (High | Low| Medium)", terrascanMinSeverity) } if maxSeverityAnnotation, ok = annotations[terrascanMaxSeverity]; !ok { zap.S().Debugf(infileInstructionNotPresentLog, terrascanMaxSeverity, resourceID) - } else { - maxSeverity = maxSeverityAnnotation.(string) + } else if maxSeverity, ok = maxSeverityAnnotation.(string); !ok { + zap.S().Debugf("%s must be a string cantaining value as (High | Low| Medium)", terrascanMaxSeverity) } return } diff --git a/pkg/iac-providers/kubernetes/v1/normalize_test.go b/pkg/iac-providers/kubernetes/v1/normalize_test.go index 8151e7f50..aeecea5ea 100644 --- a/pkg/iac-providers/kubernetes/v1/normalize_test.go +++ b/pkg/iac-providers/kubernetes/v1/normalize_test.go @@ -467,6 +467,15 @@ func TestReadMinMaxSeverityFromAnnotations(t *testing.T) { wantMinSeverity: "hiGh", wantMaxSeverity: "LOw", }, + { + name: "invalid min and max value", + args: args{annotations: map[string]interface{}{ + terrascanMaxSeverity: 2, + terrascanMinSeverity: false, + }}, + wantMinSeverity: "", + wantMaxSeverity: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/policy/opa/engine.go b/pkg/policy/opa/engine.go index de7c77f66..c07d624eb 100644 --- a/pkg/policy/opa/engine.go +++ b/pkg/policy/opa/engine.go @@ -304,8 +304,10 @@ func (e *Engine) reportViolation(regoData *RegoData, resource *output.ResourceCo if !strings.EqualFold(resource.MaxSeverity, "none") { // if both values are set then min severity will be applicable - if utils.MinSeverityApplicable(regoData.Metadata.Severity, resource.MinSeverity) { - violation.Severity = strings.ToUpper(resource.MinSeverity) + if resource.MinSeverity != "" { + if utils.MinSeverityApplicable(regoData.Metadata.Severity, resource.MinSeverity) { + violation.Severity = strings.ToUpper(resource.MinSeverity) + } } else if utils.MaxSeverityApplicable(regoData.Metadata.Severity, resource.MaxSeverity) { violation.Severity = strings.ToUpper(resource.MaxSeverity) } diff --git a/test/e2e/scan/golden/resource_prioritising/min_severity_with_skip_rule/k8s/k8s_file_setting_min_severity_with_skip_rule.txt b/test/e2e/scan/golden/resource_prioritising/min_severity_with_skip_rule/k8s/k8s_file_setting_min_severity_with_skip_rule.txt new file mode 100644 index 000000000..bc4c4ded7 --- /dev/null +++ b/test/e2e/scan/golden/resource_prioritising/min_severity_with_skip_rule/k8s/k8s_file_setting_min_severity_with_skip_rule.txt @@ -0,0 +1,29 @@ +{ + "results": { + "violations": null, + "skipped_violations": [ + { + "rule_name": "ensurePrivateIP", + "description": "Vulnerable to CVE-2020-8554", + "rule_id": "AC-K8-NS-SE-M-0188", + "severity": "HIGH", + "category": "Network Security", + "skip_comment": "reason to skip the rule", + "resource_name": "allowed-external-ip", + "resource_type": "kubernetes_service", + "file": "config.yaml", + "line": 1 + } + ], + "scan_summary": { + "file/folder": "/Users/suvarna/go/src/github.com/rchanger/terrascan/test/e2e/test_data/iac/resource_prioritising/min_severity_with_skip_rule/k8s", + "iac_type": "k8s", + "scanned_at": "2021-05-28 07:33:23.686144 +0000 UTC", + "policies_validated": 8, + "violated_policies": 0, + "low": 0, + "medium": 0, + "high": 0 + } + } +} diff --git a/test/e2e/scan/golden/resource_prioritising/min_severity_with_skip_rule/terraform/terraform_file_setting_min_severity_with_skip_rule.txt b/test/e2e/scan/golden/resource_prioritising/min_severity_with_skip_rule/terraform/terraform_file_setting_min_severity_with_skip_rule.txt new file mode 100644 index 000000000..9365e3528 --- /dev/null +++ b/test/e2e/scan/golden/resource_prioritising/min_severity_with_skip_rule/terraform/terraform_file_setting_min_severity_with_skip_rule.txt @@ -0,0 +1,45 @@ +{ + "results": { + "violations": [ + { + "rule_name": "rdsIamAuthEnabled", + "description": "Ensure that your RDS database has IAM Authentication enabled.", + "rule_id": "AWS.RDS.DataSecurity.High.0577", + "severity": "HIGH", + "category": "Data Security", + "resource_name": "PtShGgAdi4", + "resource_type": "aws_db_instance", + "module_name": "root", + "file": "main.tf", + "plan_root": "./", + "line": 1 + } + ], + "skipped_violations": [ + { + "rule_name": "rdsHasStorageEncrypted", + "description": "Ensure that your RDS database instances encrypt the underlying storage. Encrypted RDS instances use the industry standard AES-256 encryption algorithm to encrypt data on the server that hosts RDS DB instances. After data is encrypted, RDS handles authentication of access and descryption of data transparently with minimal impact on performance.", + "rule_id": "AWS.RDS.DataSecurity.High.0414", + "severity": "HIGH", + "category": "Data Security", + "skip_comment": "need to skip this rule", + "resource_name": "PtShGgAdi4", + "resource_type": "aws_db_instance", + "module_name": "root", + "file": "main.tf", + "plan_root": "./", + "line": 1 + } + ], + "scan_summary": { + "file/folder": "/Users/suvarna/go/src/github.com/rchanger/terrascan/test/e2e/test_data/iac/resource_prioritising/min_severity_with_skip_rule/terraform", + "iac_type": "terraform", + "scanned_at": "2021-05-28 07:38:52.873682 +0000 UTC", + "policies_validated": 8, + "violated_policies": 1, + "low": 0, + "medium": 0, + "high": 1 + } + } +} diff --git a/test/e2e/scan/scan_rules_filtering_test.go b/test/e2e/scan/scan_rules_filtering_test.go index f67beeb07..740d89d07 100644 --- a/test/e2e/scan/scan_rules_filtering_test.go +++ b/test/e2e/scan/scan_rules_filtering_test.go @@ -286,6 +286,22 @@ var _ = Describe("Scan command with rule filtering options", func() { scanUtils.RunScanAndAssertJSONOutput(terrascanBinaryPath, filepath.Join(resourcePrioritisingGoldenRelPath, "max_severity_set_none", "terraform", "terraform_file_setting_max_severity_none.txt"), helper.ExitCodeZero, false, true, outWriter, errWriter, scanArgs...) }) }) + Context("resource min severity set to High and max severity set to Low in tf files", func() { + iacDir := filepath.Join(resourcePrioritisingIacRelPath, "min_max_both_severity_set", "terraform") + It("should display violations with change priority to High as specified by min severity for the resource and exit with status code 3", func() { + scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "-o", "json"} + scanUtils.RunScanAndAssertJSONOutput(terrascanBinaryPath, filepath.Join(resourcePrioritisingGoldenRelPath, "min_severity_set", "terraform", "terraform_file_setting_min_severity.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + Context("resource min severity set to High and skip rule provided in tf files", func() { + iacDir := filepath.Join(resourcePrioritisingIacRelPath, "min_severity_with_skip_rule", "terraform") + It("should display skipped violations and violations with change priority to High as specified by min severity for the resource and exit with status code 3", func() { + scanArgs := []string{"-p", policyDir, "-i", "terraform", "-d", iacDir, "-o", "json"} + scanUtils.RunScanAndAssertJSONOutput(terrascanBinaryPath, filepath.Join(resourcePrioritisingGoldenRelPath, "min_severity_with_skip_rule", "terraform", "terraform_file_setting_min_severity_with_skip_rule.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + + // k8s file tests Context("resource max severity set to Low in k8s files", func() { iacDir := filepath.Join(resourcePrioritisingIacRelPath, "max_severity_set", "k8s") It("should display violations with change priority to Low for the resource and exit with status code 3", func() { @@ -307,5 +323,20 @@ var _ = Describe("Scan command with rule filtering options", func() { scanUtils.RunScanAndAssertJSONOutput(terrascanBinaryPath, filepath.Join(resourcePrioritisingGoldenRelPath, "max_severity_set_none", "k8s", "k8s_file_setting_max_severity_none.txt"), helper.ExitCodeZero, false, true, outWriter, errWriter, scanArgs...) }) }) + Context("resource min severity set to High and max severity set to Low k8s files", func() { + iacDir := filepath.Join(resourcePrioritisingIacRelPath, "min_max_both_severity_set", "k8s") + It("should display violations with change priority to High as specified by min severity for the resource and exit with status code 3", func() { + scanArgs := []string{"-p", policyDir, "-i", "k8s", "-d", iacDir, "-o", "json"} + scanUtils.RunScanAndAssertJSONOutput(terrascanBinaryPath, filepath.Join(resourcePrioritisingGoldenRelPath, "min_severity_set", "k8s", "k8s_file_setting_min_severity.txt"), helper.ExitCodeThree, false, true, outWriter, errWriter, scanArgs...) + }) + }) + Context("resource min severity set to High and skip rule provided in k8s files", func() { + iacDir := filepath.Join(resourcePrioritisingIacRelPath, "min_severity_with_skip_rule", "k8s") + // since only one violation is present for resource + It("should display skipped violations with change priority to High as specified by min severity for the resource and exit with status code 0", func() { + scanArgs := []string{"-p", policyDir, "-i", "k8s", "-d", iacDir, "-o", "json"} + scanUtils.RunScanAndAssertJSONOutput(terrascanBinaryPath, filepath.Join(resourcePrioritisingGoldenRelPath, "min_severity_with_skip_rule", "k8s", "k8s_file_setting_min_severity_with_skip_rule.txt"), helper.ExitCodeZero, false, true, outWriter, errWriter, scanArgs...) + }) + }) }) }) diff --git a/test/e2e/test_data/iac/resource_prioritising/min_max_both_severity_set/k8s/config.yaml b/test/e2e/test_data/iac/resource_prioritising/min_max_both_severity_set/k8s/config.yaml new file mode 100644 index 000000000..dcfde9c37 --- /dev/null +++ b/test/e2e/test_data/iac/resource_prioritising/min_max_both_severity_set/k8s/config.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: allowed-external-ip + annotations: + runterrascan.io/minseverity: High + runterrascan.io/maxseverity: Low +spec: + type: ClusterIP + selector: + app: MyApp + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 8080 + externalIPs: + - 192.168.10.10 + - 8.8.8.8 + - 203.0.113.0 \ No newline at end of file diff --git a/test/e2e/test_data/iac/resource_prioritising/min_max_both_severity_set/terraform/main.tf b/test/e2e/test_data/iac/resource_prioritising/min_max_both_severity_set/terraform/main.tf new file mode 100644 index 000000000..cd5332bd4 --- /dev/null +++ b/test/e2e/test_data/iac/resource_prioritising/min_max_both_severity_set/terraform/main.tf @@ -0,0 +1,15 @@ +resource "aws_db_instance" "PtShGgAdi4" { + #ts:minseverity=High + #ts:maxseverity=Low + allocated_storage = 20 + storage_type = "gp2" + engine = "mysql" + engine_version = "5.7" + instance_class = "db.t2.micro" + name = "ptshggadi4" + backup_retention_period = 0 + ca_cert_identifier = "rds-ca-2019" + username = "slaflheafllaflaehf" + password = "something" + skip_final_snapshot = true +} \ No newline at end of file diff --git a/test/e2e/test_data/iac/resource_prioritising/min_severity_with_skip_rule/k8s/config.yaml b/test/e2e/test_data/iac/resource_prioritising/min_severity_with_skip_rule/k8s/config.yaml new file mode 100644 index 000000000..b94361e3f --- /dev/null +++ b/test/e2e/test_data/iac/resource_prioritising/min_severity_with_skip_rule/k8s/config.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: allowed-external-ip + annotations: + runterrascan.io/minseverity: High + runterrascan.io/skip: "[{\"rule\": \"AC-K8-NS-SE-M-0188\", \"comment\": \"reason to skip the rule\"}]" +spec: + type: ClusterIP + selector: + app: MyApp + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 8080 + externalIPs: + - 192.168.10.10 + - 8.8.8.8 + - 203.0.113.0 \ No newline at end of file diff --git a/test/e2e/test_data/iac/resource_prioritising/min_severity_with_skip_rule/terraform/main.tf b/test/e2e/test_data/iac/resource_prioritising/min_severity_with_skip_rule/terraform/main.tf new file mode 100644 index 000000000..f86f542fc --- /dev/null +++ b/test/e2e/test_data/iac/resource_prioritising/min_severity_with_skip_rule/terraform/main.tf @@ -0,0 +1,15 @@ +resource "aws_db_instance" "PtShGgAdi4" { + #ts:minseverity=High + #ts:skip=AWS.RDS.DataSecurity.High.0414 need to skip this rule + allocated_storage = 20 + storage_type = "gp2" + engine = "mysql" + engine_version = "5.7" + instance_class = "db.t2.micro" + name = "ptshggadi4" + backup_retention_period = 0 + ca_cert_identifier = "rds-ca-2019" + username = "slaflheafllaflaehf" + password = "something" + skip_final_snapshot = true +} \ No newline at end of file