diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index a950046b34..8efce29fe7 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -4112,12 +4112,13 @@ paths: summary: Download ZIP report parameters: - in: query - name: fields[scans] + name: fields[scan-reports] schema: type: array items: type: string - enum: [] + enum: + - id description: endpoint return only specific fields in the response on a per-type basis by including a fields[TYPE] query parameter. explode: false diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index 73f2bab027..34df22cfa9 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -854,9 +854,9 @@ class TestProviderViewSet: included_data = response.json()["included"] for expected_type in expected_resources: - assert any( - d.get("type") == expected_type for d in included_data - ), f"Expected type '{expected_type}' not found in included data" + assert any(d.get("type") == expected_type for d in included_data), ( + f"Expected type '{expected_type}' not found in included data" + ) def test_providers_retrieve(self, authenticated_client, providers_fixture): provider1, *_ = providers_fixture @@ -2243,9 +2243,9 @@ class TestResourceViewSet: included_data = response.json()["included"] for expected_type in expected_resources: - assert any( - d.get("type") == expected_type for d in included_data - ), f"Expected type '{expected_type}' not found in included data" + assert any(d.get("type") == expected_type for d in included_data), ( + f"Expected type '{expected_type}' not found in included data" + ) @pytest.mark.parametrize( "filter_name, filter_value, expected_count", @@ -2451,9 +2451,9 @@ class TestFindingViewSet: included_data = response.json()["included"] for expected_type in expected_resources: - assert any( - d.get("type") == expected_type for d in included_data - ), f"Expected type '{expected_type}' not found in included data" + assert any(d.get("type") == expected_type for d in included_data), ( + f"Expected type '{expected_type}' not found in included data" + ) @pytest.mark.parametrize( "filter_name, filter_value, expected_count", @@ -2735,9 +2735,9 @@ class TestJWTFields: reverse("token-obtain"), data, format="json" ) - assert ( - response.status_code == status.HTTP_200_OK - ), f"Unexpected status code: {response.status_code}" + assert response.status_code == status.HTTP_200_OK, ( + f"Unexpected status code: {response.status_code}" + ) access_token = response.data["attributes"]["access"] payload = jwt.decode(access_token, options={"verify_signature": False}) @@ -2751,23 +2751,23 @@ class TestJWTFields: # Verify expected fields for field in expected_fields: assert field in payload, f"The field '{field}' is not in the JWT" - assert ( - payload[field] == expected_fields[field] - ), f"The value of '{field}' does not match" + assert payload[field] == expected_fields[field], ( + f"The value of '{field}' does not match" + ) # Verify time fields are integers for time_field in ["exp", "iat", "nbf"]: assert time_field in payload, f"The field '{time_field}' is not in the JWT" - assert isinstance( - payload[time_field], int - ), f"The field '{time_field}' is not an integer" + assert isinstance(payload[time_field], int), ( + f"The field '{time_field}' is not an integer" + ) # Verify identification fields are non-empty strings for id_field in ["jti", "sub", "tenant_id"]: assert id_field in payload, f"The field '{id_field}' is not in the JWT" - assert ( - isinstance(payload[id_field], str) and payload[id_field] - ), f"The field '{id_field}' is not a valid string" + assert isinstance(payload[id_field], str) and payload[id_field], ( + f"The field '{id_field}' is not a valid string" + ) @pytest.mark.django_db diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index 8ff4568691..5a6f3ed671 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -819,12 +819,12 @@ class ScanTaskSerializer(RLSSerializer): ] -class ScanReportSerializer(RLSSerializer): +class ScanReportSerializer(serializers.Serializer): + id = serializers.CharField(source="scan") + class Meta: - model = Scan - fields = [ - "id", - ] + resource_name = "scan-reports" + fields = ["id"] class ResourceTagSerializer(RLSSerializer): diff --git a/api/src/backend/api/v1/views.py b/api/src/backend/api/v1/views.py index 4a097a03ec..385b85804a 100644 --- a/api/src/backend/api/v1/views.py +++ b/api/src/backend/api/v1/views.py @@ -1115,22 +1115,22 @@ class ScanViewSet(BaseRLSViewSet): def report(self, request, pk=None): scan_instance = Scan.objects.get(pk=pk) output_path = scan_instance.output_path - if 1 == 2 and scan_instance.upload_to_s3: + if scan_instance.upload_to_s3: s3_client = None try: - s3_client = boto3.client("s3") + s3_client = boto3.client( + "s3", + aws_access_key_id=env.str("DJANGO_ARTIFACTS_AWS_ACCESS_KEY_ID"), + aws_secret_access_key=env.str( + "DJANGO_ARTIFACTS_AWS_SECRET_ACCESS_KEY" + ), + aws_session_token=env.str("DJANGO_ARTIFACTS_AWS_SESSION_TOKEN"), + region_name=env.str("DJANGO_ARTIFACTS_AWS_DEFAULT_REGION"), + ) s3_client.list_buckets() except (ClientError, NoCredentialsError, ParamValidationError): try: - s3_client = boto3.client( - "s3", - aws_access_key_id=env.str("DJANGO_ARTIFACTS_AWS_ACCESS_KEY_ID"), - aws_secret_access_key=env.str( - "DJANGO_ARTIFACTS_AWS_SECRET_ACCESS_KEY" - ), - aws_session_token=env.str("DJANGO_ARTIFACTS_AWS_SESSION_TOKEN"), - region_name=env.str("DJANGO_ARTIFACTS_AWS_DEFAULT_REGION"), - ) + s3_client = boto3.client("s3") s3_client.list_buckets() except (ClientError, NoCredentialsError, ParamValidationError): return Response( diff --git a/api/src/backend/tasks/jobs/export.py b/api/src/backend/tasks/jobs/export.py index c344976a9f..3a8ec045f8 100644 --- a/api/src/backend/tasks/jobs/export.py +++ b/api/src/backend/tasks/jobs/export.py @@ -16,9 +16,9 @@ from prowler.lib.outputs.html.html import HTML from prowler.lib.outputs.ocsf.ocsf import OCSF logger = get_task_logger(__name__) - tmp_output_directory = "/tmp/prowler_api_output" + # Predefined mapping for output formats and their configurations OUTPUT_FORMATS_MAPPING = { "csv": { @@ -30,14 +30,6 @@ OUTPUT_FORMATS_MAPPING = { "html": {"class": HTML, "suffix": html_file_suffix, "kwargs": {"stats": {}}}, } -# Mapping provider types to their identity components for output paths -PROVIDER_IDENTITY_MAP = { - "aws": lambda p: p.identity.account, - "azure": lambda p: p.identity.tenant_domain, - "gcp": lambda p: p.identity.profile, - "kubernetes": lambda p: p.identity.context.replace(":", "_").replace("/", "_"), -} - def _compress_output_files(output_directory: str) -> str: """