diff --git a/ScoutSuite/output/data/html/partials/gcp/services.cloudstorage.projects.id.buckets.html b/ScoutSuite/output/data/html/partials/gcp/services.cloudstorage.projects.id.buckets.html
index 0256d60a7..a12248917 100755
--- a/ScoutSuite/output/data/html/partials/gcp/services.cloudstorage.projects.id.buckets.html
+++ b/ScoutSuite/output/data/html/partials/gcp/services.cloudstorage.projects.id.buckets.html
@@ -12,7 +12,8 @@
Information
Storage Class: {{storage_class}}
Logging: {{convert_bool_to_enabled logging_enabled}}
Versioning: {{convert_bool_to_enabled versioning_enabled}}
- Public Access Prevention: {{public_access_prevention}}
+ Public Access Prevention: {{public_access_prevention}}
+ Effective Public Access Prevention: {{convert_bool_to_enabled effective_public_access_prevention}}
Uniform Bucket-Level Access: {{convert_bool_to_enabled uniform_bucket_level_access}}
diff --git a/ScoutSuite/providers/gcp/facade/cloudstorage.py b/ScoutSuite/providers/gcp/facade/cloudstorage.py
index 359d632a6..05e97620d 100755
--- a/ScoutSuite/providers/gcp/facade/cloudstorage.py
+++ b/ScoutSuite/providers/gcp/facade/cloudstorage.py
@@ -1,31 +1,58 @@
from google.cloud import storage
+from google.cloud import orgpolicy_v2
from google.api_core.gapic_v1.client_info import ClientInfo
-from ScoutSuite.core.console import print_exception
+from ScoutSuite.providers.gcp.facade.basefacade import GCPBaseFacade
+
+from ScoutSuite.core.console import print_exception, print_warning
from ScoutSuite.providers.utils import run_concurrently, get_and_set_concurrently
from ScoutSuite.utils import get_user_agent
-class CloudStorageFacade:
+class CloudStorageFacade(GCPBaseFacade):
+
+ def __init__(self):
+ super().__init__('cloudresourcemanager', 'v1')
+
+ def _get_effective_public_access_prevention(self, project_id):
+ try:
+ resourcemanager_client = self._get_client()
+ request = resourcemanager_client.projects().getEffectiveOrgPolicy(resource=f"projects/{project_id}",
+ body={
+ "constraint": f"constraints/storage.publicAccessPrevention"})
+ response = request.execute()
+ return response.get('booleanPolicy', {}).get('enforced', False)
+ except Exception as e:
+ print_warning(f'Failed to retrieve project {project_id} storage.publicAccessPrevention constraint: {e}')
+ return None
- def get_client(self, project_id: str):
+ def get_storage_client(self, project_id: str):
client_info = ClientInfo(user_agent=get_user_agent())
client = storage.Client(project=project_id,
client_info=client_info)
return client
+ def get_org_policy_client(self):
+ client_info = ClientInfo(user_agent=get_user_agent())
+ client = orgpolicy_v2.OrgPolicyClient(client_info=client_info)
+ return client
+
async def get_buckets(self, project_id: str):
try:
- client = self.get_client(project_id)
+ client = self.get_storage_client(project_id)
buckets = await run_concurrently(lambda: list(client.list_buckets()))
- await get_and_set_concurrently([self._get_and_set_bucket_logging,
- self._get_and_set_bucket_iam_policy], buckets)
+ await get_and_set_concurrently([self._get_and_set_bucket_logging,
+ self._get_and_set_bucket_iam_policy,
+ self._get_and_set_public_access_prevention],
+ buckets,
+ effective_public_access_prevention=self._get_effective_public_access_prevention(
+ project_id))
return buckets
except Exception as e:
print_exception(f'Failed to retrieve storage buckets: {e}')
return []
- async def _get_and_set_bucket_logging(self, bucket):
+ async def _get_and_set_bucket_logging(self, bucket, **kwargs):
try:
bucket_logging = await run_concurrently(lambda: bucket.get_logging())
setattr(bucket, 'logging', bucket_logging)
@@ -33,10 +60,17 @@ async def _get_and_set_bucket_logging(self, bucket):
print_exception(f'Failed to retrieve bucket logging: {e}')
setattr(bucket, 'logging', None)
- async def _get_and_set_bucket_iam_policy(self, bucket):
+ async def _get_and_set_bucket_iam_policy(self, bucket, **kwargs):
try:
bucket_iam_policy = await run_concurrently(lambda: bucket.get_iam_policy())
setattr(bucket, 'iam_policy', bucket_iam_policy)
except Exception as e:
print_exception(f'Failed to retrieve bucket IAM policy: {e}')
- setattr(bucket, 'iam_policy', None)
+ setattr(bucket, 'iam_policy', None)
+
+ async def _get_and_set_public_access_prevention(self, bucket, effective_public_access_prevention):
+ try:
+ setattr(bucket, 'effective_public_access_prevention', effective_public_access_prevention)
+ except Exception as e:
+ print_exception(f'Failed to set effective public access prevention for bucket {bucket}: {e}')
+ setattr(bucket, 'effective_public_access_prevention', None)
diff --git a/ScoutSuite/providers/gcp/resources/cloudstorage/buckets.py b/ScoutSuite/providers/gcp/resources/cloudstorage/buckets.py
index 8e813e6e2..4f19ba5b6 100755
--- a/ScoutSuite/providers/gcp/resources/cloudstorage/buckets.py
+++ b/ScoutSuite/providers/gcp/resources/cloudstorage/buckets.py
@@ -28,6 +28,7 @@ def _parse_bucket(self, raw_bucket):
bucket_dict['logging_enabled'] = raw_bucket.logging is not None
bucket_dict['public_access_prevention'] = raw_bucket.iam_configuration.public_access_prevention
+ bucket_dict['effective_public_access_prevention'] = raw_bucket.effective_public_access_prevention
iam_configuration = raw_bucket.iam_configuration.get('uniformBucketLevelAccess') or \
raw_bucket.iam_configuration.get('bucketPolicyOnly')
diff --git a/ScoutSuite/providers/gcp/rules/findings/cloudstorage-bucket-member.json b/ScoutSuite/providers/gcp/rules/findings/cloudstorage-bucket-member.json
index 30abee45c..e541ce11a 100755
--- a/ScoutSuite/providers/gcp/rules/findings/cloudstorage-bucket-member.json
+++ b/ScoutSuite/providers/gcp/rules/findings/cloudstorage-bucket-member.json
@@ -37,14 +37,9 @@
]
],
[
- "cloudstorage.projects.id.buckets.id.public_access_prevention",
+ "cloudstorage.projects.id.buckets.id.effective_public_access_prevention",
"notEqual",
- "enforced"
- ],
- [
- "cloudstorage.projects.id.buckets.id.public_access_prevention",
- "notEqual",
- "inherited"
+ "True"
]
],
"key": "cloudstorage-bucket-_ARG_0_",
diff --git a/ScoutSuite/providers/gcp/rules/findings/cloudstorage-bucket-no-public-access-prevention.json b/ScoutSuite/providers/gcp/rules/findings/cloudstorage-bucket-no-public-access-prevention.json
index 34a6b16df..ba8e15351 100755
--- a/ScoutSuite/providers/gcp/rules/findings/cloudstorage-bucket-no-public-access-prevention.json
+++ b/ScoutSuite/providers/gcp/rules/findings/cloudstorage-bucket-no-public-access-prevention.json
@@ -9,15 +9,10 @@
"conditions": [
"and",
[
- "cloudstorage.projects.id.buckets.id.public_access_prevention",
+ "cloudstorage.projects.id.buckets.id.effective_public_access_prevention",
"notEqual",
- "enforced"
- ],
- [
- "cloudstorage.projects.id.buckets.id.public_access_prevention",
- "notEqual",
- "inherited"
+ "True"
]
],
- "id_suffix": "public_access_prevention"
+ "class_suffix": "public_access_prevention"
}
diff --git a/requirements.txt b/requirements.txt
index d43d62487..200deafd1 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -23,6 +23,7 @@ google-cloud-logging>=2.2.0
google-cloud-monitoring==1.1.1
google-cloud-resource-manager>=0.28.3
google-cloud-storage>=1.13.2
+google-cloud-org-policy==1.10.0
google-cloud-kms==1.4.1
## API Client Libraries
google-api-python-client>=2.47.0