feat(gcp): Add support for skipping APIs check (#8575)

Co-authored-by: Sergio Garcia <sergargar1@gmail.com>
This commit is contained in:
Tom
2025-08-27 13:44:34 +01:00
committed by GitHub
parent a1abe6dd2d
commit 24364bd73e
6 changed files with 106 additions and 2 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
- `eks_cluster_deletion_protection_enabled` check for AWS provider [(#8536)](https://github.com/prowler-cloud/prowler/pull/8536)
- ECS privilege escalation patterns (StartTask and RunTask) for AWS provider [(#8541)](https://github.com/prowler-cloud/prowler/pull/8541)
- Resource Explorer enumeration v2 API actions in `cloudtrail_threat_detection_enumeration` check [(#8557)](https://github.com/prowler-cloud/prowler/pull/8557)
- GCP `--skip-api-check` command line flag [(#8575)](https://github.com/prowler-cloud/prowler/pull/8575)
### Changed
- Refine kisa isms-p compliance mapping [(#8479)](https://github.com/prowler-cloud/prowler/pull/8479)
+1
View File
@@ -202,6 +202,7 @@ class Provider(ABC):
config_path=arguments.config_file,
mutelist_path=arguments.mutelist_file,
fixer_config=fixer_config,
skip_api_check=arguments.skip_api_check,
)
elif "kubernetes" in provider_class_name.lower():
provider_class(
+6
View File
@@ -86,6 +86,7 @@ class GcpProvider(Provider):
client_secret: str = None,
refresh_token: str = None,
service_account_key: dict = None,
skip_api_check: bool = False,
):
"""
GCP Provider constructor
@@ -107,6 +108,7 @@ class GcpProvider(Provider):
client_secret: str
refresh_token: str
service_account_key: dict
skip_api_check: bool
Raises:
GCPNoAccesibleProjectsError if no project IDs can be accessed via Google Credentials
@@ -174,6 +176,10 @@ class GcpProvider(Provider):
gcp_config.DEFAULT_RETRY_ATTEMPTS = retries_max_attempts
logger.info(f"GCP retry attempts set to {retries_max_attempts}")
if skip_api_check:
logger.info("Skipping API active check for each service")
self.skip_api_check = skip_api_check
self._impersonated_service_account = impersonate_service_account
# Set the GCP credentials using the provided client_id, client_secret and refresh_token
gcp_credentials = None
@@ -57,3 +57,10 @@ def init_parser(self):
type=int,
help="Set the maximum attempts for the Google Cloud SDK retry config (Default: 3)",
)
gcp_config_subparser.add_argument(
"--skip-api-check",
action="store_true",
default=False,
help="Assume all APIs are active and skip the active API check for each service",
)
+4 -1
View File
@@ -29,7 +29,10 @@ class GCPService:
self.service, api_version, self.credentials
)
# Only project ids that have their API enabled will be scanned
self.project_ids = self.__is_api_active__(provider.project_ids)
if provider.skip_api_check:
self.project_ids = provider.project_ids
else:
self.project_ids = self.__is_api_active__(provider.project_ids)
self.projects = provider.projects
self.default_project_id = provider.default_project_id
self.audit_config = provider.audit_config
+87
View File
@@ -987,3 +987,90 @@ class TestGCPProvider:
from prowler.providers.gcp.config import DEFAULT_RETRY_ATTEMPTS
assert DEFAULT_RETRY_ATTEMPTS == 3
def test_skip_api_check_argument(self):
"""Test that skip_api_check argument is set correctly in GcpProvider"""
mocked_credentials = MagicMock()
mocked_credentials.refresh.return_value = None
mocked_credentials._service_account_email = "test-service-account-email"
arguments = Namespace()
arguments.project_id = []
arguments.excluded_project_id = []
arguments.organization_id = None
arguments.list_project_id = False
arguments.credentials_file = "test_credentials_file"
arguments.impersonate_service_account = ""
arguments.config_file = default_config_file_path
arguments.fixer_config = default_fixer_config_file_path
arguments.skip_api_check = True
projects = {
"test-project": GCPProject(
number="55555555",
id="project/55555555",
name="test-project",
labels={"test": "value"},
lifecycle_state="ACTIVE",
),
}
mocked_service = MagicMock()
mocked_service.projects.list.return_value = MagicMock(
execute=MagicMock(return_value={"projects": projects})
)
mocked_is_api_active = MagicMock()
mocked_is_api_active.return_value = projects.keys()
with (
patch(
"prowler.providers.gcp.gcp_provider.GcpProvider.get_projects",
return_value=projects,
),
patch(
"prowler.providers.gcp.gcp_provider.GcpProvider.update_projects_with_organizations",
return_value=None,
),
patch(
"os.path.abspath",
return_value="test_credentials_file",
),
patch(
"prowler.providers.gcp.gcp_provider.default",
return_value=(mocked_credentials, MagicMock()),
),
patch(
"prowler.providers.gcp.gcp_provider.discovery.build",
return_value=mocked_service,
),
patch(
"prowler.providers.gcp.lib.service.service.GCPService.__is_api_active__",
mocked_is_api_active,
),
):
gcp_provider = GcpProvider(
retries_max_attempts=None,
organization_id=arguments.organization_id,
project_ids=arguments.project_id,
excluded_project_ids=arguments.excluded_project_id,
credentials_file=arguments.credentials_file,
impersonate_service_account=arguments.impersonate_service_account,
list_project_ids=arguments.list_project_id,
config_path=arguments.config_file,
fixer_config=arguments.fixer_config,
client_id=None,
client_secret=None,
refresh_token=None,
skip_api_check=arguments.skip_api_check,
)
from prowler.providers.gcp.lib.service.service import GCPService
GCPService("testservice", gcp_provider)
assert gcp_provider.skip_api_check is True
mocked_is_api_active.assert_not_called()