Repository: aquasecurity/tfsec
Pull request #908 (2021-07-20 15:22:10)

Add google storage public access checks
SAAS-2122/SAAS-2123


Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4284876ce..0b4b6a342 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,12 +26,12 @@ The generator will determine the next available code and create the check and th
 
 We currently use the following list of severities:
 
-| Level    | When to use                                                                     | Example                                               |
-| -------- | ------------------------------------------------------------------------------- | ----------------------------------------------------- |
-| Critical | A direct risk of compromise to infrastructure, data or other assets.            | A database resource is marked as publicly accessible. |
-| High     | A misconfiguration which compromises security of the infrastructure.            | A storage medium is unencrypted.                      |
-| Medium   | Best practice has not been followed which impacts security of the organisation. | "Force destroy" is enabled on a bucket.               |
-| Low      | Best practice has not been followed, which decreases operational efficiency.    | Description missing on security group rule.           |
+| Level    | When to use                                                                        | Example                                               |
+| -------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------- |
+| Critical | Direct risk of compromise to infrastructure, data or other assets.                 | A database resource is marked as publicly accessible. |
+| High     | A misconfiguration that compromises the security of the infrastructure.            | A storage medium is unencrypted.                      |
+| Medium   | Best practice has not been followed that impacts the security of the organisation. | "Force destroy" is enabled on a bucket.               |
+| Low      | Best practice has not been followed, which decreases operational efficiency.       | Description missing on security group rule.           |
 
 
 ### Writing Your Check Code
diff --git a/cmd/gen-rules-markdown/main.go b/cmd/gen-rules-markdown/main.go
deleted file mode 100644
index 32a541915..000000000
--- a/cmd/gen-rules-markdown/main.go
+++ /dev/null
@@ -1,194 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"github.com/spf13/cobra"
-
-	_ "github.com/aquasecurity/tfsec/internal/app/tfsec/rules"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
-	"github.com/aquasecurity/tfsec/pkg/rule"
-)
-
-func main() {
-	if err := rootCmd.Execute(); err != nil {
-		fmt.Println(err)
-		os.Exit(1)
-	}
-}
-
-var rootCmd = &cobra.Command{
-	Use: "gen-rules-markdown",
-	RunE: func(cmd *cobra.Command, args []string) error {
-
-		projectRoot, err := os.Getwd()
-		if err != nil {
-			panic(err)
-		}
-
-		rulesRoot := filepath.Join(projectRoot, "internal", "app", "tfsec", "rules")
-		testRoot := filepath.Join(projectRoot, "internal", "app", "tfsec", "test")
-
-		var imports []string
-
-		for _, rule := range scanner.GetRegisteredRules() {
-
-			oldPath := filepath.Join(rulesRoot, fmt.Sprintf("%s.go", strings.ToLower(rule.LegacyID)))
-			packageName := strings.ReplaceAll(rule.Service, "-", "")
-
-			newBaseDir := filepath.Join(rulesRoot, string(rule.Provider), packageName)
-			newBasePath := filepath.Join(newBaseDir, fmt.Sprintf("%s_rule", strings.ReplaceAll(rule.ShortCode, "-", "_")))
-
-			newTestPath := newBasePath + "_test.go"
-			newPath := newBasePath + ".go"
-
-			oldTestPath := filepath.Join(testRoot, fmt.Sprintf("%s_test.go", strings.ToLower(rule.LegacyID)))
-
-			importPath := fmt.Sprintf("github.com/aquasecurity/tfsec/internal/app/tfsec/rules/%s/%s", rule.Provider, packageName)
-			newImp := `_ "` + importPath + `"`
-			var importExists bool
-			for _, imp := range imports {
-				if imp == newImp {
-					importExists = true
-					break
-				}
-			}
-			if !importExists {
-				imports = append(imports, newImp)
-			}
-
-			if _, err := os.Stat(oldPath); err == os.ErrNotExist {
-				panic(fmt.Errorf("rule definition file not found: %s", rule.LegacyID))
-			}
-
-			if err := os.MkdirAll(newBaseDir, 0700); err != nil {
-				panic(err)
-			}
-
-			ruleData, err := ioutil.ReadFile(oldPath)
-			if err != nil {
-				panic(err)
-			}
-
-			//transform rule here
-			ruleData = []byte(strings.ReplaceAll(string(ruleData), "package rules", fmt.Sprintf("package %s", packageName)))
-
-			lines := strings.Split(string(ruleData), "\n")
-			var idName string
-			lines, idName = rewriteRule(rule, lines)
-
-			fmt.Printf("Writing rule file %s from %s...", newPath, oldPath)
-			if err := ioutil.WriteFile(newPath, []byte(strings.Join(lines, "\n")), 0600); err != nil {
-				panic(err)
-			}
-
-			if _, err := os.Stat(oldTestPath); err == nil {
-				testData, err := ioutil.ReadFile(oldTestPath)
-				if err != nil {
-					panic(err)
-				}
-
-				testData = []byte(strings.ReplaceAll(string(testData), `"github.com/aquasecurity/tfsec/internal/app/tfsec/rules"`, ""))
-				testData = []byte(strings.ReplaceAll(string(testData), "package test", fmt.Sprintf("package %s", packageName)))
-				testData = []byte(strings.ReplaceAll(string(testData), "rules."+idName, fmt.Sprintf(`"%s"`, rule.ID())))
-
-				lines := strings.Split(string(testData), "\n")
-				lines = rewriteTest(rule, idName, lines)
-
-				fmt.Printf("Writing test file %s from %s...\n", newTestPath, oldTestPath)
-				if err := ioutil.WriteFile(newTestPath, []byte(strings.Join(lines, "\n")), 0600); err != nil {
-					panic(err)
-				}
-
-			}
-
-		}
-
-		importTemplate := fmt.Sprintf(`package rules
-		
-	import (
-		%s
-	)
-
-		`, strings.Join(imports, "\n"))
-
-		return ioutil.WriteFile(projectRoot+"/internal/app/tfsec/rules/init.go", []byte(importTemplate), 0600)
-	},
-}
-
-func rewriteRule(rule rule.Rule, oldLines []string) ([]string, string) {
-	var newLines []string
-
-	consts := make(map[string]string)
-
-	var inMultiLine bool
-	var multi string
-	var multiName string
-	var idName string
-
-	for _, line := range oldLines {
-
-		if inMultiLine {
-
-			multi = multi + "\n" + line
-			if strings.Count(line, "`") == 1 {
-				consts[multiName] = multi
-				multi = ""
-				inMultiLine = false
-			}
-
-			continue
-		}
-
-		if strings.Contains(line, "const ") {
-			parts := strings.SplitN(line, "=", 2)
-			if len(parts) < 2 {
-				continue
-			}
-			if strings.Count(parts[1], "`") == 1 {
-				inMultiLine = true
-				multi = parts[1]
-				multiName = strings.TrimSpace(strings.ReplaceAll(parts[0], "const", ""))
-				continue
-			}
-			name := strings.TrimSpace(strings.ReplaceAll(parts[0], "const", ""))
-			consts[name] = parts[1]
-			if idName == "" {
-				idName = name
-			}
-			continue
-		}
-
-		newLines = append(newLines, line)
-	}
-
-	var finalLines []string
-
-	for _, line := range newLines {
-		for name, val := range consts {
-			line = strings.ReplaceAll(line, name+",", val+",")
-		}
-		finalLines = append(finalLines, line)
-
-	}
-
-	return finalLines, idName
-
-}
-
-func rewriteTest(rule rule.Rule, idName string, oldLines []string) []string {
-	var newLines []string
-
-	for _, line := range oldLines {
-		// tranbsform line here...
-		line = strings.ReplaceAll(line, "[placeholder]", rule.ID())
-		newLines = append(newLines, line)
-	}
-
-	return newLines
-
-}
diff --git a/cmd/tfsec-skeleton/generate.go b/cmd/tfsec-skeleton/generate.go
index e483d9977..b9f4e0cfa 100644
--- a/cmd/tfsec-skeleton/generate.go
+++ b/cmd/tfsec-skeleton/generate.go
@@ -10,7 +10,7 @@ import (
 	"github.com/liamg/clinch/prompt"
 )
 
-var providers = map[string]string{"AWS": "aws", "Azure": "azu", "GCP": "gcp", "Oracle": "oci", "General": "gen", "DigitalOcean": "dig", "GitHub": "git"}
+var providers = map[string]string{"AWS": "aws", "Azure": "azu", "Google": "gcp", "Oracle": "oci", "General": "gen", "DigitalOcean": "dig", "GitHub": "git"}
 
 type checkSkeleton struct {
 	Provider         string
diff --git a/internal/app/tfsec/rules/google/compute/disk_encryption_customer_keys_rule.go b/internal/app/tfsec/rules/google/compute/disk_encryption_customer_keys_rule.go
index 2c7e3e57f..dc993909f 100644
--- a/internal/app/tfsec/rules/google/compute/disk_encryption_customer_keys_rule.go
+++ b/internal/app/tfsec/rules/google/compute/disk_encryption_customer_keys_rule.go
@@ -17,26 +17,25 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP001",
+		LegacyID:  "GCP001",
 		Service:   "compute",
 		ShortCode: "disk-encryption-customer-keys",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "Encrypted compute disk with unmanaged keys.",
-			Impact:       "Encryption of disk using unmanaged keys.",
-			Resolution:   "Enable encryption using a customer-managed key.",
-			Explanation:  `
+			Summary:    "Encrypted compute disk with unmanaged keys.",
+			Impact:     "Encryption of disk using unmanaged keys.",
+			Resolution: "Enable encryption using a customer-managed key.",
+			Explanation: `
 By default, Compute Engine encrypts all data at rest. Compute Engine handles and manages this encryption for you without any additional actions on your part.
 
 If the <code>disk_encryption_key</code> block is included in the resource declaration then it *must* include a <code>raw_key</code> or <code>kms_key_self_link</code>.
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_compute_disk" "bad_example" {
 	# ...
 }`,
-			GoodExample:  `
+			GoodExample: `
 resource "google_compute_disk" "good_example" {
 	disk_encryption_key {
 		kms_key_self_link = "something"
@@ -49,7 +48,7 @@ resource "google_compute_disk" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/compute_disk.html",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_compute_disk"},
 		DefaultSeverity: severity.High,
diff --git a/internal/app/tfsec/rules/google/compute/disk_encryption_required_rule.go b/internal/app/tfsec/rules/google/compute/disk_encryption_required_rule.go
index 94ba795c8..eba0b79ef 100644
--- a/internal/app/tfsec/rules/google/compute/disk_encryption_required_rule.go
+++ b/internal/app/tfsec/rules/google/compute/disk_encryption_required_rule.go
@@ -12,27 +12,26 @@ import (
 	"github.com/aquasecurity/tfsec/pkg/severity"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP013",
+		LegacyID:  "GCP013",
 		Service:   "compute",
 		ShortCode: "disk-encryption-required",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "The encryption key used to encrypt a compute disk has been specified in plaintext.",
-			Explanation:  `
+			Summary: "The encryption key used to encrypt a compute disk has been specified in plaintext.",
+			Explanation: `
 Sensitive values such as raw encryption keys should not be included in your Terraform code, and should be stored securely by a secrets manager.
 `,
-			Impact:       "The encryption key should be considered compromised as it is not stored securely.",
-			Resolution:   "Reference a managed key rather than include the key in raw format.",
-			BadExample:   `
+			Impact:     "The encryption key should be considered compromised as it is not stored securely.",
+			Resolution: "Reference a managed key rather than include the key in raw format.",
+			BadExample: `
 resource "google_compute_disk" "good_example" {
 	disk_encryption_key {
 		raw_key="b2ggbm8gdGhpcyBpcyBiYWQ="
 	}
 }
 `,
-			GoodExample:  `
+			GoodExample: `
 resource "google_compute_disk" "good_example" {
 	disk_encryption_key {
 		kms_key_self_link = google_kms_crypto_key.my_crypto_key.id
@@ -44,7 +43,7 @@ resource "google_compute_disk" "good_example" {
 				"https://cloud.google.com/compute/docs/disks/customer-supplied-encryption",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_compute_disk"},
 		DefaultSeverity: severity.Critical,
diff --git a/internal/app/tfsec/rules/google/compute/no_public_egress_rule.go b/internal/app/tfsec/rules/google/compute/no_public_egress_rule.go
index 2ab80fd05..6d72cc3f7 100644
--- a/internal/app/tfsec/rules/google/compute/no_public_egress_rule.go
+++ b/internal/app/tfsec/rules/google/compute/no_public_egress_rule.go
@@ -45,7 +45,7 @@ resource "google_compute_firewall" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/compute_firewall.html",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_compute_firewall"},
 		DefaultSeverity: severity.Critical,
diff --git a/internal/app/tfsec/rules/google/compute/no_public_ingress_rule.go b/internal/app/tfsec/rules/google/compute/no_public_ingress_rule.go
index 4f0609b93..63a3bc0e5 100644
--- a/internal/app/tfsec/rules/google/compute/no_public_ingress_rule.go
+++ b/internal/app/tfsec/rules/google/compute/no_public_ingress_rule.go
@@ -45,7 +45,7 @@ resource "google_compute_firewall" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/compute_firewall.html",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_compute_firewall"},
 		DefaultSeverity: severity.Critical,
diff --git a/internal/app/tfsec/rules/google/gke/enforce_pod_security_policy_rule.go b/internal/app/tfsec/rules/google/gke/enforce_pod_security_policy_rule.go
index 7b845aaff..c940dfdc6 100644
--- a/internal/app/tfsec/rules/google/gke/enforce_pod_security_policy_rule.go
+++ b/internal/app/tfsec/rules/google/gke/enforce_pod_security_policy_rule.go
@@ -17,17 +17,16 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP009",
+		LegacyID:  "GCP009",
 		Service:   "gke",
 		ShortCode: "enforce-pod-security-policy",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "Pod security policy enforcement not defined.",
-			Impact:       "Pods could be operating with more permissions than required to be effective",
-			Resolution:   "Use security policies for pods to restrict permissions to those needed to be effective",
-			Explanation:  `
+			Summary:    "Pod security policy enforcement not defined.",
+			Impact:     "Pods could be operating with more permissions than required to be effective",
+			Resolution: "Use security policies for pods to restrict permissions to those needed to be effective",
+			Explanation: `
 By default, Pods in Kubernetes can operate with capabilities beyond what they require. You should constrain the Pod's capabilities to only those required for that workload.
 
 Kubernetes offers controls for restricting your Pods to execute with only explicitly granted capabilities. 
@@ -36,13 +35,13 @@ Pod Security Policy allows you to set smart defaults for your Pods, and enforce
 
 The policies you define should be specific to the needs of your application
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_container_cluster" "bad_example" {
 	pod_security_policy_config {
         enabled = "false"
 	}
 }`,
-			GoodExample:  `
+			GoodExample: `
 resource "google_container_cluster" "good_example" {
 	pod_security_policy_config {
         enabled = "true"
@@ -53,7 +52,7 @@ resource "google_container_cluster" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/container_cluster.html#pod_security_policy_config",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_container_cluster"},
 		DefaultSeverity: severity.High,
diff --git a/internal/app/tfsec/rules/google/gke/metadata_endpoints_disabled_rule.go b/internal/app/tfsec/rules/google/gke/metadata_endpoints_disabled_rule.go
index f350fb8a1..c6846ed58 100644
--- a/internal/app/tfsec/rules/google/gke/metadata_endpoints_disabled_rule.go
+++ b/internal/app/tfsec/rules/google/gke/metadata_endpoints_disabled_rule.go
@@ -17,17 +17,16 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP007",
+		LegacyID:  "GCP007",
 		Service:   "gke",
 		ShortCode: "metadata-endpoints-disabled",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "Legacy metadata endpoints enabled.",
-			Impact:       "Legacy metadata endpoints don't require metadata headers",
-			Resolution:   "Disable legacy metadata endpoints",
-			Explanation:  `
+			Summary:    "Legacy metadata endpoints enabled.",
+			Impact:     "Legacy metadata endpoints don't require metadata headers",
+			Resolution: "Disable legacy metadata endpoints",
+			Explanation: `
 The Compute Engine instance metadata server exposes legacy v0.1 and v1beta1 endpoints, which do not enforce metadata query headers. 
 
 This is a feature in the v1 APIs that makes it more difficult for a potential attacker to retrieve instance metadata. 
@@ -36,13 +35,13 @@ Unless specifically required, we recommend you disable these legacy APIs.
 
 When setting the <code>metadata</code> block, the default value for <code>disable-legacy-endpoints</code> is set to true, they should not be explicitly enabled.
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_container_cluster" "bad_example" {
 	metadata {
     disable-legacy-endpoints = false
   }
 }`,
-			GoodExample:  `
+			GoodExample: `
 resource "google_container_cluster" "good_example" {
 	metadata {
     disable-legacy-endpoints = true
@@ -53,7 +52,7 @@ resource "google_container_cluster" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/container_cluster.html#metadata",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_container_cluster"},
 		DefaultSeverity: severity.High,
diff --git a/internal/app/tfsec/rules/google/gke/no_legacy_authentication_rule.go b/internal/app/tfsec/rules/google/gke/no_legacy_authentication_rule.go
index 80ba18226..76bc9dc78 100644
--- a/internal/app/tfsec/rules/google/gke/no_legacy_authentication_rule.go
+++ b/internal/app/tfsec/rules/google/gke/no_legacy_authentication_rule.go
@@ -17,22 +17,21 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP008",
+		LegacyID:  "GCP008",
 		Service:   "gke",
 		ShortCode: "no-legacy-authentication",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "Legacy client authentication methods utilized.",
-			Impact:       "Username and password authentication methods are less secure",
-			Resolution:   "Use service account or OAuth for authentication",
-			Explanation:  `
+			Summary:    "Legacy client authentication methods utilized.",
+			Impact:     "Username and password authentication methods are less secure",
+			Resolution: "Use service account or OAuth for authentication",
+			Explanation: `
 It is recommended to use Service Accounts and OAuth as authentication methods for accessing the master in the container cluster. 
 
 Basic authentication should be disabled by explicitly unsetting the <code>username</code> and <code>password</code> on the <code>master_auth</code> block.
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_container_cluster" "bad_example" {
 }
 
@@ -46,7 +45,7 @@ resource "google_container_cluster" "gke" {
 	}
 }
 `,
-			GoodExample:  `
+			GoodExample: `
 resource "google_container_cluster" "good_example" {
 	master_auth {
 	    username = ""
@@ -59,7 +58,7 @@ resource "google_container_cluster" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/container_cluster.html#master_auth",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_container_cluster"},
 		DefaultSeverity: severity.High,
diff --git a/internal/app/tfsec/rules/google/gke/node_metadata_security_rule.go b/internal/app/tfsec/rules/google/gke/node_metadata_security_rule.go
index a5a40b55b..1cad6c30a 100644
--- a/internal/app/tfsec/rules/google/gke/node_metadata_security_rule.go
+++ b/internal/app/tfsec/rules/google/gke/node_metadata_security_rule.go
@@ -19,23 +19,22 @@ import (
 	"github.com/zclconf/go-cty/cty"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP006",
+		LegacyID:  "GCP006",
 		Service:   "gke",
 		ShortCode: "node-metadata-security",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "Node metadata value disables metadata concealment.",
-			Impact:       "Metadata that isn't concealed potentially risks leakage of sensitive data",
-			Resolution:   "Set node metadata to SECURE or GKE_METADATA_SERVER",
-			Explanation:  `
+			Summary:    "Node metadata value disables metadata concealment.",
+			Impact:     "Metadata that isn't concealed potentially risks leakage of sensitive data",
+			Resolution: "Set node metadata to SECURE or GKE_METADATA_SERVER",
+			Explanation: `
 If the <code>workload_metadata_config</code> block within <code>node_config</code> is included, the <code>node_metadata</code> attribute should be configured securely.
 
 The attribute should be set to <code>SECURE</code> to use metadata concealment, or <code>GKE_METADATA_SERVER</code> if workload identity is enabled. This ensures that the VM metadata is not unnecessarily exposed to pods.
 
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_container_node_pool" "bad_example" {
 	node_config {
 		workload_metadata_config {
@@ -43,7 +42,7 @@ resource "google_container_node_pool" "bad_example" {
 		}
 	}
 }`,
-			GoodExample:  `
+			GoodExample: `
 resource "google_container_node_pool" "good_example" {
 	node_config {
 		workload_metadata_config {
@@ -56,7 +55,7 @@ resource "google_container_node_pool" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/container_cluster.html#node_metadata",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_container_cluster", "google_container_node_pool"},
 		DefaultSeverity: severity.High,
diff --git a/internal/app/tfsec/rules/google/gke/node_shielding_enabled_rule.go b/internal/app/tfsec/rules/google/gke/node_shielding_enabled_rule.go
index 685cb869e..a05f5d3e2 100644
--- a/internal/app/tfsec/rules/google/gke/node_shielding_enabled_rule.go
+++ b/internal/app/tfsec/rules/google/gke/node_shielding_enabled_rule.go
@@ -17,26 +17,25 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP010",
+		LegacyID:  "GCP010",
 		Service:   "gke",
 		ShortCode: "node-shielding-enabled",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "Shielded GKE nodes not enabled.",
-			Impact:       "Node identity and integrity can't be verified without shielded GKE nodes",
-			Resolution:   "Enable node shielding",
-			Explanation:  `
+			Summary:    "Shielded GKE nodes not enabled.",
+			Impact:     "Node identity and integrity can't be verified without shielded GKE nodes",
+			Resolution: "Enable node shielding",
+			Explanation: `
 CIS GKE Benchmark Recommendation: 6.5.5. Ensure Shielded GKE Nodes are Enabled
 
 Shielded GKE Nodes provide strong, verifiable node identity and integrity to increase the security of GKE nodes and should be enabled on all GKE clusters.
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_container_cluster" "bad_example" {
 	enable_shielded_nodes = "false"
 }`,
-			GoodExample:  `
+			GoodExample: `
 resource "google_container_cluster" "good_example" {
 	enable_shielded_nodes = "true"
 }`,
@@ -45,7 +44,7 @@ resource "google_container_cluster" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/container_cluster.html#enable_shielded_nodes",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_container_cluster"},
 		DefaultSeverity: severity.High,
diff --git a/internal/app/tfsec/rules/google/gke/use_rbac_permissions_rule.go b/internal/app/tfsec/rules/google/gke/use_rbac_permissions_rule.go
index 7533a3d4f..4d4abe338 100644
--- a/internal/app/tfsec/rules/google/gke/use_rbac_permissions_rule.go
+++ b/internal/app/tfsec/rules/google/gke/use_rbac_permissions_rule.go
@@ -19,27 +19,26 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP005",
+		LegacyID:  "GCP005",
 		Service:   "gke",
 		ShortCode: "use-rbac-permissions",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "Legacy ABAC permissions are enabled.",
-			Impact:       "ABAC permissions are less secure than RBAC permissions",
-			Resolution:   "Switch to using RBAC permissions",
-			Explanation:  `
+			Summary:    "Legacy ABAC permissions are enabled.",
+			Impact:     "ABAC permissions are less secure than RBAC permissions",
+			Resolution: "Switch to using RBAC permissions",
+			Explanation: `
 You should disable Attribute-Based Access Control (ABAC), and instead use Role-Based Access Control (RBAC) in GKE.
 
 RBAC has significant security advantages and is now stable in Kubernetes, so it’s time to disable ABAC.
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_container_cluster" "bad_example" {
 	enable_legacy_abac = "true"
 }
 `,
-			GoodExample:  `
+			GoodExample: `
 resource "google_container_cluster" "good_example" {
 	# ...
 	# enable_legacy_abac not set
@@ -51,7 +50,7 @@ resource "google_container_cluster" "good_example" {
 				"https://www.terraform.io/docs/providers/google/r/container_cluster.html#enable_legacy_abac",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_container_cluster"},
 		DefaultSeverity: severity.High,
diff --git a/internal/app/tfsec/rules/google/gke/use_service_account_rule.go b/internal/app/tfsec/rules/google/gke/use_service_account_rule.go
index 26620a916..9f57b38a6 100644
--- a/internal/app/tfsec/rules/google/gke/use_service_account_rule.go
+++ b/internal/app/tfsec/rules/google/gke/use_service_account_rule.go
@@ -18,27 +18,25 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 )
 
-
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP012",
+		LegacyID:  "GCP012",
 		Service:   "gke",
 		ShortCode: "use-service-account",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "Checks for service account defined for GKE nodes",
-			Impact:       "Service accounts with wide permissions can increase the risk of compromise",
-			Resolution:   "Use limited permissions for service accounts to be effective",
-			Explanation:  `
+			Summary:    "Checks for service account defined for GKE nodes",
+			Impact:     "Service accounts with wide permissions can increase the risk of compromise",
+			Resolution: "Use limited permissions for service accounts to be effective",
+			Explanation: `
 You should create and use a minimally privileged service account to run your GKE cluster instead of using the Compute Engine default service account.
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_container_cluster" "bad_example" {
 	node_config {
 	}
 }
 `,
-			GoodExample:  `
+			GoodExample: `
 resource "google_container_cluster" "good_example" {
 	node_config {
 		service_account = "cool-service-account@example.com"
@@ -49,7 +47,7 @@ resource "google_container_cluster" "good_example" {
 				"https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa",
 			},
 		},
-		Provider:        provider.GCPProvider,
+		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
 		RequiredLabels:  []string{"google_container_cluster", "google_container_node_pool"},
 		DefaultSeverity: severity.Medium,
diff --git a/internal/app/tfsec/rules/google/iam/no_user_granted_permissions_rule.go b/internal/app/tfsec/rules/google/iam/no_user_granted_permissions_rule.go
index fb7f33d80..4df5fe51d 100644
--- a/internal/app/tfsec/rules/google/iam/no_user_granted_permissions_rule.go
+++ b/internal/app/tfsec/rules/google/iam/no_user_granted_permissions_rule.go
@@ -20,24 +20,23 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 )
 
-
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
-		LegacyID:   "GCP011",
+		LegacyID:  "GCP011",
 		Service:   "iam",
 		ShortCode: "no-user-granted-permissions",
 		Documentation: rule.RuleDocumentation{
-			Summary:      "IAM granted directly to user.",
-			Impact:       "Users shouldn't have permissions granted to them directly",
-			Resolution:   "Roles should be granted permissions and assigned to users",
-			Explanation:  `
+			Summary:    "IAM granted directly to user.",
+			Impact:     "Users shouldn't have permissions granted to them directly",
+			Resolution: "Roles should be granted permissions and assigned to users",
+			Explanation: `
 Permissions should not be directly granted to users, you identify roles that contain the appropriate permissions, and then grant those roles to the user. 
 
 Granting permissions to users quickly become unwieldy and complex to make large scale changes to remove access to a particular resource.
 
 Permissions should be granted on roles, groups, services accounts instead.
 `,
-			BadExample:   `
+			BadExample: `
 resource "google_project_iam_binding" "bad_example" {
 	members = [
 		"user:test@example.com",
@@ -48,7 +47,7 @@ resource "google_project_iam_member" "bad_example" {
 	member = "user:test@example.com"
 }
 `,
-			GoodExample:  `
+			GoodExample: `
 resource "google_project_iam_binding" "good_example" {
 	members = [
 		"group:test@example.com",
@@ -64,7 +63,7 @@ resource "google_storage_bucket_iam_member" "good_example" {
 				"https://www.terraform.io/docs/providers/google/d/iam_policy.html#members",
 			},
 		},
-		Provider:      provider.GCPProvider,
+		Provider:      provider.GoogleProvider,
 		RequiredTypes: []string{"resource", "data"},
 		RequiredLabels: []string{
 			"google_cloud_run_service_iam_binding",
diff --git a/internal/app/tfsec/rules/google/storage/enable_uniform_bucket_level_access.go b/internal/app/tfsec/rules/google/storage/enable_uniform_bucket_level_access.go
index 2d3711f23..db19af1c7 100644
--- a/internal/app/tfsec/rules/google/storage/enable_uniform_bucket_level_access.go
+++ b/internal/app/tfsec/rules/google/storage/enable_uniform_bucket_level_access.go
@@ -1,4 +1,4 @@
-package iam
+package storage
 
 import (
 	"fmt"
@@ -68,9 +68,10 @@ resource "google_storage_bucket" "static-site" {
 `,
 			Links: []string{
 				"https://cloud.google.com/storage/docs/uniform-bucket-level-access",
+				"https://jbrojbrojbro.medium.com/you-make-the-rules-with-authentication-controls-for-cloud-storage-53c32543747b",
 			},
 		},
-		Provider:      provider.GCPProvider,
+		Provider:      provider.GoogleProvider,
 		RequiredTypes: []string{"resource"},
 		RequiredLabels: []string{
 			"google_storage_bucket",
diff --git a/internal/app/tfsec/rules/google/storage/no_public_access_rule.go b/internal/app/tfsec/rules/google/storage/no_public_access_rule.go
new file mode 100644
index 000000000..34cc8d2b6
--- /dev/null
+++ b/internal/app/tfsec/rules/google/storage/no_public_access_rule.go
@@ -0,0 +1,83 @@
+package storage
+
+import (
+	"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:   "storage",
+		ShortCode: "no-public-access",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Ensure that Cloud Storage bucket is not anonymously or publicly accessible.",
+			Explanation: `Using 'allUsers' or 'allAuthenticatedUsers' as members in an IAM member/binding causes data to be exposed outside of the organisation.`,
+			Impact:      "Public exposure of sensitive data.",
+			Resolution:  "Restrict public access to the bucket.",
+			BadExample: `
+resource "google_storage_bucket_iam_binding" "binding" {
+	bucket = google_storage_bucket.default.name
+	role = "roles/storage.admin"
+	members = [
+		"allAuthenticatedUsers",
+	]
+}
+			`,
+			GoodExample: `
+resource "google_storage_bucket_iam_binding" "binding" {
+	bucket = google_storage_bucket.default.name
+	role = "roles/storage.admin"
+	members = [
+		"user:jane@example.com",
+	]
+}
+			`,
+			Links: []string{
+				"https://jbrojbrojbro.medium.com/you-make-the-rules-with-authentication-controls-for-cloud-storage-53c32543747b",
+			},
+		},
+		Provider:        provider.GoogleProvider,
+		RequiredTypes:   []string{"resource"},
+		RequiredLabels:  []string{"google_storage_bucket_iam_binding", "google_storage_bucket_iam_member"},
+		DefaultSeverity: severity.High,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, _ *hclcontext.Context) {
+
+			if memberAttr := resourceBlock.GetAttribute("member"); memberAttr != nil && memberAttr.IsString() {
+				if googleIAMMemberIsExternal(memberAttr.Value().AsString()) {
+					set.Add(result.New(resourceBlock).
+						WithDescription("Resource '%s' allows public access via member attribute.").
+						WithRange(memberAttr.Range()).
+						WithAttributeAnnotation(memberAttr),
+					)
+				}
+			}
+
+			if membersAttr := resourceBlock.GetAttribute("members"); membersAttr != nil {
+				for _, member := range membersAttr.ValueAsStrings() {
+					if googleIAMMemberIsExternal(member) {
+						set.Add(result.New(resourceBlock).
+							WithDescription("Resource '%s' allows public access via members attribute.").
+							WithRange(membersAttr.Range()).
+							WithAttributeAnnotation(membersAttr),
+						)
+					}
+				}
+			}
+
+		},
+	})
+}
+
+func googleIAMMemberIsExternal(member string) bool {
+	return member == "allUsers" || member == "allAuthenticatedUsers"
+}
diff --git a/pkg/provider/provider.go b/pkg/provider/provider.go
index f90d1488c..fb5b30109 100644
--- a/pkg/provider/provider.go
+++ b/pkg/provider/provider.go
@@ -9,7 +9,7 @@ const (
 	UnknownProvider      Provider = ""
 	AWSProvider          Provider = "aws"
 	AzureProvider        Provider = "azure"
-	GCPProvider          Provider = "google"
+	GoogleProvider       Provider = "google"
 	GeneralProvider      Provider = "general"
 	OracleProvider       Provider = "oracle"
 	DigitalOceanProvider Provider = "digitalocean"


Test patch:
diff --git a/internal/app/tfsec/rules/google/storage/enable_uniform_bucket_level_access_test.go b/internal/app/tfsec/rules/google/storage/enable_uniform_bucket_level_access_test.go
index 7927a2bf2..9a78ad5f7 100644
--- a/internal/app/tfsec/rules/google/storage/enable_uniform_bucket_level_access_test.go
+++ b/internal/app/tfsec/rules/google/storage/enable_uniform_bucket_level_access_test.go
@@ -1,4 +1,4 @@
-package iam
+package storage
 
 import (
 	"testing"
diff --git a/internal/app/tfsec/rules/google/storage/no_public_access_rule_test.go b/internal/app/tfsec/rules/google/storage/no_public_access_rule_test.go
new file mode 100644
index 000000000..da27c524a
--- /dev/null
+++ b/internal/app/tfsec/rules/google/storage/no_public_access_rule_test.go
@@ -0,0 +1,99 @@
+package storage
+
+import (
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_GoogleNoPublicAccess(t *testing.T) {
+	expectedCode := "google-storage-no-public-access"
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode string
+		mustExcludeResultCode string
+	}{
+		{
+			name: "detects issue with iam_binding using allAuthenticatedUsers",
+			source: `
+resource "google_storage_bucket_iam_binding" "binding" {
+	bucket = google_storage_bucket.default.name
+	role = "roles/storage.admin"
+	members = [
+		"allAuthenticatedUsers",
+	]
+}
+`,
+			mustIncludeResultCode: expectedCode,
+		},
+		{
+			name: "detects issue with iam_binding using ",
+			source: `
+resource "google_storage_bucket_iam_binding" "binding" {
+	bucket = google_storage_bucket.default.name
+	role = "roles/storage.admin"
+	members = [
+		"allUsers",
+	]
+}
+`,
+			mustIncludeResultCode: expectedCode,
+		},
+		{
+			name: "detects issue with iam_member using allAuthenticatedUsers",
+			source: `
+resource "google_storage_bucket_iam_member" "member" {
+	bucket = google_storage_bucket.default.name
+	role = "roles/storage.admin"
+	member = "allAuthenticatedUsers"
+}
+`,
+			mustIncludeResultCode: expectedCode,
+		},
+		{
+			name: "detects issue with iam_member using allUsers",
+			source: `
+resource "google_storage_bucket_iam_member" "member" {
+	bucket = google_storage_bucket.default.name
+	role = "roles/storage.admin"
+	member = "allUsers"
+}
+`,
+			mustIncludeResultCode: expectedCode,
+		},
+		{
+			name: "detects no issue for iam_binding when public access is not configured",
+			source: `
+resource "google_storage_bucket_iam_binding" "binding" {
+	bucket = google_storage_bucket.default.name
+	role = "roles/storage.admin"
+	members = [
+		"user:someone@example.com",
+	]
+}
+`,
+			mustExcludeResultCode: expectedCode,
+		},
+		{
+			name: "detects no issue for iam_member when public access is not configured",
+			source: `
+resource "google_storage_bucket_iam_member" "member" {
+	bucket = google_storage_bucket.default.name
+	role = "roles/storage.admin"
+	member = "user:someone@example.com"
+}
+`,
+			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)
+		})
+	}
+}