Repository: aquasecurity/tfsec
Pull request #1101 (2021-10-02 14:06:40)

add check for github require_signed_commits


Patch:
diff --git a/internal/app/tfsec/rules/github/repositories/enable_signed_commits_rule.go b/internal/app/tfsec/rules/github/repositories/enable_signed_commits_rule.go
new file mode 100644
index 000000000..6f8f0afff
--- /dev/null
+++ b/internal/app/tfsec/rules/github/repositories/enable_signed_commits_rule.go
@@ -0,0 +1,68 @@
+package repositories
+
+// ATTENTION!
+// This rule was autogenerated!
+// Before making changes, consider updating the generator.
+
+import (
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/pkg/provider"
+	"github.com/aquasecurity/tfsec/pkg/result"
+	"github.com/aquasecurity/tfsec/pkg/rule"
+	"github.com/aquasecurity/tfsec/pkg/severity"
+)
+
+func init() {
+	scanner.RegisterCheckRule(rule.Rule{
+		Provider:  provider.GitHubProvider,
+		Service:   "repositories",
+		ShortCode: "require-signed-commits",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Require signed commits should be enabled.",
+			Explanation: `You can do this setting the <code>require_signed_commits</code> attribute to 'true'.`,
+			Impact:      "You cannot guarantee the source of unsigned commits.",
+			Resolution:  "Require signed commits for all protected branches.",
+			BadExample: []string{`
+resource "github_branch_protection" "bad_example" {
+  repository_id = github_repository.example.node_id
+  
+  pattern          = "main"
+  enforce_admins   = true
+  allows_deletions = true
+  require_signed_commits = false
+}
+`},
+			GoodExample: []string{`
+resource "github_branch_protection" "good_example" {
+  repository_id = github_repository.example.node_id
+  pattern          = "main"
+  enforce_admins   = true
+  allows_deletions = true
+  require_signed_commits = true
+}
+`},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/github/latest/docs/resources/branch_protection#require_signed_commits",
+				"https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification",
+			},
+		},
+		RequiredTypes: []string{
+			"resource",
+		},
+		RequiredLabels: []string{
+			"github_branch_protection",
+		},
+		DefaultSeverity: severity.High,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, module block.Module) {
+			if requireSignedCommitsAttr := resourceBlock.GetAttribute("require_signed_commits"); requireSignedCommitsAttr.IsNil() { // alert on use of default value
+				set.AddResult().
+					WithDescription("Resource '%s' uses default value for require_signed_commits", resourceBlock.FullName())
+			} else if requireSignedCommitsAttr.IsFalse() {
+				set.AddResult().
+					WithDescription("Resource '%s' does not have require_signed_commits set to true", resourceBlock.FullName()).
+					WithAttribute(requireSignedCommitsAttr)
+			}
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/github/repositories/vulnerability_alerts_rule.go b/internal/app/tfsec/rules/github/repositories/vulnerability_alerts_rule.go
index 9d1f8cfda..6bf63e3e0 100644
--- a/internal/app/tfsec/rules/github/repositories/vulnerability_alerts_rule.go
+++ b/internal/app/tfsec/rules/github/repositories/vulnerability_alerts_rule.go
@@ -20,7 +20,7 @@ func init() {
 		ShortCode: "vulnerability-alerts",
 		Documentation: rule.RuleDocumentation{
 			Summary:     "Github vulnerability alerts should be enabled.",
-			Explanation: `You can do this by either setting <code>vulnerability_alerts</code> attribute to 'true'.`,
+			Explanation: `You can do this by setting the <code>vulnerability_alerts</code> attribute to 'true'.`,
 			Impact:      "Insecure vulnerabilities might be used in the codebase.",
 			Resolution:  "Enable vulnerability alerts for all repositories.",
 			BadExample: []string{`


Test patch:
diff --git a/internal/app/tfsec/rules/github/repositories/enable_signed_commits_rule_test.go b/internal/app/tfsec/rules/github/repositories/enable_signed_commits_rule_test.go
new file mode 100644
index 000000000..7413d78c1
--- /dev/null
+++ b/internal/app/tfsec/rules/github/repositories/enable_signed_commits_rule_test.go
@@ -0,0 +1,53 @@
+package repositories
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_GithubRequireSignedCommits_FailureExamples(t *testing.T) {
+	expectedCode := "github-repositories-require-signed-commits"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, badExample := range rule.Documentation.BadExample {
+		t.Logf("Running bad example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(badExample) == "" {
+			t.Fatalf("bad example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, rule.ID(), "", results)
+	}
+}
+
+func Test_GithubRequireSignedCommits_SuccessExamples(t *testing.T) {
+	expectedCode := "github-repositories-require-signed-commits"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, example := range rule.Documentation.GoodExample {
+		t.Logf("Running good example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(example) == "" {
+			t.Fatalf("good example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", rule.ID(), results)
+	}
+}