Skip to content

Commit e28bde7

Browse files
feat(openstack): object storage service with 7 new checks (#10258)
1 parent cc0d83d commit e28bde7

File tree

33 files changed

+2887
-0
lines changed

33 files changed

+2887
-0
lines changed

prowler/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
1010
- `entra_conditional_access_policy_compliant_device_hybrid_joined_device_mfa_required` check for M365 provider [(#10197)](https://github.com/prowler-cloud/prowler/pull/10197)
1111
- Add `trusted_ips` configurable option to `opensearch_service_domains_not_publicly_accessible` check to reduce false positives on IP-restricted policies [(#8631)](https://github.com/prowler-cloud/prowler/pull/8631)
1212
- `guardduty_delegated_admin_enabled_all_regions` check for AWS provider [(#9867)](https://github.com/prowler-cloud/prowler/pull/9867)
13+
- OpenStack object storage service with 7 checks [(#10258)](https://github.com/prowler-cloud/prowler/pull/10258)
1314

1415
### 🔄 Changed
1516

prowler/providers/openstack/services/objectstorage/__init__.py

Whitespace-only changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from prowler.providers.common.provider import Provider
2+
from prowler.providers.openstack.services.objectstorage.objectstorage_service import (
3+
ObjectStorage,
4+
)
5+
6+
objectstorage_client = ObjectStorage(Provider.get_global_provider())

prowler/providers/openstack/services/objectstorage/objectstorage_container_acl_not_globally_shared/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"Provider": "openstack",
3+
"CheckID": "objectstorage_container_acl_not_globally_shared",
4+
"CheckTitle": "Object storage container read ACL is not globally shared",
5+
"CheckType": [],
6+
"ServiceName": "objectstorage",
7+
"SubServiceName": "",
8+
"ResourceIdTemplate": "",
9+
"Severity": "high",
10+
"ResourceType": "OS::Swift::Container",
11+
"ResourceGroup": "storage",
12+
"Description": "**OpenStack Swift containers** are evaluated to verify that the **read ACL** does not use `*:*` (global sharing). The `*:*` ACL grants read access to all authenticated users from any project in the OpenStack deployment, violating project isolation and the principle of least privilege.",
13+
"Risk": "Containers with `*:*` read ACL are accessible to **every authenticated user** in the OpenStack deployment, regardless of their project. This breaks **multi-tenant isolation**, exposing data to users in other projects. **Compromised credentials** from any project can access the container's contents.",
14+
"RelatedUrl": "",
15+
"AdditionalURLs": [
16+
"https://docs.openstack.org/swift/latest/overview_acl.html",
17+
"https://docs.openstack.org/security-guide/object-storage.html"
18+
],
19+
"Remediation": {
20+
"Code": {
21+
"CLI": "swift post <container_name> --read-acl '<project_id>:*'",
22+
"NativeIaC": "",
23+
"Other": "1. Navigate to **Object Store > Containers**\n2. Select the container with global read ACL\n3. Edit the container metadata\n4. Replace `*:*` with specific project-scoped ACLs\n5. Save changes",
24+
"Terraform": ""
25+
},
26+
"Recommendation": {
27+
"Text": "Replace `*:*` read ACLs with **project-scoped ACLs** (e.g., `project-id:*` or `project-id:user-id`). Use the **most restrictive ACL** that meets access requirements. Implement regular ACL audits to detect overly permissive configurations. Consider using **Keystone role-based access control** for fine-grained permissions.",
28+
"Url": "https://hub.prowler.com/check/objectstorage_container_acl_not_globally_shared"
29+
}
30+
},
31+
"Categories": [
32+
"identity-access"
33+
],
34+
"DependsOn": [],
35+
"RelatedTo": [],
36+
"Notes": "The `*:*` ACL means 'any user in any project'. This is different from `.r:*` which grants anonymous (unauthenticated) access. Both are overly permissive but target different audiences: `*:*` targets all authenticated users while `.r:*` targets everyone including unauthenticated users."
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from typing import List
2+
3+
from prowler.lib.check.models import Check, CheckReportOpenStack
4+
from prowler.providers.openstack.services.objectstorage.objectstorage_client import (
5+
objectstorage_client,
6+
)
7+
8+
9+
class objectstorage_container_acl_not_globally_shared(Check):
10+
"""Ensure object storage container read ACL does not use global sharing."""
11+
12+
def execute(self) -> List[CheckReportOpenStack]:
13+
findings: List[CheckReportOpenStack] = []
14+
15+
for container in objectstorage_client.containers:
16+
report = CheckReportOpenStack(metadata=self.metadata(), resource=container)
17+
acl_entries = [entry.strip() for entry in container.read_ACL.split(",")]
18+
if "*:*" in acl_entries or "*" in acl_entries:
19+
report.status = "FAIL"
20+
report.status_extended = f"Container {container.name} has globally shared read ACL (*:*) allowing all authenticated users from any project."
21+
else:
22+
report.status = "PASS"
23+
report.status_extended = (
24+
f"Container {container.name} read ACL is not globally shared."
25+
)
26+
27+
findings.append(report)
28+
29+
return findings

prowler/providers/openstack/services/objectstorage/objectstorage_container_listing_disabled/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"Provider": "openstack",
3+
"CheckID": "objectstorage_container_listing_disabled",
4+
"CheckTitle": "Object storage container listings are not publicly accessible",
5+
"CheckType": [],
6+
"ServiceName": "objectstorage",
7+
"SubServiceName": "",
8+
"ResourceIdTemplate": "",
9+
"Severity": "medium",
10+
"ResourceType": "OS::Swift::Container",
11+
"ResourceGroup": "storage",
12+
"Description": "**OpenStack Swift containers** are evaluated to verify that **public container listings** are disabled. The `.rlistings` ACL allows users with read access to list all objects within the container. When combined with `.r:*`, this enables unauthenticated users to enumerate all objects, facilitating targeted data exfiltration.",
13+
"Risk": "Containers with `.rlistings` enabled allow attackers to enumerate all object names, sizes, and modification dates. This **metadata exposure** aids **targeted attacks**, reveals application structure, and can expose sensitive file names. Combined with public read access, it enables complete **data exfiltration**.",
14+
"RelatedUrl": "",
15+
"AdditionalURLs": [
16+
"https://docs.openstack.org/swift/latest/overview_acl.html",
17+
"https://docs.openstack.org/security-guide/object-storage.html"
18+
],
19+
"Remediation": {
20+
"Code": {
21+
"CLI": "swift post <container_name> --read-acl ''",
22+
"NativeIaC": "",
23+
"Other": "1. Navigate to **Object Store > Containers**\n2. Select the container with public listing\n3. Edit the container metadata\n4. Remove `.rlistings` from the Read ACL\n5. Save changes",
24+
"Terraform": ""
25+
},
26+
"Recommendation": {
27+
"Text": "Remove `.rlistings` from container read ACLs to prevent **public object enumeration**. Listings should only be available to **authenticated project members**. If external access is needed, implement application-level access control with authenticated APIs.",
28+
"Url": "https://hub.prowler.com/check/objectstorage_container_listing_disabled"
29+
}
30+
},
31+
"Categories": [
32+
"internet-exposed"
33+
],
34+
"DependsOn": [],
35+
"RelatedTo": [],
36+
"Notes": "The `.rlistings` ACL controls whether container listings (GET on container) are allowed. Even without `.rlistings`, individual objects may still be readable if `.r:*` is set. Both ACLs should be removed for full protection."
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from typing import List
2+
3+
from prowler.lib.check.models import Check, CheckReportOpenStack
4+
from prowler.providers.openstack.services.objectstorage.objectstorage_client import (
5+
objectstorage_client,
6+
)
7+
8+
9+
class objectstorage_container_listing_disabled(Check):
10+
"""Ensure object storage container object listings are not publicly accessible."""
11+
12+
def execute(self) -> List[CheckReportOpenStack]:
13+
findings: List[CheckReportOpenStack] = []
14+
15+
for container in objectstorage_client.containers:
16+
report = CheckReportOpenStack(metadata=self.metadata(), resource=container)
17+
acl_entries = [entry.strip() for entry in container.read_ACL.split(",")]
18+
if ".rlistings" in acl_entries:
19+
report.status = "FAIL"
20+
report.status_extended = f"Container {container.name} has public listing enabled (.rlistings) allowing anonymous object enumeration."
21+
elif "*:*" in acl_entries or "*" in acl_entries:
22+
report.status = "FAIL"
23+
report.status_extended = f"Container {container.name} has listing enabled via global read ACL (*:*) allowing all authenticated users to list objects."
24+
else:
25+
report.status = "PASS"
26+
report.status_extended = (
27+
f"Container {container.name} does not have public listing enabled."
28+
)
29+
30+
findings.append(report)
31+
32+
return findings

prowler/providers/openstack/services/objectstorage/objectstorage_container_metadata_sensitive_data/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)