Repository: aquasecurity/tfsec
Pull request #980 (2021-07-30 10:49:42)

Add more google iam checks


Patch:
diff --git a/internal/app/tfsec/rules/google/iam/no_folder_level_default_service_account_assignment_rule.go b/internal/app/tfsec/rules/google/iam/no_folder_level_default_service_account_assignment_rule.go
new file mode 100644
index 000000000..fc3ef8b77
--- /dev/null
+++ b/internal/app/tfsec/rules/google/iam/no_folder_level_default_service_account_assignment_rule.go
@@ -0,0 +1,116 @@
+package iam
+
+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:   "iam",
+		ShortCode: "no-folder-level-default-service-account-assignment",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Roles should not be assigned to default service accounts",
+			Explanation: `Default service accounts should not be used - consider creating specialised service accounts for individual purposes.`,
+			Impact:      "Violation of principal of least privilege",
+			Resolution:  "Use specialised service accounts for specific purposes.",
+			BadExample: []string{`
+resource "google_folder_iam_member" "folder-123" {
+	folder = "folder-123"
+	role    = "roles/whatever"
+	member  = "123-compute@developer.gserviceaccount.com"
+}
+`,
+				`
+resource "google_folder_iam_member" "folder-123" {
+	folder = "folder-123"
+	role    = "roles/whatever"
+	member  = "123@appspot.gserviceaccount.com"
+}
+`, `
+data "google_compute_default_service_account" "default" {
+}
+
+resource "google_folder_iam_member" "folder-123" {
+	folder = "folder-123"
+	role    = "roles/whatever"
+	member  = data.google_compute_default_service_account.default.id
+}
+`,
+			},
+			GoodExample: []string{`
+resource "google_service_account" "test" {
+	account_id   = "account123"
+	display_name = "account123"
+}
+			  
+resource "google_folder_iam_member" "folder-123" {
+	folder = "folder-123"
+	role    = "roles/whatever"
+	member  = "serviceAccount:${google_service_account.test.email}"
+}
+`,
+			},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_folder_iam",
+				"",
+			},
+		},
+		Provider:        provider.GoogleProvider,
+		RequiredTypes:   []string{"resource"},
+		RequiredLabels:  []string{"google_folder_iam_binding", "google_folder_iam_member"},
+		DefaultSeverity: severity.Medium,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, ctx *hclcontext.Context) {
+
+			if memberAttr := resourceBlock.GetAttribute("member"); memberAttr.IsNotNil() {
+				if memberAttr.IsString() {
+					if isMemberDefaultServiceAccount(memberAttr.Value().AsString()) {
+						set.AddResult().
+							WithAttribute(memberAttr).
+							WithDescription("Resource '%s' assigns a role to a default service account.", resourceBlock.FullName())
+					}
+				} else {
+					computeServiceAccounts := ctx.GetDatasByType("google_compute_default_service_account")
+					serviceAccounts := append(computeServiceAccounts, ctx.GetResourcesByType("google_app_engine_default_service_account")...)
+					for _, serviceAccount := range serviceAccounts {
+						if memberAttr.ReferencesBlock(serviceAccount) {
+							set.AddResult().
+								WithAttribute(memberAttr).
+								WithDescription("Resource '%s' assigns a role to a default service account.", resourceBlock.FullName())
+						}
+					}
+				}
+			}
+
+			if membersAttr := resourceBlock.GetAttribute("members"); membersAttr.IsNotNil() {
+				for _, member := range membersAttr.ValueAsStrings() {
+					if isMemberDefaultServiceAccount(member) {
+						set.AddResult().
+							WithAttribute(membersAttr).
+							WithDescription("Resource '%s' assigns a role to a default service account.", resourceBlock.FullName())
+					}
+				}
+				computeServiceAccounts := ctx.GetDatasByType("google_compute_default_service_account")
+				serviceAccounts := append(computeServiceAccounts, ctx.GetResourcesByType("google_app_engine_default_service_account")...)
+				for _, serviceAccount := range serviceAccounts {
+					if membersAttr.ReferencesBlock(serviceAccount) {
+						set.AddResult().
+							WithAttribute(membersAttr).
+							WithDescription("Resource '%s' assigns a role to a default service account.", resourceBlock.FullName())
+					}
+				}
+			}
+
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/google/iam/no_folder_level_service_account_impersonation_rule.go b/internal/app/tfsec/rules/google/iam/no_folder_level_service_account_impersonation_rule.go
new file mode 100644
index 000000000..8c1ede9e9
--- /dev/null
+++ b/internal/app/tfsec/rules/google/iam/no_folder_level_service_account_impersonation_rule.go
@@ -0,0 +1,70 @@
+package iam
+
+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:   "iam",
+		ShortCode: "no-folder-level-service-account-impersonation",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Users should not be granted service account access at the folder level",
+			Explanation: `Users with service account access at folder level can impersonate any service account. Instead, they should be given access to particular service accounts as required.`,
+			Impact:      "Privilege escalation, impersonation of any/all services",
+			Resolution:  "Provide access at the service-level instead of folder-level, if required",
+			BadExample: []string{
+				`
+resource "google_folder_iam_binding" "folder-123" {
+	folder = "folder-123"
+	role    = "roles/iam.serviceAccountUser"
+}
+`,
+				`
+resource "google_folder_iam_binding" "folder-123" {
+	folder = "folder-123"
+	role    = "roles/iam.serviceAccountTokenCreator"
+}
+`,
+			},
+			GoodExample: []string{`
+resource "google_folder_iam_binding" "folder-123" {
+	folder = "folder-123"
+	role    = "roles/nothingInParticular"
+}
+			`},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_folder_iam",
+				"https://cloud.google.com/iam/docs/impersonating-service-accounts",
+			},
+		},
+		Provider:        provider.GoogleProvider,
+		RequiredTypes:   []string{"resource"},
+		RequiredLabels:  []string{"google_folder_iam_binding", "google_folder_iam_member"},
+		DefaultSeverity: severity.Medium,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, _ *hclcontext.Context) {
+
+			roleAttr := resourceBlock.GetAttribute("role")
+			if !roleAttr.IsString() {
+				return
+			}
+			if roleAttr.IsAny("roles/iam.serviceAccountUser", "roles/iam.serviceAccountTokenCreator") {
+				set.AddResult().
+					WithAttribute(roleAttr).
+					WithDescription("Resource '%s' grants service account access to a user at folder level.", resourceBlock.FullName())
+			}
+
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/google/iam/no_org_level_default_service_account_assignment_rule.go b/internal/app/tfsec/rules/google/iam/no_org_level_default_service_account_assignment_rule.go
new file mode 100644
index 000000000..5a07001dc
--- /dev/null
+++ b/internal/app/tfsec/rules/google/iam/no_org_level_default_service_account_assignment_rule.go
@@ -0,0 +1,116 @@
+package iam
+
+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:   "iam",
+		ShortCode: "no-org-level-default-service-account-assignment",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Roles should not be assigned to default service accounts",
+			Explanation: `Default service accounts should not be used - consider creating specialised service accounts for individual purposes.`,
+			Impact:      "Violation of principal of least privilege",
+			Resolution:  "Use specialised service accounts for specific purposes.",
+			BadExample: []string{`
+resource "google_organization_iam_member" "org-123" {
+	org_id = "organization-123"
+	role    = "roles/whatever"
+	member  = "123-compute@developer.gserviceaccount.com"
+}
+`,
+				`
+resource "google_organization_iam_member" "org-123" {
+	org_id = "org-123"
+	role    = "roles/whatever"
+	member  = "123@appspot.gserviceaccount.com"
+}
+`, `
+data "google_compute_default_service_account" "default" {
+}
+
+resource "google_organization_iam_member" "org-123" {
+	org_id = "org-123"
+	role    = "roles/whatever"
+	member  = data.google_compute_default_service_account.default.id
+}
+`,
+			},
+			GoodExample: []string{`
+resource "google_service_account" "test" {
+	account_id   = "account123"
+	display_name = "account123"
+}
+			  
+resource "google_organization_iam_member" "org-123" {
+	org_id = "org-123"
+	role    = "roles/whatever"
+	member  = "serviceAccount:${google_service_account.test.email}"
+}
+`,
+			},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_organization_iam",
+				"",
+			},
+		},
+		Provider:        provider.GoogleProvider,
+		RequiredTypes:   []string{"resource"},
+		RequiredLabels:  []string{"google_organization_iam_binding", "google_organization_iam_member"},
+		DefaultSeverity: severity.Medium,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, ctx *hclcontext.Context) {
+
+			if memberAttr := resourceBlock.GetAttribute("member"); memberAttr.IsNotNil() {
+				if memberAttr.IsString() {
+					if isMemberDefaultServiceAccount(memberAttr.Value().AsString()) {
+						set.AddResult().
+							WithAttribute(memberAttr).
+							WithDescription("Resource '%s' assigns a role to a default service account.", resourceBlock.FullName())
+					}
+				} else {
+					computeServiceAccounts := ctx.GetDatasByType("google_compute_default_service_account")
+					serviceAccounts := append(computeServiceAccounts, ctx.GetResourcesByType("google_app_engine_default_service_account")...)
+					for _, serviceAccount := range serviceAccounts {
+						if memberAttr.ReferencesBlock(serviceAccount) {
+							set.AddResult().
+								WithAttribute(memberAttr).
+								WithDescription("Resource '%s' assigns a role to a default service account.", resourceBlock.FullName())
+						}
+					}
+				}
+			}
+
+			if membersAttr := resourceBlock.GetAttribute("members"); membersAttr.IsNotNil() {
+				for _, member := range membersAttr.ValueAsStrings() {
+					if isMemberDefaultServiceAccount(member) {
+						set.AddResult().
+							WithAttribute(membersAttr).
+							WithDescription("Resource '%s' assigns a role to a default service account.", resourceBlock.FullName())
+					}
+				}
+				computeServiceAccounts := ctx.GetDatasByType("google_compute_default_service_account")
+				serviceAccounts := append(computeServiceAccounts, ctx.GetResourcesByType("google_app_engine_default_service_account")...)
+				for _, serviceAccount := range serviceAccounts {
+					if membersAttr.ReferencesBlock(serviceAccount) {
+						set.AddResult().
+							WithAttribute(membersAttr).
+							WithDescription("Resource '%s' assigns a role to a default service account.", resourceBlock.FullName())
+					}
+				}
+			}
+
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/google/iam/no_org_level_service_account_impersonation_rule.go b/internal/app/tfsec/rules/google/iam/no_org_level_service_account_impersonation_rule.go
new file mode 100644
index 000000000..8c34345d7
--- /dev/null
+++ b/internal/app/tfsec/rules/google/iam/no_org_level_service_account_impersonation_rule.go
@@ -0,0 +1,70 @@
+package iam
+
+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:   "iam",
+		ShortCode: "no-org-level-service-account-impersonation",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Users should not be granted service account access at the organization level",
+			Explanation: `Users with service account access at organization level can impersonate any service account. Instead, they should be given access to particular service accounts as required.`,
+			Impact:      "Privilege escalation, impersonation of any/all services",
+			Resolution:  "Provide access at the service-level instead of organization-level, if required",
+			BadExample: []string{
+				`
+resource "google_organization_iam_binding" "organization-123" {
+	org_id  = "org-123"
+	role    = "roles/iam.serviceAccountUser"
+}
+`,
+				`
+resource "google_organization_iam_binding" "organization-123" {
+	org_id  = "org-123"
+	role    = "roles/iam.serviceAccountTokenCreator"
+}
+`,
+			},
+			GoodExample: []string{`
+resource "google_organization_iam_binding" "organization-123" {
+	org_id  = "org-123"
+	role    = "roles/nothingInParticular"
+}
+			`},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_organization_iam",
+				"https://cloud.google.com/iam/docs/impersonating-service-accounts",
+			},
+		},
+		Provider:        provider.GoogleProvider,
+		RequiredTypes:   []string{"resource"},
+		RequiredLabels:  []string{"google_organization_iam_binding", "google_organization_iam_member"},
+		DefaultSeverity: severity.Medium,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, _ *hclcontext.Context) {
+
+			roleAttr := resourceBlock.GetAttribute("role")
+			if !roleAttr.IsString() {
+				return
+			}
+			if roleAttr.IsAny("roles/iam.serviceAccountUser", "roles/iam.serviceAccountTokenCreator") {
+				set.AddResult().
+					WithAttribute(roleAttr).
+					WithDescription("Resource '%s' grants service account access to a user at organization level.", resourceBlock.FullName())
+			}
+
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/google/iam/no_default_service_account_assignment_rule.go b/internal/app/tfsec/rules/google/iam/no_project_level_default_service_account_assignment_rule.go
similarity index 96%
rename from internal/app/tfsec/rules/google/iam/no_default_service_account_assignment_rule.go
rename to internal/app/tfsec/rules/google/iam/no_project_level_default_service_account_assignment_rule.go
index c56e75a49..7965829f9 100644
--- a/internal/app/tfsec/rules/google/iam/no_default_service_account_assignment_rule.go
+++ b/internal/app/tfsec/rules/google/iam/no_project_level_default_service_account_assignment_rule.go
@@ -21,7 +21,7 @@ import (
 func init() {
 	scanner.RegisterCheckRule(rule.Rule{
 		Service:   "iam",
-		ShortCode: "no-default-service-account-assignment",
+		ShortCode: "no-project-level-default-service-account-assignment",
 		Documentation: rule.RuleDocumentation{
 			Summary:     "Roles should not be assigned to default service accounts",
 			Explanation: `Default service accounts should not be used - consider creating specialised service accounts for individual purposes.`,
@@ -71,7 +71,7 @@ resource "google_project_iam_member" "project-123" {
 		},
 		Provider:        provider.GoogleProvider,
 		RequiredTypes:   []string{"resource"},
-		RequiredLabels:  []string{"google_project_iam_binding,", "google_project_iam_member"},
+		RequiredLabels:  []string{"google_project_iam_binding", "google_project_iam_member"},
 		DefaultSeverity: severity.Medium,
 		CheckFunc: func(set result.Set, resourceBlock block.Block, ctx *hclcontext.Context) {
 


Test patch:
diff --git a/internal/app/tfsec/rules/google/iam/no_folder_level_default_service_account_assignment_rule_test.go b/internal/app/tfsec/rules/google/iam/no_folder_level_default_service_account_assignment_rule_test.go
new file mode 100644
index 000000000..9611fcad7
--- /dev/null
+++ b/internal/app/tfsec/rules/google/iam/no_folder_level_default_service_account_assignment_rule_test.go
@@ -0,0 +1,53 @@
+package iam
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_GoogleNoDefaultServiceAccountAtFolderAssignment_FailureExamples(t *testing.T) {
+	expectedCode := "google-iam-no-folder-level-default-service-account-assignment"
+
+	check, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.FailNow()
+	}
+	for i, badExample := range check.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", check.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, check.ID(), "", results)
+	}
+}
+
+func Test_GoogleNoDefaultServiceAccountAtFolderAssignment_SuccessExamples(t *testing.T) {
+	expectedCode := "google-iam-no-folder-level-default-service-account-assignment"
+
+	check, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.FailNow()
+	}
+	for i, example := range check.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", check.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", check.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/google/iam/no_folder_level_service_account_impersonation_rule_test.go b/internal/app/tfsec/rules/google/iam/no_folder_level_service_account_impersonation_rule_test.go
new file mode 100644
index 000000000..7b6c027c8
--- /dev/null
+++ b/internal/app/tfsec/rules/google/iam/no_folder_level_service_account_impersonation_rule_test.go
@@ -0,0 +1,53 @@
+package iam
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_GoogleNoFolderLevelServiceAccountAccess_FailureExamples(t *testing.T) {
+	expectedCode := "google-iam-no-folder-level-service-account-impersonation"
+
+	check, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.FailNow()
+	}
+	for i, badExample := range check.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", check.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, check.ID(), "", results)
+	}
+}
+
+func Test_GoogleNoFolderLevelServiceAccountAccess_SuccessExamples(t *testing.T) {
+	expectedCode := "google-iam-no-folder-level-service-account-impersonation"
+
+	check, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.FailNow()
+	}
+	for i, example := range check.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", check.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", check.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/google/iam/no_org_level_default_service_account_assignment_rule_test.go b/internal/app/tfsec/rules/google/iam/no_org_level_default_service_account_assignment_rule_test.go
new file mode 100644
index 000000000..ddebec541
--- /dev/null
+++ b/internal/app/tfsec/rules/google/iam/no_org_level_default_service_account_assignment_rule_test.go
@@ -0,0 +1,53 @@
+package iam
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_GoogleNoDefaultServiceAccountAtOrgAssignment_FailureExamples(t *testing.T) {
+	expectedCode := "google-iam-no-org-level-default-service-account-assignment"
+
+	check, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.FailNow()
+	}
+	for i, badExample := range check.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", check.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, check.ID(), "", results)
+	}
+}
+
+func Test_GoogleNoDefaultServiceAccountAtOrgAssignment_SuccessExamples(t *testing.T) {
+	expectedCode := "google-iam-no-org-level-default-service-account-assignment"
+
+	check, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.FailNow()
+	}
+	for i, example := range check.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", check.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", check.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/google/iam/no_org_level_service_account_impersonation_rule_test.go b/internal/app/tfsec/rules/google/iam/no_org_level_service_account_impersonation_rule_test.go
new file mode 100644
index 000000000..ce9777c33
--- /dev/null
+++ b/internal/app/tfsec/rules/google/iam/no_org_level_service_account_impersonation_rule_test.go
@@ -0,0 +1,53 @@
+package iam
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_GoogleNoOrganizationLevelServiceAccountAccess_FailureExamples(t *testing.T) {
+	expectedCode := "google-iam-no-org-level-service-account-impersonation"
+
+	check, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.FailNow()
+	}
+	for i, badExample := range check.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", check.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, check.ID(), "", results)
+	}
+}
+
+func Test_GoogleNoOrganizationLevelServiceAccountAccess_SuccessExamples(t *testing.T) {
+	expectedCode := "google-iam-no-org-level-service-account-impersonation"
+
+	check, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.FailNow()
+	}
+	for i, example := range check.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", check.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", check.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/google/iam/no_default_service_account_assignment_rule_test.go b/internal/app/tfsec/rules/google/iam/no_project_level_default_service_account_assignment_rule_test.go
similarity index 89%
rename from internal/app/tfsec/rules/google/iam/no_default_service_account_assignment_rule_test.go
rename to internal/app/tfsec/rules/google/iam/no_project_level_default_service_account_assignment_rule_test.go
index cad9a0215..ddad9f33c 100644
--- a/internal/app/tfsec/rules/google/iam/no_default_service_account_assignment_rule_test.go
+++ b/internal/app/tfsec/rules/google/iam/no_project_level_default_service_account_assignment_rule_test.go
@@ -10,7 +10,7 @@ import (
 )
 
 func Test_GoogleNoDefaultServiceAccountAssignment_FailureExamples(t *testing.T) {
-	expectedCode := "google-iam-no-default-service-account-assignment"
+	expectedCode := "google-iam-no-project-level-default-service-account-assignment"
 
 	check, err := scanner.GetRuleById(expectedCode)
 	if err != nil {
@@ -32,7 +32,7 @@ func Test_GoogleNoDefaultServiceAccountAssignment_FailureExamples(t *testing.T)
 }
 
 func Test_GoogleNoDefaultServiceAccountAssignment_SuccessExamples(t *testing.T) {
-	expectedCode := "google-iam-no-default-service-account-assignment"
+	expectedCode := "google-iam-no-project-level-default-service-account-assignment"
 
 	check, err := scanner.GetRuleById(expectedCode)
 	if err != nil {