Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions prowler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to the **Prowler SDK** are documented in this file.

- `entra_app_registration_client_secret_unused` check for M365 provider [(#11232)](https://github.com/prowler-cloud/prowler/pull/11232)
- `cloudsql_instance_cmek_encryption_enabled` check for GCP provider [(#11023)](https://github.com/prowler-cloud/prowler/pull/11023)
- Google Workspace Groups service with 3 new checks [(#11186)](https://github.com/prowler-cloud/prowler/pull/11186)

### 🔄 Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,9 @@
{
"Id": "3.1.6.1",
"Description": "Ensure accessing groups from outside this organization is set to private",
"Checks": [],
"Checks": [
"groups_external_access_restricted"
],
"Attributes": [
{
"Section": "3 Apps",
Expand All @@ -1243,7 +1245,9 @@
{
"Id": "3.1.6.2",
"Description": "Ensure creating groups is restricted",
"Checks": [],
"Checks": [
"groups_creation_restricted"
],
"Attributes": [
{
"Section": "3 Apps",
Expand All @@ -1264,7 +1268,9 @@
{
"Id": "3.1.6.3",
"Description": "Ensure default for permission to view conversations is restricted",
"Checks": [],
"Checks": [
"groups_view_conversations_restricted"
],
"Attributes": [
{
"Section": "3 Apps",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,9 @@
{
"Id": "GWS.GROUPS.1.1",
"Description": "Group access from outside the organization SHALL be disabled unless explicitly granted by the group owner",
"Checks": [],
"Checks": [
"groups_external_access_restricted"
],
"Attributes": [
{
"Section": "Groups",
Expand All @@ -1639,7 +1641,9 @@
{
"Id": "GWS.GROUPS.1.2",
"Description": "Group owners' ability to add external members to groups SHOULD be disabled unless necessary for agency mission fulfillment",
"Checks": [],
"Checks": [
"groups_creation_restricted"
],
"Attributes": [
{
"Section": "Groups",
Expand All @@ -1652,7 +1656,9 @@
{
"Id": "GWS.GROUPS.1.3",
"Description": "Group owners' ability to allow posting to a group by an external, non-group member SHOULD be disabled unless necessary for agency mission fulfillment",
"Checks": [],
"Checks": [
"groups_creation_restricted"
],
"Attributes": [
{
"Section": "Groups",
Expand All @@ -1665,7 +1671,9 @@
{
"Id": "GWS.GROUPS.2.1",
"Description": "Group creation SHOULD be restricted to admins within the organization unless necessary for agency mission fulfillment",
"Checks": [],
"Checks": [
"groups_creation_restricted"
],
"Attributes": [
{
"Section": "Groups",
Expand All @@ -1678,7 +1686,9 @@
{
"Id": "GWS.GROUPS.3.1",
"Description": "The default permission to view conversations SHOULD be set to All Group Members",
"Checks": [],
"Checks": [
"groups_view_conversations_restricted"
],
"Attributes": [
{
"Section": "Groups",
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from prowler.providers.common.provider import Provider
from prowler.providers.googleworkspace.services.groups.groups_service import (
Groups,
)

groups_client = Groups(Provider.get_global_provider())
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"Provider": "googleworkspace",
"CheckID": "groups_creation_restricted",
"CheckTitle": "Group creation is restricted to admins with no external members or incoming email",
"CheckType": [],
"ServiceName": "groups",
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "NotDefined",
"ResourceGroup": "collaboration",
"Description": "Google Groups for Business **creation settings** control who can create groups and whether group owners can add external members or allow incoming email from outside the organization. Restricting creation to admins and disabling external member and incoming email options limits the attack surface.",
"Risk": "Allowing any user to create groups with external members or incoming email from outside increases the risk of **unauthorized data sharing**, **spam delivery**, and **shadow IT** groups that bypass organizational controls.",
"RelatedUrl": "",
"AdditionalURLs": [
"https://support.google.com/a/answer/10308022",
"https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings"
],
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Groups for Business**\n3. Click **Creating groups**\n4. Select **Only organization admins can create groups**\n5. Uncheck **Group owners can allow external members**\n6. Uncheck **Group owners can allow incoming email from outside the organization**\n7. Click **Save**",
"Terraform": ""
},
"Recommendation": {
"Text": "Restrict **group creation** to **organization admins** and disable **external member** and **incoming email** options to maintain control over group membership and communication boundaries.",
"Url": "https://hub.prowler.com/check/groups_creation_restricted"
}
},
"Categories": [
"trust-boundaries"
],
"DependsOn": [],
"RelatedTo": [
"groups_external_access_restricted",
"groups_view_conversations_restricted"
],
"Notes": ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from typing import List

from prowler.lib.check.models import Check, CheckReportGoogleWorkspace
from prowler.providers.googleworkspace.services.groups.groups_client import (
groups_client,
)


class groups_creation_restricted(Check):
"""Check that group creation is restricted to admins only with no external members or incoming email.

This check verifies three sub-settings:
- Only organization admins can create groups (not all users)
- Group owners cannot allow external members
- Group owners cannot allow incoming email from outside the organization
"""

def execute(self) -> List[CheckReportGoogleWorkspace]:
findings = []

if groups_client.policies_fetched:
report = CheckReportGoogleWorkspace(
metadata=self.metadata(),
resource=groups_client.policies,
resource_id="groupsPolicies",
resource_name="Groups Policies",
customer_id=groups_client.provider.identity.customer_id,
)

policies = groups_client.policies
domain = groups_client.provider.identity.domain

access_level = policies.create_groups_access_level
external_members = policies.owners_can_allow_external_members
incoming_mail = policies.owners_can_allow_incoming_mail_from_public

issues = []

# Check creation access level
# Default is USERS_IN_DOMAIN (insecure) — only ADMIN_ONLY is compliant
if access_level is None or access_level != "ADMIN_ONLY":
effective = access_level or "USERS_IN_DOMAIN (default)"
issues.append(
f"group creation is set to {effective} instead of ADMIN_ONLY"
)

# Check external members
# Default is false (secure) — only false is compliant
if external_members is True:
issues.append("group owners can allow external members")

# Check incoming mail from outside
# Default is false (secure) — only true is non-compliant
if incoming_mail is True:
issues.append(
"group owners can allow incoming email from outside the organization"
)

if not issues:
report.status = "PASS"
report.status_extended = (
f"Group creation is properly restricted in domain {domain}: "
f"admin-only creation, no external members, "
f"no incoming email from outside."
)
else:
report.status = "FAIL"
issues_text = "; ".join(issues)
report.status_extended = (
f"Group creation is not fully restricted "
f"in domain {domain}: {issues_text}."
)

findings.append(report)

return findings
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"Provider": "googleworkspace",
"CheckID": "groups_external_access_restricted",
"CheckTitle": "Accessing groups from outside the organization is set to private",
"CheckType": [],
"ServiceName": "groups",
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "NotDefined",
"ResourceGroup": "collaboration",
"Description": "Google Groups for Business **external access** controls whether people outside the organization can view and search for groups. When set to private, only users within the domain can discover and access groups, while external users can still email a group if the group's own settings allow it.",
"Risk": "Allowing external access to groups exposes **group names, descriptions, and membership** to anyone outside the organization, increasing the risk of **information disclosure** and enabling external parties to identify targets for **social engineering attacks**.",
"RelatedUrl": "",
"AdditionalURLs": [
"https://support.google.com/a/answer/10308022",
"https://cloud.google.com/identity/docs/concepts/supported-policy-api-settings"
],
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "1. Sign in to the Google **Admin console** at https://admin.google.com\n2. Navigate to **Apps** > **Google Workspace** > **Groups for Business**\n3. Click **Sharing options**\n4. Set **Accessing groups from outside this organization** to **Private**\n5. Click **Save**",
"Terraform": ""
},
"Recommendation": {
"Text": "Set **external group access** to **private** to prevent external parties from viewing or searching for organizational groups.",
"Url": "https://hub.prowler.com/check/groups_external_access_restricted"
}
},
"Categories": [
"trust-boundaries"
],
"DependsOn": [],
"RelatedTo": [
"groups_creation_restricted",
"groups_view_conversations_restricted"
],
"Notes": ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from typing import List

from prowler.lib.check.models import Check, CheckReportGoogleWorkspace
from prowler.providers.googleworkspace.services.groups.groups_client import (
groups_client,
)


class groups_external_access_restricted(Check):
"""Check that accessing groups from outside the organization is set to private.

This check verifies that the domain-level Groups for Business policy
restricts external access so that only domain users can view groups,
preventing information exposure to external parties.
"""

def execute(self) -> List[CheckReportGoogleWorkspace]:
findings = []

if groups_client.policies_fetched:
report = CheckReportGoogleWorkspace(
metadata=self.metadata(),
resource=groups_client.policies,
resource_id="groupsPolicies",
resource_name="Groups Policies",
customer_id=groups_client.provider.identity.customer_id,
)

collaboration = groups_client.policies.collaboration_capability
domain = groups_client.provider.identity.domain

if collaboration == "DOMAIN_USERS_ONLY":
report.status = "PASS"
report.status_extended = (
f"Groups external access is set to private (domain users only) "
f"in domain {domain}."
)
elif collaboration is None:
report.status = "PASS"
report.status_extended = (
f"Groups external access uses Google's secure default "
f"configuration (private) in domain {domain}."
)
else:
report.status = "FAIL"
report.status_extended = (
f"Groups external access is set to {collaboration} "
f"in domain {domain}. "
f"External access should be set to private (domain users only)."
)

findings.append(report)

return findings
Loading
Loading