feat(googleworkspace): add sites, additional_services and marketplace service checks (#11281)

This commit is contained in:
lydiavilchez
2026-05-21 15:52:15 +02:00
committed by GitHub
parent 4dfa2b9748
commit 74622dd576
27 changed files with 1733 additions and 5 deletions
+1
View File
@@ -6,6 +6,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
### 🚀 Added
- Sites, Additional Google services, and Marketplace checks for Google Workspace provider using the Cloud Identity Policy API [(#11281)](https://github.com/prowler-cloud/prowler/pull/11281)
- `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)
@@ -1291,7 +1291,9 @@
{
"Id": "3.1.7.1",
"Description": "Ensure service status for Google Sites is set to off",
"Checks": [],
"Checks": [
"sites_service_disabled"
],
"Attributes": [
{
"Section": "3 Apps",
@@ -1312,7 +1314,9 @@
{
"Id": "3.1.8.1",
"Description": "Ensure access to external Google Groups is OFF for Everyone",
"Checks": [],
"Checks": [
"additionalservices_external_groups_disabled"
],
"Attributes": [
{
"Section": "3 Apps",
@@ -1333,7 +1337,9 @@
{
"Id": "3.1.9.1.1",
"Description": "Ensure users access to Google Workspace Marketplace apps is restricted",
"Checks": [],
"Checks": [
"marketplace_apps_access_restricted"
],
"Attributes": [
{
"Section": "3 Apps",
@@ -374,7 +374,9 @@
{
"Id": "GWS.COMMONCONTROLS.11.1",
"Description": "Only approved Marketplace apps SHALL be allowed for installation",
"Checks": [],
"Checks": [
"marketplace_apps_access_restricted"
],
"Attributes": [
{
"Section": "Common Controls",
@@ -1714,7 +1716,9 @@
{
"Id": "GWS.SITES.1.1",
"Description": "Sites Service SHOULD be disabled for all users",
"Checks": [],
"Checks": [
"sites_service_disabled"
],
"Attributes": [
{
"Section": "Sites",
@@ -0,0 +1,6 @@
from prowler.providers.common.provider import Provider
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServices,
)
additionalservices_client = AdditionalServices(Provider.get_global_provider())
@@ -0,0 +1,37 @@
{
"Provider": "googleworkspace",
"CheckID": "additionalservices_external_groups_disabled",
"CheckTitle": "Access to external Google Groups is off for everyone",
"CheckType": [],
"ServiceName": "additionalservices",
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "NotDefined",
"ResourceGroup": "collaboration",
"Description": "The Additional Google services configuration **disables access to external Google Groups** for all users. This setting controls whether users can access groups created outside the organization from their Google Workspace account.",
"Risk": "When external Google Groups access is enabled, users can access and participate in groups created **outside the organization**, potentially exposing them to **phishing, social engineering, or data leakage** through unmanaged external group communications.",
"RelatedUrl": "",
"AdditionalURLs": [
"https://support.google.com/a/answer/181865",
"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** > **Additional Google services**\n3. Scroll down to **Google Groups**\n4. Set it to **OFF for everyone**\n5. Click **Save**",
"Terraform": ""
},
"Recommendation": {
"Text": "Disable access to **external Google Groups** for all users. If specific users require access to external groups, enable it by exception for those users or groups only.",
"Url": "https://hub.prowler.com/check/additionalservices_external_groups_disabled"
}
},
"Categories": [
"trust-boundaries"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": "This check covers the 'Additional Google services > Google Groups' toggle, which is distinct from the 'Groups for Business' sharing settings covered by the groups service checks."
}
@@ -0,0 +1,55 @@
from typing import List
from prowler.lib.check.models import Check, CheckReportGoogleWorkspace
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_client import (
additionalservices_client,
)
class additionalservices_external_groups_disabled(Check):
"""Check that access to external Google Groups is disabled for all users.
This check verifies that the domain-level Additional Google services policy
disables external Google Groups access, preventing users from accessing
groups created outside the organization.
"""
def execute(self) -> List[CheckReportGoogleWorkspace]:
findings = []
if additionalservices_client.policies_fetched:
report = CheckReportGoogleWorkspace(
metadata=self.metadata(),
resource=additionalservices_client.policies,
resource_id="additionalServicesPolicies",
resource_name="Additional Services Policies",
customer_id=additionalservices_client.provider.identity.customer_id,
)
groups_state = additionalservices_client.policies.groups_service_state
if groups_state == "DISABLED":
report.status = "PASS"
report.status_extended = (
f"Access to external Google Groups is disabled "
f"in domain {additionalservices_client.provider.identity.domain}."
)
else:
report.status = "FAIL"
if groups_state is None:
report.status_extended = (
f"Access to external Google Groups is not explicitly configured "
f"in domain {additionalservices_client.provider.identity.domain}. "
f"The default is ON for everyone. "
f"External Google Groups access should be disabled."
)
else:
report.status_extended = (
f"Access to external Google Groups is enabled "
f"in domain {additionalservices_client.provider.identity.domain}. "
f"External Google Groups access should be disabled."
)
findings.append(report)
return findings
@@ -0,0 +1,92 @@
from typing import Optional
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.googleworkspace.lib.service.service import GoogleWorkspaceService
class AdditionalServices(GoogleWorkspaceService):
"""Google Workspace Additional Services for auditing domain-level service toggles.
Uses the Cloud Identity Policy API v1 to read the service status of
additional Google services configured in the Admin Console, such as
the external Google Groups access toggle.
"""
def __init__(self, provider):
super().__init__(provider)
self.policies = AdditionalServicesPolicies()
self.policies_fetched = False
self._fetch_additional_services_policies()
def _fetch_additional_services_policies(self):
"""Fetch Additional Services policies from the Cloud Identity Policy API v1."""
logger.info("Additional Services - Fetching policies...")
try:
service = self._build_service("cloudidentity", "v1")
if not service:
logger.error("Failed to build Cloud Identity service")
return
request = service.policies().list(
pageSize=100,
filter='setting.type.matches("groups.service_status")',
)
fetch_succeeded = True
while request is not None:
try:
response = request.execute()
for policy in response.get("policies", []):
if not self._is_customer_level_policy(policy):
continue
setting = policy.get("setting", {})
setting_type = setting.get("type", "").removeprefix("settings/")
value = setting.get("value", {})
if setting_type == "groups.service_status":
self.policies.groups_service_state = value.get(
"serviceState"
)
logger.debug(
"Additional Services - Groups service state: "
f"{self.policies.groups_service_state}"
)
request = service.policies().list_next(request, response)
except Exception as error:
self._handle_api_error(
error,
"fetching Additional Services policies",
self.provider.identity.customer_id,
)
fetch_succeeded = False
break
self.policies_fetched = fetch_succeeded
logger.info(
f"Additional Services policies fetched - "
f"Groups service state: {self.policies.groups_service_state}"
)
except Exception as error:
self._handle_api_error(
error,
"fetching Additional Services policies",
self.provider.identity.customer_id,
)
self.policies_fetched = False
class AdditionalServicesPolicies(BaseModel):
"""Model for domain-level Additional Google Services policy settings."""
# groups.service_status
groups_service_state: Optional[str] = None
@@ -0,0 +1,37 @@
{
"Provider": "googleworkspace",
"CheckID": "marketplace_apps_access_restricted",
"CheckTitle": "Users access to Google Workspace Marketplace apps is restricted",
"CheckType": [],
"ServiceName": "marketplace",
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "NotDefined",
"ResourceGroup": "collaboration",
"Description": "The domain-wide Google Workspace Marketplace configuration **restricts which apps users can install**. Only admin-approved apps from the Marketplace allowlist are permitted, preventing users from installing unvetted third-party applications.",
"Risk": "Allowing unrestricted Marketplace app installation exposes the organization to **unvetted third-party applications** that may request broad OAuth scopes, potentially gaining access to **sensitive organizational data** including emails, documents, and calendar events without proper security review.",
"RelatedUrl": "",
"AdditionalURLs": [
"https://support.google.com/a/answer/6089179",
"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 Marketplace apps**\n3. Click **Settings**\n4. Under **Manage Google Workspace Marketplace allowlist access**, select **Allow users to install and run only selected apps from the Marketplace**\n5. Click **Save**",
"Terraform": ""
},
"Recommendation": {
"Text": "Restrict **Marketplace app installation** to only **admin-approved apps** to prevent users from installing unvetted third-party applications that could access sensitive organizational data.",
"Url": "https://hub.prowler.com/check/marketplace_apps_access_restricted"
}
},
"Categories": [
"trust-boundaries"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,61 @@
from typing import List
from prowler.lib.check.models import Check, CheckReportGoogleWorkspace
from prowler.providers.googleworkspace.services.marketplace.marketplace_client import (
marketplace_client,
)
class marketplace_apps_access_restricted(Check):
"""Check that Google Workspace Marketplace app installation is restricted.
This check verifies that the domain-level Marketplace policy restricts
which apps users can install, preventing unvetted third-party applications
from accessing organizational data.
"""
def execute(self) -> List[CheckReportGoogleWorkspace]:
findings = []
if marketplace_client.policies_fetched:
report = CheckReportGoogleWorkspace(
metadata=self.metadata(),
resource=marketplace_client.policies,
resource_id="marketplacePolicies",
resource_name="Marketplace Policies",
customer_id=marketplace_client.provider.identity.customer_id,
)
access_level = marketplace_client.policies.access_level
if access_level == "ALLOW_LISTED_APPS":
report.status = "PASS"
report.status_extended = (
f"Marketplace app installation is restricted to admin-approved apps "
f"in domain {marketplace_client.provider.identity.domain}."
)
elif access_level == "ALLOW_NONE":
report.status = "PASS"
report.status_extended = (
f"Marketplace app installation is fully blocked "
f"in domain {marketplace_client.provider.identity.domain}."
)
else:
report.status = "FAIL"
if access_level is None:
report.status_extended = (
f"Marketplace app access is not explicitly configured "
f"in domain {marketplace_client.provider.identity.domain}. "
f"The default allows all apps. "
f"App installation should be restricted to approved apps only."
)
else:
report.status_extended = (
f"Marketplace allows users to install any app "
f"in domain {marketplace_client.provider.identity.domain}. "
f"App installation should be restricted to approved apps only."
)
findings.append(report)
return findings
@@ -0,0 +1,6 @@
from prowler.providers.common.provider import Provider
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
Marketplace,
)
marketplace_client = Marketplace(Provider.get_global_provider())
@@ -0,0 +1,89 @@
from typing import Optional
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.googleworkspace.lib.service.service import GoogleWorkspaceService
class Marketplace(GoogleWorkspaceService):
"""Google Workspace Marketplace service for auditing domain-level Marketplace policies.
Uses the Cloud Identity Policy API v1 to read the Marketplace app access
settings configured in the Admin Console.
"""
def __init__(self, provider):
super().__init__(provider)
self.policies = MarketplacePolicies()
self.policies_fetched = False
self._fetch_marketplace_policies()
def _fetch_marketplace_policies(self):
"""Fetch Marketplace policies from the Cloud Identity Policy API v1."""
logger.info("Marketplace - Fetching marketplace policies...")
try:
service = self._build_service("cloudidentity", "v1")
if not service:
logger.error("Failed to build Cloud Identity service")
return
request = service.policies().list(
pageSize=100,
filter='setting.type.matches("workspace_marketplace.*")',
)
fetch_succeeded = True
while request is not None:
try:
response = request.execute()
for policy in response.get("policies", []):
if not self._is_customer_level_policy(policy):
continue
setting = policy.get("setting", {})
setting_type = setting.get("type", "").removeprefix("settings/")
value = setting.get("value", {})
if setting_type == "workspace_marketplace.apps_access_options":
self.policies.access_level = value.get("accessLevel")
logger.debug(
"Marketplace access level: "
f"{self.policies.access_level}"
)
request = service.policies().list_next(request, response)
except Exception as error:
self._handle_api_error(
error,
"fetching Marketplace policies",
self.provider.identity.customer_id,
)
fetch_succeeded = False
break
self.policies_fetched = fetch_succeeded
logger.info(
f"Marketplace policies fetched - "
f"Access level: {self.policies.access_level}"
)
except Exception as error:
self._handle_api_error(
error,
"fetching Marketplace policies",
self.provider.identity.customer_id,
)
self.policies_fetched = False
class MarketplacePolicies(BaseModel):
"""Model for domain-level Marketplace policy settings."""
# workspace_marketplace.apps_access_options
access_level: Optional[str] = None
@@ -0,0 +1,6 @@
from prowler.providers.common.provider import Provider
from prowler.providers.googleworkspace.services.sites.sites_service import (
Sites,
)
sites_client = Sites(Provider.get_global_provider())
@@ -0,0 +1,88 @@
from typing import Optional
from pydantic import BaseModel
from prowler.lib.logger import logger
from prowler.providers.googleworkspace.lib.service.service import GoogleWorkspaceService
class Sites(GoogleWorkspaceService):
"""Google Workspace Sites service for auditing domain-level Sites policies.
Uses the Cloud Identity Policy API v1 to read the Sites service status
configured in the Admin Console.
"""
def __init__(self, provider):
super().__init__(provider)
self.policies = SitesPolicies()
self.policies_fetched = False
self._fetch_sites_policies()
def _fetch_sites_policies(self):
"""Fetch Sites policies from the Cloud Identity Policy API v1."""
logger.info("Sites - Fetching sites policies...")
try:
service = self._build_service("cloudidentity", "v1")
if not service:
logger.error("Failed to build Cloud Identity service")
return
request = service.policies().list(
pageSize=100,
filter='setting.type.matches("sites.*")',
)
fetch_succeeded = True
while request is not None:
try:
response = request.execute()
for policy in response.get("policies", []):
if not self._is_customer_level_policy(policy):
continue
setting = policy.get("setting", {})
setting_type = setting.get("type", "").removeprefix("settings/")
value = setting.get("value", {})
if setting_type == "sites.service_status":
self.policies.service_state = value.get("serviceState")
logger.debug(
"Sites service state: " f"{self.policies.service_state}"
)
request = service.policies().list_next(request, response)
except Exception as error:
self._handle_api_error(
error,
"fetching Sites policies",
self.provider.identity.customer_id,
)
fetch_succeeded = False
break
self.policies_fetched = fetch_succeeded
logger.info(
f"Sites policies fetched - "
f"Service state: {self.policies.service_state}"
)
except Exception as error:
self._handle_api_error(
error,
"fetching Sites policies",
self.provider.identity.customer_id,
)
self.policies_fetched = False
class SitesPolicies(BaseModel):
"""Model for domain-level Sites policy settings."""
# sites.service_status
service_state: Optional[str] = None
@@ -0,0 +1,37 @@
{
"Provider": "googleworkspace",
"CheckID": "sites_service_disabled",
"CheckTitle": "Service status for Google Sites is set to off",
"CheckType": [],
"ServiceName": "sites",
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "NotDefined",
"ResourceGroup": "collaboration",
"Description": "The domain-wide Google Sites configuration has the service **disabled for all users**. Google Sites allows users to create internal and external websites, which may expose sensitive information or create unmanaged content outside the organization's control.",
"Risk": "When Google Sites is enabled, users can create websites that may **inadvertently expose internal information** to external parties. These sites can be difficult to track and manage, creating potential **data leakage vectors** outside the organization's standard content management controls.",
"RelatedUrl": "",
"AdditionalURLs": [
"https://support.google.com/a/answer/182442",
"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** > **Sites**\n3. Click **Service status**\n4. Select **OFF for everyone**\n5. Click **Save**",
"Terraform": ""
},
"Recommendation": {
"Text": "Disable **Google Sites** for all users to reduce the organization's attack surface. If specific users require access, enable it by exception for those users or groups only.",
"Url": "https://hub.prowler.com/check/sites_service_disabled"
}
},
"Categories": [
"trust-boundaries"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,52 @@
from typing import List
from prowler.lib.check.models import Check, CheckReportGoogleWorkspace
from prowler.providers.googleworkspace.services.sites.sites_client import sites_client
class sites_service_disabled(Check):
"""Check that the Google Sites service is disabled for all users.
This check verifies that the domain-level policy disables the Google Sites
service, reducing the organization's attack surface by preventing users
from creating internal or external websites.
"""
def execute(self) -> List[CheckReportGoogleWorkspace]:
findings = []
if sites_client.policies_fetched:
report = CheckReportGoogleWorkspace(
metadata=self.metadata(),
resource=sites_client.policies,
resource_id="sitesPolicies",
resource_name="Sites Policies",
customer_id=sites_client.provider.identity.customer_id,
)
service_state = sites_client.policies.service_state
if service_state == "DISABLED":
report.status = "PASS"
report.status_extended = (
f"Google Sites service is disabled "
f"in domain {sites_client.provider.identity.domain}."
)
else:
report.status = "FAIL"
if service_state is None:
report.status_extended = (
f"Google Sites service is not explicitly configured "
f"in domain {sites_client.provider.identity.domain}. "
f"The default is ON for everyone. Google Sites should be disabled."
)
else:
report.status_extended = (
f"Google Sites service is enabled "
f"in domain {sites_client.provider.identity.domain}. "
f"Google Sites should be disabled."
)
findings.append(report)
return findings
@@ -0,0 +1,128 @@
from unittest.mock import patch
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServicesPolicies,
)
from tests.providers.googleworkspace.googleworkspace_fixtures import (
CUSTOMER_ID,
set_mocked_googleworkspace_provider,
)
class TestAdditionalServicesExternalGroupsDisabled:
def test_pass_groups_disabled(self):
"""Test PASS when external Google Groups access is disabled"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_external_groups_disabled.additionalservices_external_groups_disabled.additionalservices_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_external_groups_disabled.additionalservices_external_groups_disabled import (
additionalservices_external_groups_disabled,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = AdditionalServicesPolicies(
groups_service_state="DISABLED"
)
check = additionalservices_external_groups_disabled()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "PASS"
assert "disabled" in findings[0].status_extended
assert findings[0].resource_name == "Additional Services Policies"
assert findings[0].resource_id == "additionalServicesPolicies"
assert findings[0].customer_id == CUSTOMER_ID
def test_fail_groups_enabled(self):
"""Test FAIL when external Google Groups access is enabled"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_external_groups_disabled.additionalservices_external_groups_disabled.additionalservices_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_external_groups_disabled.additionalservices_external_groups_disabled import (
additionalservices_external_groups_disabled,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = AdditionalServicesPolicies(
groups_service_state="ENABLED"
)
check = additionalservices_external_groups_disabled()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "FAIL"
assert "enabled" in findings[0].status_extended
def test_fail_no_policy_set(self):
"""Test FAIL when no explicit policy is set (None) - Google default is ON (insecure)"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_external_groups_disabled.additionalservices_external_groups_disabled.additionalservices_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_external_groups_disabled.additionalservices_external_groups_disabled import (
additionalservices_external_groups_disabled,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = AdditionalServicesPolicies(groups_service_state=None)
check = additionalservices_external_groups_disabled()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "FAIL"
assert "not explicitly configured" in findings[0].status_extended
def test_no_findings_when_fetch_failed(self):
"""Test no findings returned when the API fetch failed"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_external_groups_disabled.additionalservices_external_groups_disabled.additionalservices_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_external_groups_disabled.additionalservices_external_groups_disabled import (
additionalservices_external_groups_disabled,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = False
mock_client.policies = AdditionalServicesPolicies()
check = additionalservices_external_groups_disabled()
findings = check.execute()
assert len(findings) == 0
@@ -0,0 +1,234 @@
from unittest.mock import MagicMock, patch
from tests.providers.googleworkspace.googleworkspace_fixtures import (
set_mocked_googleworkspace_provider,
)
class TestAdditionalServicesService:
def test_fetch_policies_groups_off(self):
"""Test fetching Additional Services policy with Groups OFF"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_credentials = MagicMock()
mock_session = MagicMock()
mock_session.credentials = mock_credentials
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {
"policies": [
{
"setting": {
"type": "settings/groups.service_status",
"value": {
"serviceState": "DISABLED",
},
}
},
]
}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServices,
)
additional_services = AdditionalServices(mock_provider)
assert additional_services.policies_fetched is True
assert additional_services.policies.groups_service_state == "DISABLED"
def test_fetch_policies_groups_on(self):
"""Test fetching Additional Services policy with Groups ON"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {
"policies": [
{
"setting": {
"type": "settings/groups.service_status",
"value": {
"serviceState": "ENABLED",
},
}
},
]
}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServices,
)
additional_services = AdditionalServices(mock_provider)
assert additional_services.policies_fetched is True
assert additional_services.policies.groups_service_state == "ENABLED"
def test_fetch_policies_empty_response(self):
"""Test handling empty policies response"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {"policies": []}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServices,
)
additional_services = AdditionalServices(mock_provider)
assert additional_services.policies_fetched is True
assert additional_services.policies.groups_service_state is None
def test_fetch_policies_api_error(self):
"""Test handling of API errors during policy fetch"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_service.policies().list.side_effect = Exception("API Error")
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServices,
)
additional_services = AdditionalServices(mock_provider)
assert additional_services.policies_fetched is False
assert additional_services.policies.groups_service_state is None
def test_fetch_policies_build_service_returns_none(self):
"""Test early return when _build_service fails to construct the client"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_service.GoogleWorkspaceService._build_service",
return_value=None,
),
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServices,
)
additional_services = AdditionalServices(mock_provider)
assert additional_services.policies_fetched is False
assert additional_services.policies.groups_service_state is None
def test_fetch_policies_execute_raises(self):
"""Test inner except handler when request.execute() raises during pagination"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_request = MagicMock()
mock_request.execute.side_effect = Exception("Execute failed")
mock_service.policies().list.return_value = mock_request
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.additionalservices.additionalservices_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServices,
)
additional_services = AdditionalServices(mock_provider)
assert additional_services.policies_fetched is False
assert additional_services.policies.groups_service_state is None
def test_additional_services_policies_model(self):
"""Test AdditionalServicesPolicies Pydantic model"""
from prowler.providers.googleworkspace.services.additionalservices.additionalservices_service import (
AdditionalServicesPolicies,
)
policies = AdditionalServicesPolicies(groups_service_state="DISABLED")
assert policies.groups_service_state == "DISABLED"
@@ -0,0 +1,152 @@
from unittest.mock import patch
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
MarketplacePolicies,
)
from tests.providers.googleworkspace.googleworkspace_fixtures import (
CUSTOMER_ID,
set_mocked_googleworkspace_provider,
)
class TestMarketplaceAppsAccessRestricted:
def test_pass_allow_listed_apps(self):
"""Test PASS when Marketplace access is restricted to admin-approved apps"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted.marketplace_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted import (
marketplace_apps_access_restricted,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = MarketplacePolicies(access_level="ALLOW_LISTED_APPS")
check = marketplace_apps_access_restricted()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "PASS"
assert "restricted" in findings[0].status_extended
assert findings[0].resource_name == "Marketplace Policies"
assert findings[0].resource_id == "marketplacePolicies"
assert findings[0].customer_id == CUSTOMER_ID
def test_pass_allow_none(self):
"""Test PASS when Marketplace app installation is fully blocked"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted.marketplace_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted import (
marketplace_apps_access_restricted,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = MarketplacePolicies(access_level="ALLOW_NONE")
check = marketplace_apps_access_restricted()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "PASS"
assert "blocked" in findings[0].status_extended
def test_fail_allow_all(self):
"""Test FAIL when Marketplace allows all apps"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted.marketplace_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted import (
marketplace_apps_access_restricted,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = MarketplacePolicies(access_level="ALLOW_ALL")
check = marketplace_apps_access_restricted()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "FAIL"
assert "any app" in findings[0].status_extended
def test_fail_no_policy_set(self):
"""Test FAIL when no explicit policy is set (None) - Google default is ALLOW_ALL (insecure)"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted.marketplace_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted import (
marketplace_apps_access_restricted,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = MarketplacePolicies(access_level=None)
check = marketplace_apps_access_restricted()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "FAIL"
assert "not explicitly configured" in findings[0].status_extended
def test_no_findings_when_fetch_failed(self):
"""Test no findings returned when the API fetch failed"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted.marketplace_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_apps_access_restricted.marketplace_apps_access_restricted import (
marketplace_apps_access_restricted,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = False
mock_client.policies = MarketplacePolicies()
check = marketplace_apps_access_restricted()
findings = check.execute()
assert len(findings) == 0
@@ -0,0 +1,279 @@
from unittest.mock import MagicMock, patch
from tests.providers.googleworkspace.googleworkspace_fixtures import (
set_mocked_googleworkspace_provider,
)
class TestMarketplaceService:
def test_fetch_policies_allow_all(self):
"""Test fetching Marketplace policy with ALLOW_ALL access level"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_credentials = MagicMock()
mock_session = MagicMock()
mock_session.credentials = mock_credentials
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {
"policies": [
{
"setting": {
"type": "settings/workspace_marketplace.apps_access_options",
"value": {
"accessLevel": "ALLOW_ALL",
},
}
},
]
}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
Marketplace,
)
marketplace = Marketplace(mock_provider)
assert marketplace.policies_fetched is True
assert marketplace.policies.access_level == "ALLOW_ALL"
def test_fetch_policies_allow_listed_apps(self):
"""Test fetching Marketplace policy with ALLOW_LISTED_APPS access level"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {
"policies": [
{
"setting": {
"type": "settings/workspace_marketplace.apps_access_options",
"value": {
"accessLevel": "ALLOW_LISTED_APPS",
},
}
},
]
}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
Marketplace,
)
marketplace = Marketplace(mock_provider)
assert marketplace.policies_fetched is True
assert marketplace.policies.access_level == "ALLOW_LISTED_APPS"
def test_fetch_policies_allow_none(self):
"""Test fetching Marketplace policy with ALLOW_NONE access level"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {
"policies": [
{
"setting": {
"type": "settings/workspace_marketplace.apps_access_options",
"value": {
"accessLevel": "ALLOW_NONE",
},
}
},
]
}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
Marketplace,
)
marketplace = Marketplace(mock_provider)
assert marketplace.policies_fetched is True
assert marketplace.policies.access_level == "ALLOW_NONE"
def test_fetch_policies_empty_response(self):
"""Test handling empty policies response"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {"policies": []}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
Marketplace,
)
marketplace = Marketplace(mock_provider)
assert marketplace.policies_fetched is True
assert marketplace.policies.access_level is None
def test_fetch_policies_api_error(self):
"""Test handling of API errors during policy fetch"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_service.policies().list.side_effect = Exception("API Error")
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
Marketplace,
)
marketplace = Marketplace(mock_provider)
assert marketplace.policies_fetched is False
assert marketplace.policies.access_level is None
def test_fetch_policies_build_service_returns_none(self):
"""Test early return when _build_service fails to construct the client"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_service.GoogleWorkspaceService._build_service",
return_value=None,
),
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
Marketplace,
)
marketplace = Marketplace(mock_provider)
assert marketplace.policies_fetched is False
assert marketplace.policies.access_level is None
def test_fetch_policies_execute_raises(self):
"""Test inner except handler when request.execute() raises during pagination"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_request = MagicMock()
mock_request.execute.side_effect = Exception("Execute failed")
mock_service.policies().list.return_value = mock_request
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.marketplace.marketplace_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
Marketplace,
)
marketplace = Marketplace(mock_provider)
assert marketplace.policies_fetched is False
assert marketplace.policies.access_level is None
def test_marketplace_policies_model(self):
"""Test MarketplacePolicies Pydantic model"""
from prowler.providers.googleworkspace.services.marketplace.marketplace_service import (
MarketplacePolicies,
)
policies = MarketplacePolicies(access_level="ALLOW_LISTED_APPS")
assert policies.access_level == "ALLOW_LISTED_APPS"
@@ -0,0 +1,124 @@
from unittest.mock import patch
from prowler.providers.googleworkspace.services.sites.sites_service import (
SitesPolicies,
)
from tests.providers.googleworkspace.googleworkspace_fixtures import (
CUSTOMER_ID,
set_mocked_googleworkspace_provider,
)
class TestSitesServiceDisabled:
def test_pass_service_disabled(self):
"""Test PASS when Sites service is disabled (OFF for everyone)"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service_disabled.sites_service_disabled.sites_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.sites.sites_service_disabled.sites_service_disabled import (
sites_service_disabled,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = SitesPolicies(service_state="DISABLED")
check = sites_service_disabled()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "PASS"
assert "disabled" in findings[0].status_extended
assert findings[0].resource_name == "Sites Policies"
assert findings[0].resource_id == "sitesPolicies"
assert findings[0].customer_id == CUSTOMER_ID
def test_fail_service_enabled(self):
"""Test FAIL when Sites service is enabled (ON for everyone)"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service_disabled.sites_service_disabled.sites_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.sites.sites_service_disabled.sites_service_disabled import (
sites_service_disabled,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = SitesPolicies(service_state="ENABLED")
check = sites_service_disabled()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "FAIL"
assert "enabled" in findings[0].status_extended
def test_fail_no_policy_set(self):
"""Test FAIL when no explicit policy is set (None) - Google default is ON (insecure)"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service_disabled.sites_service_disabled.sites_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.sites.sites_service_disabled.sites_service_disabled import (
sites_service_disabled,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = True
mock_client.policies = SitesPolicies(service_state=None)
check = sites_service_disabled()
findings = check.execute()
assert len(findings) == 1
assert findings[0].status == "FAIL"
assert "not explicitly configured" in findings[0].status_extended
def test_no_findings_when_fetch_failed(self):
"""Test no findings returned when the API fetch failed"""
mock_provider = set_mocked_googleworkspace_provider()
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service_disabled.sites_service_disabled.sites_client"
) as mock_client,
):
from prowler.providers.googleworkspace.services.sites.sites_service_disabled.sites_service_disabled import (
sites_service_disabled,
)
mock_client.provider = mock_provider
mock_client.policies_fetched = False
mock_client.policies = SitesPolicies()
check = sites_service_disabled()
findings = check.execute()
assert len(findings) == 0
@@ -0,0 +1,234 @@
from unittest.mock import MagicMock, patch
from tests.providers.googleworkspace.googleworkspace_fixtures import (
set_mocked_googleworkspace_provider,
)
class TestSitesService:
def test_fetch_policies_service_status_off(self):
"""Test fetching Sites policy with service status OFF"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_credentials = MagicMock()
mock_session = MagicMock()
mock_session.credentials = mock_credentials
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {
"policies": [
{
"setting": {
"type": "settings/sites.service_status",
"value": {
"serviceState": "DISABLED",
},
}
},
]
}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.sites.sites_service import (
Sites,
)
sites = Sites(mock_provider)
assert sites.policies_fetched is True
assert sites.policies.service_state == "DISABLED"
def test_fetch_policies_service_status_on(self):
"""Test fetching Sites policy with service status ON"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {
"policies": [
{
"setting": {
"type": "settings/sites.service_status",
"value": {
"serviceState": "ENABLED",
},
}
},
]
}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.sites.sites_service import (
Sites,
)
sites = Sites(mock_provider)
assert sites.policies_fetched is True
assert sites.policies.service_state == "ENABLED"
def test_fetch_policies_empty_response(self):
"""Test handling empty policies response"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_policies_list = MagicMock()
mock_policies_list.execute.return_value = {"policies": []}
mock_service.policies().list.return_value = mock_policies_list
mock_service.policies().list_next.return_value = None
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.sites.sites_service import (
Sites,
)
sites = Sites(mock_provider)
assert sites.policies_fetched is True
assert sites.policies.service_state is None
def test_fetch_policies_api_error(self):
"""Test handling of API errors during policy fetch"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_service.policies().list.side_effect = Exception("API Error")
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.sites.sites_service import (
Sites,
)
sites = Sites(mock_provider)
assert sites.policies_fetched is False
assert sites.policies.service_state is None
def test_fetch_policies_build_service_returns_none(self):
"""Test early return when _build_service fails to construct the client"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service.GoogleWorkspaceService._build_service",
return_value=None,
),
):
from prowler.providers.googleworkspace.services.sites.sites_service import (
Sites,
)
sites = Sites(mock_provider)
assert sites.policies_fetched is False
assert sites.policies.service_state is None
def test_fetch_policies_execute_raises(self):
"""Test inner except handler when request.execute() raises during pagination"""
mock_provider = set_mocked_googleworkspace_provider()
mock_provider.audit_config = {}
mock_provider.fixer_config = {}
mock_session = MagicMock()
mock_session.credentials = MagicMock()
mock_provider.session = mock_session
mock_service = MagicMock()
mock_request = MagicMock()
mock_request.execute.side_effect = Exception("Execute failed")
mock_service.policies().list.return_value = mock_request
with (
patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mock_provider,
),
patch(
"prowler.providers.googleworkspace.services.sites.sites_service.GoogleWorkspaceService._build_service",
return_value=mock_service,
),
):
from prowler.providers.googleworkspace.services.sites.sites_service import (
Sites,
)
sites = Sites(mock_provider)
assert sites.policies_fetched is False
assert sites.policies.service_state is None
def test_sites_policies_model(self):
"""Test SitesPolicies Pydantic model"""
from prowler.providers.googleworkspace.services.sites.sites_service import (
SitesPolicies,
)
policies = SitesPolicies(service_state="DISABLED")
assert policies.service_state == "DISABLED"