iam

package
v0.10.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2024 License: MIT Imports: 6 Imported by: 1

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CheckNoConditionOnWorkloadIdentityPoolProvider = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0068",
		Provider:    providers.GoogleProvider,
		Service:     "iam",
		ShortCode:   "no-conditions-workload-identity-pool-provider",
		Summary:     "A configuration for an external workload identity pool provider should have conditions set",
		Impact:      "Allows an external attacker to authenticate as the attached service account and act with its permissions",
		Resolution:  "Set conditions on this provider, for example by restricting it to only be allowed from repositories in your GitHub organization",
		Explanation: `In GitHub Actions, one can authenticate to Google Cloud by setting values for workload_identity_provider and service_account and requesting a short-lived OIDC token which is then used to execute commands as that Service Account. If you don't specify a condition in the workload identity provider pool configuration, then any GitHub Action can assume this role and act as that Service Account.`,
		Links: []string{
			"https://www.revblock.dev/exploiting-misconfigured-google-cloud-service-accounts-from-github-actions/",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoConditionOnWorkloadIdentityPoolProviderGoodExamples,
			BadExamples:         terraformNoConditionOnWorkloadIdentityPoolProviderBadExamples,
			Links:               terraformNoConditionOnWorkloadIdentityPoolProviderLinks,
			RemediationMarkdown: terraformNoConditionOnWorkloadIdentityPoolProviderMarkdown,
		},
		Severity: severity.High,
	},
	func(s *state.State) (results scan.Results) {
		for _, provider := range s.Google.IAM.WorkloadIdentityPoolProviders {
			if provider.AttributeCondition.IsEmpty() {
				results.Add(
					"This workload identity pool provider configuration has no conditions set.",
					provider.AttributeCondition,
				)
			} else {
				results.AddPassed(provider)
			}
		}
		return
	},
)
View Source
var CheckNoDefaultNetwork = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0010",
		Provider:    providers.GoogleProvider,
		Service:     "iam",
		ShortCode:   "no-default-network",
		Summary:     "Default network should not be created at project level",
		Impact:      "Exposure of internal infrastructure/services to public internet",
		Resolution:  "Disable automatic default network creation",
		Explanation: `The default network which is provided for a project contains multiple insecure firewall rules which allow ingress to the project's infrastructure. Creation of this network should therefore be disabled.`,
		Links:       []string{},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoDefaultNetworkGoodExamples,
			BadExamples:         terraformNoDefaultNetworkBadExamples,
			Links:               terraformNoDefaultNetworkLinks,
			RemediationMarkdown: terraformNoDefaultNetworkRemediationMarkdown,
		},
		Severity: severity.High,
	},
	func(s *state.State) (results scan.Results) {

		for _, project := range s.Google.IAM.AllProjects() {
			if project.Metadata.IsUnmanaged() {
				continue
			}
			if project.AutoCreateNetwork.IsTrue() {
				results.Add(
					"Project has automatic network creation enabled.",
					project.AutoCreateNetwork,
				)
			} else {
				results.AddPassed(project)
			}
		}
		return
	},
)
View Source
var CheckNoFolderLevelDefaultServiceAccountAssignment = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0004",
		Provider:    providers.GoogleProvider,
		Service:     "iam",
		ShortCode:   "no-folder-level-default-service-account-assignment",
		Summary:     "Roles should not be assigned to default service accounts",
		Impact:      "Violation of principal of least privilege",
		Resolution:  "Use specialised service accounts for specific purposes.",
		Explanation: `Default service accounts should not be used - consider creating specialised service accounts for individual purposes.`,
		Links: []string{
			"",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoFolderLevelDefaultServiceAccountAssignmentGoodExamples,
			BadExamples:         terraformNoFolderLevelDefaultServiceAccountAssignmentBadExamples,
			Links:               terraformNoFolderLevelDefaultServiceAccountAssignmentLinks,
			RemediationMarkdown: terraformNoFolderLevelDefaultServiceAccountAssignmentRemediationMarkdown,
		},
		Severity: severity.Medium,
	},
	func(s *state.State) (results scan.Results) {
		for _, folder := range s.Google.IAM.AllFolders() {
			for _, member := range folder.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.DefaultServiceAccount.IsTrue() {
					results.Add(
						"Role is assigned to a default service account at folder level.",
						member.DefaultServiceAccount,
					)
				} else if isMemberDefaultServiceAccount(member.Member.Value()) {
					results.Add(
						"Role is assigned to a default service account at folder level.",
						member.Member,
					)
				} else {
					results.AddPassed(&member)
				}

			}
			for _, binding := range folder.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if binding.IncludesDefaultServiceAccount.IsTrue() {
					results.Add(
						"Role is assigned to a default service account at folder level.",
						binding.IncludesDefaultServiceAccount,
					)
					continue
				}
				for _, member := range binding.Members {
					if isMemberDefaultServiceAccount(member.Value()) {
						results.Add(
							"Role is assigned to a default service account at folder level.",
							member,
						)
					} else {
						results.AddPassed(member)
					}
				}
			}

		}
		return
	},
)
View Source
var CheckNoFolderLevelServiceAccountImpersonation = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0005",
		Provider:    providers.GoogleProvider,
		Service:     "IAM",
		ShortCode:   "no-folder-level-service-account-impersonation",
		Summary:     "Users should not be granted service account access at the folder level",
		Impact:      "Privilege escalation, impersonation of any/all services",
		Resolution:  "Provide access at the service-level instead of folder-level, if required",
		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.`,
		Links: []string{
			"https://cloud.google.com/iam/docs/impersonating-service-accounts",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoFolderLevelServiceAccountImpersonationGoodExamples,
			BadExamples:         terraformNoFolderLevelServiceAccountImpersonationBadExamples,
			Links:               terraformNoFolderLevelServiceAccountImpersonationLinks,
			RemediationMarkdown: terraformNoFolderLevelServiceAccountImpersonationRemediationMarkdown,
		},
		Severity: severity.Medium,
	},
	func(s *state.State) (results scan.Results) {
		for _, folder := range s.Google.IAM.AllFolders() {
			for _, member := range folder.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Role.IsOneOf("roles/iam.serviceAccountUser", "roles/iam.serviceAccountTokenCreator") {
					results.Add(
						"Service account access is granted to a user at folder level.",
						member.Role,
					)
				} else {
					results.AddPassed(&member)
				}

			}
			for _, binding := range folder.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if binding.Role.IsOneOf("roles/iam.serviceAccountUser", "roles/iam.serviceAccountTokenCreator") {
					results.Add(
						"Service account access is granted to a user at folder level.",
						binding.Role,
					)
				} else {
					results.AddPassed(&binding)
				}

			}
		}
		return
	},
)
View Source
var CheckNoOrgLevelDefaultServiceAccountAssignment = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0008",
		Provider:    providers.GoogleProvider,
		Service:     "iam",
		ShortCode:   "no-org-level-default-service-account-assignment",
		Summary:     "Roles should not be assigned to default service accounts",
		Impact:      "Violation of principal of least privilege",
		Resolution:  "Use specialised service accounts for specific purposes.",
		Explanation: `Default service accounts should not be used - consider creating specialised service accounts for individual purposes.`,
		Links: []string{
			"",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoOrgLevelDefaultServiceAccountAssignmentGoodExamples,
			BadExamples:         terraformNoOrgLevelDefaultServiceAccountAssignmentBadExamples,
			Links:               terraformNoOrgLevelDefaultServiceAccountAssignmentLinks,
			RemediationMarkdown: terraformNoOrgLevelDefaultServiceAccountAssignmentRemediationMarkdown,
		},
		Severity: severity.Medium,
	},
	func(s *state.State) (results scan.Results) {
		for _, org := range s.Google.IAM.Organizations {
			for _, binding := range org.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if binding.IncludesDefaultServiceAccount.IsTrue() {
					results.Add(
						"Role is assigned to a default service account at organisation level.",
						binding.IncludesDefaultServiceAccount,
					)
				} else {
					for _, member := range binding.Members {
						if isMemberDefaultServiceAccount(member.Value()) {
							results.Add(
								"Role is assigned to a default service account at organisation level.",
								member,
							)
						} else {
							results.AddPassed(member)
						}

					}
				}
			}
			for _, member := range org.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if isMemberDefaultServiceAccount(member.Member.Value()) {
					results.Add(
						"Role is assigned to a default service account at organisation level.",
						member.Member,
					)
				} else if member.DefaultServiceAccount.IsTrue() {
					results.Add(
						"Role is assigned to a default service account at organisation level.",
						member.DefaultServiceAccount,
					)
				} else {
					results.AddPassed(&member)
				}

			}
		}
		return
	},
)
View Source
var CheckNoOrgLevelServiceAccountImpersonation = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0009",
		Provider:    providers.GoogleProvider,
		Service:     "iam",
		ShortCode:   "no-org-level-service-account-impersonation",
		Summary:     "Users should not be granted service account access at the organization level",
		Impact:      "Privilege escalation, impersonation of any/all services",
		Resolution:  "Provide access at the service-level instead of organization-level, if required",
		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.`,
		Links: []string{
			"https://cloud.google.com/iam/docs/impersonating-service-accounts",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoOrgLevelServiceAccountImpersonationGoodExamples,
			BadExamples:         terraformNoOrgLevelServiceAccountImpersonationBadExamples,
			Links:               terraformNoOrgLevelServiceAccountImpersonationLinks,
			RemediationMarkdown: terraformNoOrgLevelServiceAccountImpersonationRemediationMarkdown,
		},
		Severity: severity.Medium,
	},
	func(s *state.State) (results scan.Results) {
		for _, org := range s.Google.IAM.Organizations {
			for _, member := range org.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Role.IsOneOf("roles/iam.serviceAccountUser", "roles/iam.serviceAccountTokenCreator") {
					results.Add(
						"Service account access is granted to a user at organization level.",
						member.Role,
					)
				} else {
					results.AddPassed(&member)
				}

			}
			for _, binding := range org.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if binding.Role.IsOneOf("roles/iam.serviceAccountUser", "roles/iam.serviceAccountTokenCreator") {
					results.Add(
						"Service account access is granted to a user at organization level.",
						binding.Role,
					)
				} else {
					results.AddPassed(&binding)
				}

			}
		}
		return
	},
)
View Source
var CheckNoPrivilegedServiceAccounts = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0007",
		Provider:    providers.GoogleProvider,
		Service:     "iam",
		ShortCode:   "no-privileged-service-accounts",
		Summary:     "Service accounts should not have roles assigned with excessive privileges",
		Impact:      "Cloud account takeover if a resource using a service account is compromised",
		Resolution:  "Limit service account access to minimal required set",
		Explanation: `Service accounts should have a minimal set of permissions assigned in order to do their job. They should never have excessive access as if compromised, an attacker can escalate privileges and take over the entire account.`,
		Links: []string{
			"https://cloud.google.com/iam/docs/understanding-roles",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoPrivilegedServiceAccountsGoodExamples,
			BadExamples:         terraformNoPrivilegedServiceAccountsBadExamples,
			Links:               terraformNoPrivilegedServiceAccountsLinks,
			RemediationMarkdown: terraformNoPrivilegedServiceAccountsRemediationMarkdown,
		},
		Severity: severity.High,
	},
	func(s *state.State) (results scan.Results) {
		for _, project := range s.Google.IAM.AllProjects() {
			for _, member := range project.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Member.StartsWith("serviceAccount:") {
					if isRolePrivileged(member.Role.Value()) {
						results.Add(
							"Service account is granted a privileged role.",
							member.Role,
						)
					} else {
						results.AddPassed(&member)
					}

				}
			}
			for _, binding := range project.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if isRolePrivileged(binding.Role.Value()) {
					for _, member := range binding.Members {
						if member.StartsWith("serviceAccount:") {
							results.Add(
								"Service account is granted a privileged role.",
								binding.Role,
							)
						} else {
							results.AddPassed(&binding)
						}

					}
				}
			}
		}
		for _, folder := range s.Google.IAM.AllFolders() {
			for _, member := range folder.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Member.StartsWith("serviceAccount:") {
					if isRolePrivileged(member.Role.Value()) {
						results.Add(
							"Service account is granted a privileged role.",
							member.Role,
						)
					} else {
						results.AddPassed(&member)
					}

				}
			}
			for _, binding := range folder.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if isRolePrivileged(binding.Role.Value()) {
					for _, member := range binding.Members {
						if member.StartsWith("serviceAccount:") {
							results.Add(
								"Service account is granted a privileged role.",
								binding.Role,
							)
						} else {
							results.AddPassed(member)
						}

					}
				}
			}

		}

		for _, org := range s.Google.IAM.Organizations {
			for _, member := range org.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Member.StartsWith("serviceAccount:") {
					if isRolePrivileged(member.Role.Value()) {
						results.Add(
							"Service account is granted a privileged role.",
							member.Role,
						)
					} else {
						results.AddPassed(&member)
					}

				}
			}
			for _, binding := range org.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if isRolePrivileged(binding.Role.Value()) {
					for _, member := range binding.Members {
						if member.StartsWith("serviceAccount:") {
							results.Add(
								"Service account is granted a privileged role.",
								binding.Role,
							)
						} else {
							results.AddPassed(member)
						}

					}
				}
			}

		}

		return
	},
)
View Source
var CheckNoProjectLevelDefaultServiceAccountAssignment = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0006",
		Provider:    providers.GoogleProvider,
		Service:     "iam",
		ShortCode:   "no-project-level-default-service-account-assignment",
		Summary:     "Roles should not be assigned to default service accounts",
		Impact:      "Violation of principal of least privilege",
		Resolution:  "Use specialised service accounts for specific purposes.",
		Explanation: `Default service accounts should not be used - consider creating specialised service accounts for individual purposes.`,
		Links: []string{
			"",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoProjectLevelDefaultServiceAccountAssignmentGoodExamples,
			BadExamples:         terraformNoProjectLevelDefaultServiceAccountAssignmentBadExamples,
			Links:               terraformNoProjectLevelDefaultServiceAccountAssignmentLinks,
			RemediationMarkdown: terraformNoProjectLevelDefaultServiceAccountAssignmentRemediationMarkdown,
		},
		Severity: severity.Medium,
	},
	func(s *state.State) (results scan.Results) {
		for _, project := range s.Google.IAM.AllProjects() {
			for _, binding := range project.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if binding.IncludesDefaultServiceAccount.IsTrue() {
					results.Add(
						"Role is assigned to a default service account at project level.",
						binding.IncludesDefaultServiceAccount,
					)
				} else {
					for _, member := range binding.Members {
						if isMemberDefaultServiceAccount(member.Value()) {
							results.Add(
								"Role is assigned to a default service account at project level.",
								member,
							)
						} else {
							results.AddPassed(member)
						}

					}
				}
			}
			for _, member := range project.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.DefaultServiceAccount.IsTrue() {
					results.Add(
						"Role is assigned to a default service account at project level.",
						member.DefaultServiceAccount,
					)
				} else if isMemberDefaultServiceAccount(member.Member.Value()) {
					results.Add(
						"Role is assigned to a default service account at project level.",
						member.Member,
					)
				} else {
					results.AddPassed(&member)
				}

			}
		}
		return
	},
)
View Source
var CheckNoProjectLevelServiceAccountImpersonation = rules.Register(
	scan.Rule{
		AVDID:       "AVD-GCP-0011",
		Provider:    providers.GoogleProvider,
		Service:     "iam",
		ShortCode:   "no-project-level-service-account-impersonation",
		Summary:     "Users should not be granted service account access at the project level",
		Impact:      "Privilege escalation, impersonation of any/all services",
		Resolution:  "Provide access at the service-level instead of project-level, if required",
		Explanation: `Users with service account access at project level can impersonate any service account. Instead, they should be given access to particular service accounts as required.`,
		Links: []string{
			"https://cloud.google.com/iam/docs/impersonating-service-accounts",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoProjectLevelServiceAccountImpersonationGoodExamples,
			BadExamples:         terraformNoProjectLevelServiceAccountImpersonationBadExamples,
			Links:               terraformNoProjectLevelServiceAccountImpersonationLinks,
			RemediationMarkdown: terraformNoProjectLevelServiceAccountImpersonationRemediationMarkdown,
		},
		Severity: severity.Medium,
	},
	func(s *state.State) (results scan.Results) {
		for _, project := range s.Google.IAM.AllProjects() {
			for _, member := range project.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Role.IsOneOf("roles/iam.serviceAccountUser", "roles/iam.serviceAccountTokenCreator") {
					results.Add(
						"Service account access is granted to a user at project level.",
						member.Role,
					)
				} else {
					results.AddPassed(&member)
				}
			}
			for _, binding := range project.Bindings {
				if binding.Metadata.IsUnmanaged() {
					continue
				}
				if binding.Role.IsOneOf("roles/iam.serviceAccountUser", "roles/iam.serviceAccountTokenCreator") {
					results.Add(
						"Service account access is granted to a user at project level.",
						binding.Role,
					)
				} else {
					results.AddPassed(&binding)
				}

			}
		}
		return
	},
)
View Source
var CheckNoUserGrantedPermissions = rules.Register(
	scan.Rule{
		AVDID:      "AVD-GCP-0003",
		Provider:   providers.GoogleProvider,
		Service:    "iam",
		ShortCode:  "no-user-granted-permissions",
		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.`,
		Links: []string{
			"https://cloud.google.com/iam/docs/overview#permissions",
			"https://cloud.google.com/resource-manager/reference/rest/v1/projects/setIamPolicy",
		},
		Terraform: &scan.EngineMetadata{
			GoodExamples:        terraformNoUserGrantedPermissionsGoodExamples,
			BadExamples:         terraformNoUserGrantedPermissionsBadExamples,
			Links:               terraformNoUserGrantedPermissionsLinks,
			RemediationMarkdown: terraformNoUserGrantedPermissionsRemediationMarkdown,
		},
		Severity: severity.Medium,
	},
	func(s *state.State) (results scan.Results) {
		for _, project := range s.Google.IAM.AllProjects() {
			for _, member := range project.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Member.StartsWith("user:") {
					results.Add(
						"Permissions are granted directly to a user.",
						member.Role,
					)
				} else {
					results.AddPassed(&member)
				}

			}
			for _, binding := range project.Bindings {
				for _, member := range binding.Members {
					if member.StartsWith("user:") {
						results.Add(
							"Permissions are granted directly to a user.",
							binding.Role,
						)
					} else {
						results.AddPassed(member)
					}

				}
			}
		}

		for _, folder := range s.Google.IAM.AllFolders() {
			for _, member := range folder.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Member.StartsWith("user:") {
					results.Add(
						"Permissions are granted directly to a user.",
						member.Role,
					)
				} else {
					results.AddPassed(&member)
				}

			}
			for _, binding := range folder.Bindings {
				for _, member := range binding.Members {
					if member.StartsWith("user:") {
						results.Add(
							"Permissions are granted directly to a user.",
							binding.Role,
						)
					} else {
						results.AddPassed(member)
					}

				}
			}
		}

		for _, org := range s.Google.IAM.Organizations {
			for _, member := range org.Members {
				if member.Metadata.IsUnmanaged() {
					continue
				}
				if member.Member.StartsWith("user:") {
					results.Add(
						"Permissions are granted directly to a user.",
						member.Role,
					)
				} else {
					results.AddPassed(&member)
				}

			}
			for _, binding := range org.Bindings {
				for _, member := range binding.Members {
					if member.StartsWith("user:") {
						results.Add(
							"Permissions are granted directly to a user.",
							binding.Role,
						)
					} else {
						results.AddPassed(member)
					}

				}
			}
		}

		return
	},
)

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL