Compare commits

...
8 changed files with 85 additions and 5 deletions

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:3.12.15-slim-trixie@sha256:05cda9777409a9c3ffddd94a4c476b79f0769a0b4857f0c7ed9226b6800b0d6f AS build
FROM python:3.12.16-slim-trixie@sha256:8523d6abeb48ceae0b7240d30c5808fc26cb79c1a635bacdf19cf3baecfbec07 AS build
LABEL maintainer="https://github.com/prowler-cloud/prowler"
LABEL org.opencontainers.image.source="https://github.com/prowler-cloud/prowler"
+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:3.12.15-slim-trixie@sha256:05cda9777409a9c3ffddd94a4c476b79f0769a0b4857f0c7ed9226b6800b0d6f AS build
FROM python:3.12.16-slim-trixie@sha256:8523d6abeb48ceae0b7240d30c5808fc26cb79c1a635bacdf19cf3baecfbec07 AS build
LABEL maintainer="https://github.com/prowler-cloud/api"
@@ -0,0 +1 @@
Python base image from 3.12.15 to 3.12.16 in the API container image, patching CVE-2026-115557
@@ -0,0 +1 @@
MongoDB Atlas connection errors now include the HTTP status, error code and detail returned by Atlas instead of a generic HTTP error, and a custom exception message no longer persists into later errors of the same type
@@ -0,0 +1 @@
Python base image from 3.12.15 to 3.12.16 in the SDK container image, patching CVE-2026-115557
@@ -38,7 +38,9 @@ class MongoDBAtlasBaseException(ProwlerException):
def __init__(self, code, file=None, original_exception=None, message=None):
provider = "MongoDB Atlas"
error_info = self.MONGODBATLAS_ERROR_CODES.get((code, self.__class__.__name__))
error_info = dict(
self.MONGODBATLAS_ERROR_CODES.get((code, self.__class__.__name__))
)
if message:
error_info["message"] = message
super().__init__(
@@ -236,7 +236,12 @@ class MongodbatlasProvider(Provider):
message="MongoDB Atlas authentication failed. Please check your API credentials.",
)
response.raise_for_status()
if not response.ok:
raise MongoDBAtlasIdentityError(
file=os.path.basename(__file__),
message=MongodbatlasProvider._describe_api_error(response),
)
organizations_data = response.json()
# Extract organization information from the response
@@ -266,7 +271,7 @@ class MongodbatlasProvider(Provider):
return identity
except MongoDBAtlasAuthenticationError:
except (MongoDBAtlasAuthenticationError, MongoDBAtlasIdentityError):
raise
except Exception as error:
logger.critical(
@@ -276,6 +281,22 @@ class MongodbatlasProvider(Provider):
original_exception=error,
)
@staticmethod
def _describe_api_error(response) -> str:
"""Build an identity error message that keeps the reason Atlas returns."""
message = f"MongoDB Atlas identity setup failed - HTTP {response.status_code}"
try:
body = response.json()
except ValueError:
return message
if not isinstance(body, dict):
return message
if body.get("errorCode"):
message += f" {body['errorCode']}"
if body.get("detail"):
message += f": {body['detail']}"
return message
def print_credentials(self):
"""Print the MongoDB Atlas credentials"""
report_lines = [
@@ -136,6 +136,60 @@ class TestMongodbatlasProvider:
with pytest.raises(MongoDBAtlasIdentityError):
MongodbatlasProvider.setup_identity(session)
@patch("requests.get")
def test_setup_identity_forbidden_keeps_atlas_error_detail(self, mock_get):
mock_response = MagicMock()
mock_response.status_code = 403
mock_response.ok = False
mock_response.json.return_value = {
"detail": "IP address 203.0.113.10 is not allowed to access this resource.",
"error": 403,
"errorCode": "IP_ADDRESS_NOT_ON_ACCESS_LIST",
"reason": "Forbidden",
}
mock_get.return_value = mock_response
session = MongoDBAtlasSession(
public_key=ATLAS_PUBLIC_KEY,
private_key=ATLAS_PRIVATE_KEY,
)
with pytest.raises(MongoDBAtlasIdentityError) as exc_info:
MongodbatlasProvider.setup_identity(session)
assert str(exc_info.value) == (
"MongoDBAtlasIdentityError[8003]: MongoDB Atlas identity setup failed"
" - HTTP 403 IP_ADDRESS_NOT_ON_ACCESS_LIST: IP address 203.0.113.10"
" is not allowed to access this resource."
)
@patch("requests.get")
def test_setup_identity_error_without_json_body_reports_status(self, mock_get):
mock_response = MagicMock()
mock_response.status_code = 502
mock_response.ok = False
mock_response.json.side_effect = ValueError("No JSON")
mock_get.return_value = mock_response
session = MongoDBAtlasSession(
public_key=ATLAS_PUBLIC_KEY,
private_key=ATLAS_PRIVATE_KEY,
)
with pytest.raises(MongoDBAtlasIdentityError) as exc_info:
MongodbatlasProvider.setup_identity(session)
assert exc_info.value.message == (
"MongoDB Atlas identity setup failed - HTTP 502"
)
def test_custom_message_does_not_leak_into_later_exceptions(self):
MongoDBAtlasIdentityError(message="custom detail")
assert (
MongoDBAtlasIdentityError().message == "MongoDB Atlas identity setup failed"
)
def test_test_connection_success(self):
"""Test successful connection test"""
with (