Repository: aquasecurity/tfsec
Pull request #944 (2021-07-23 13:04:50)

Add rule for google sql backups


Patch:
diff --git a/internal/app/tfsec/rules/google/sql/enable_backup_rule.go b/internal/app/tfsec/rules/google/sql/enable_backup_rule.go
new file mode 100644
index 000000000..0aea125ca
--- /dev/null
+++ b/internal/app/tfsec/rules/google/sql/enable_backup_rule.go
@@ -0,0 +1,91 @@
+package sql
+
+import (
+	"fmt"
+
+	"github.com/aquasecurity/tfsec/pkg/result"
+	"github.com/aquasecurity/tfsec/pkg/severity"
+
+	"github.com/aquasecurity/tfsec/pkg/provider"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/hclcontext"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
+
+	"github.com/aquasecurity/tfsec/pkg/rule"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+)
+
+func init() {
+	scanner.RegisterCheckRule(rule.Rule{
+		Service:   "sql",
+		ShortCode: "enable-backup",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Enable automated backups to recover from data-loss",
+			Explanation: `Automated backups are not enabled by default. Backups are an easy way to restore data in a corruption or data-loss scenario.`,
+			Impact:      "No recovery of lost or corrupted data",
+			Resolution:  "Enable automated backups",
+			BadExample: `
+resource "google_sql_database_instance" "db" {
+	name             = "db"
+	database_version = "POSTGRES_12"
+	region           = "us-central1"
+	settings {
+		backup_configuration {
+			enabled = false
+		}
+	}
+}
+			`,
+			GoodExample: `
+resource "google_sql_database_instance" "db" {
+	name             = "db"
+	database_version = "POSTGRES_12"
+	region           = "us-central1"
+	settings {
+		backup_configuration {
+			enabled = true
+		}
+	}
+}
+			`,
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance#settings.backup_configuration.enabled=true",
+				"https://cloud.google.com/sql/docs/mysql/backup-recovery/backups",
+			},
+		},
+		Provider:        provider.GoogleProvider,
+		RequiredTypes:   []string{"resource"},
+		RequiredLabels:  []string{"google_sql_database_instance"},
+		DefaultSeverity: severity.Medium,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, _ *hclcontext.Context) {
+
+			settingsBlock := resourceBlock.GetBlock("settings")
+			if settingsBlock == nil {
+				set.Add(
+					result.New(resourceBlock).
+						WithDescription(fmt.Sprintf("Resource '%s' does not have backups enabled.", resourceBlock.FullName())),
+				)
+				return
+			}
+
+			if backupBlock := settingsBlock.GetBlock("backup_configuration"); backupBlock == nil {
+				set.Add(
+					result.New(resourceBlock).
+						WithDescription(fmt.Sprintf("Resource '%s' does not have backups enabled.", resourceBlock.FullName())),
+				)
+			} else if enabledAttr := backupBlock.GetAttribute("enabled"); enabledAttr == nil {
+				set.Add(
+					result.New(resourceBlock).
+						WithDescription(fmt.Sprintf("Resource '%s' does not have backups enabled.", resourceBlock.FullName())),
+				)
+			} else if enabledAttr.IsFalse() {
+				set.Add(
+					result.New(resourceBlock).
+						WithDescription(fmt.Sprintf("Resource '%s' has backups explicitly disabled.", resourceBlock.FullName())),
+				)
+			}
+		},
+	})
+}


Test patch:
diff --git a/internal/app/tfsec/rules/google/sql/enable_backup_rule_test.go b/internal/app/tfsec/rules/google/sql/enable_backup_rule_test.go
new file mode 100644
index 000000000..292babd7f
--- /dev/null
+++ b/internal/app/tfsec/rules/google/sql/enable_backup_rule_test.go
@@ -0,0 +1,70 @@
+package sql
+
+import (
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_GoogleEnableBackup(t *testing.T) {
+	expectedCode := "google-sql-enable-backup"
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode string
+		mustExcludeResultCode string
+	}{
+		{
+			name: "rule matches when backups are disabled explicitly",
+			source: `
+resource "google_sql_database_instance" "db" {
+	name             = "db"
+	database_version = "POSTGRES_12"
+	region           = "us-central1"
+	settings {
+		backup_configuration {
+			enabled = false
+		}
+	}
+}
+`,
+			mustIncludeResultCode: expectedCode,
+		},
+		{
+			name: "rule matches when backups are disabled by default",
+			source: `
+resource "google_sql_database_instance" "db" {
+	name             = "db"
+	database_version = "POSTGRES_12"
+	region           = "us-central1"
+}
+`,
+			mustIncludeResultCode: expectedCode,
+		},
+		{
+			name: "rule does not match when backups are enabled",
+			source: `
+resource "google_sql_database_instance" "db" {
+	name             = "db"
+	database_version = "POSTGRES_12"
+	region           = "us-central1"
+	settings {
+		backup_configuration {
+			enabled = true
+		}
+	}
+}
+`,
+			mustExcludeResultCode: expectedCode,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+
+			results := testutil.ScanHCL(test.source, t)
+			testutil.AssertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+}