From a517c575dd79142917b961ca2baeb86eb27bc7f1 Mon Sep 17 00:00:00 2001 From: Prowler Bot Date: Wed, 11 Jun 2025 11:19:43 +0200 Subject: [PATCH] revert: RLS transactions handling and DB custom backend (#7995) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Víctor Fernández Poyatos --- .github/workflows/api-pull-request.yml | 2 +- api/.pre-commit-config.yaml | 2 +- api/CHANGELOG.md | 9 ++- api/pyproject.toml | 2 +- api/src/backend/api/base_views.py | 62 ++++++-------------- api/src/backend/api/specs/v1.yaml | 2 +- api/src/backend/api/v1/views.py | 2 +- api/src/backend/config/django/base.py | 1 - api/src/backend/database_backend/__init__.py | 0 api/src/backend/database_backend/base.py | 15 ----- 10 files changed, 29 insertions(+), 68 deletions(-) delete mode 100644 api/src/backend/database_backend/__init__.py delete mode 100644 api/src/backend/database_backend/base.py diff --git a/.github/workflows/api-pull-request.yml b/.github/workflows/api-pull-request.yml index 604c878bf6..7addd0fd42 100644 --- a/.github/workflows/api-pull-request.yml +++ b/.github/workflows/api-pull-request.yml @@ -159,7 +159,7 @@ jobs: working-directory: ./api if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' run: | - poetry run safety check --ignore 70612,66963,74429 + poetry run safety check --ignore 70612,66963,74429,77119 - name: Vulture working-directory: ./api diff --git a/api/.pre-commit-config.yaml b/api/.pre-commit-config.yaml index 1cd04529c3..ab495505c5 100644 --- a/api/.pre-commit-config.yaml +++ b/api/.pre-commit-config.yaml @@ -80,7 +80,7 @@ repos: - id: safety name: safety description: "Safety is a tool that checks your installed dependencies for known security vulnerabilities" - entry: bash -c 'poetry run safety check --ignore 70612,66963,74429' + entry: bash -c 'poetry run safety check --ignore 70612,66963,74429,77119' language: system - id: vulture diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index d4e4e6f4f4..885d856202 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to the **Prowler API** are documented in this file. +## [v1.8.4] (Prowler v5.7.4) + +### Removed +- Reverted RLS transaction handling and DB custom backend [(#7994)](https://github.com/prowler-cloud/prowler/pull/7994). + +--- + ## [v1.8.3] (Prowler v5.7.3) ### Added @@ -15,7 +22,6 @@ All notable changes to the **Prowler API** are documented in this file. - Reverted the change `get_with_retry` to use the original `get` method for retrieving tasks [(#7932)](https://github.com/prowler-cloud/prowler/pull/7932). - Fixed the connection status verification before launching a scan [(#7831)](https://github.com/prowler-cloud/prowler/pull/7831) - --- ## [v1.8.2] (Prowler v5.7.2) @@ -98,7 +104,6 @@ All notable changes to the **Prowler API** are documented in this file. - Fixed a race condition when deleting export files after the S3 upload [(#7172)](https://github.com/prowler-cloud/prowler/pull/7172). - Handled exception when a provider has no secret in test connection [(#7283)](https://github.com/prowler-cloud/prowler/pull/7283). - ### Added - Support for developing new integrations [(#7167)](https://github.com/prowler-cloud/prowler/pull/7167). diff --git a/api/pyproject.toml b/api/pyproject.toml index 732634b702..d519c2510c 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -35,7 +35,7 @@ name = "prowler-api" package-mode = false # Needed for the SDK compatibility requires-python = ">=3.11,<3.13" -version = "1.8.3" +version = "1.8.4" [project.scripts] celery = "src.backend.config.settings.celery" diff --git a/api/src/backend/api/base_views.py b/api/src/backend/api/base_views.py index 7ff0695af8..605afe332d 100644 --- a/api/src/backend/api/base_views.py +++ b/api/src/backend/api/base_views.py @@ -47,9 +47,11 @@ class BaseViewSet(ModelViewSet): class BaseRLSViewSet(BaseViewSet): - def initial(self, request, *args, **kwargs): - super().initial(request, *args, **kwargs) + def dispatch(self, request, *args, **kwargs): + with transaction.atomic(): + return super().dispatch(request, *args, **kwargs) + def initial(self, request, *args, **kwargs): # Ideally, this logic would be in the `.setup()` method but DRF view sets don't call it # https://docs.djangoproject.com/en/5.1/ref/class-based-views/base/#django.views.generic.base.View.setup if request.auth is None: @@ -59,19 +61,9 @@ class BaseRLSViewSet(BaseViewSet): if tenant_id is None: raise NotAuthenticated("Tenant ID is not present in token") - self.request.tenant_id = tenant_id - - self._rls_cm = rls_transaction(tenant_id) - self._rls_cm.__enter__() - - def finalize_response(self, request, response, *args, **kwargs): - response = super().finalize_response(request, response, *args, **kwargs) - - if hasattr(self, "_rls_cm"): - self._rls_cm.__exit__(None, None, None) - del self._rls_cm - - return response + with rls_transaction(tenant_id): + self.request.tenant_id = tenant_id + return super().initial(request, *args, **kwargs) def get_serializer_context(self): context = super().get_serializer_context() @@ -117,8 +109,6 @@ class BaseTenantViewset(BaseViewSet): pass # Tenant might not exist, handle gracefully def initial(self, request, *args, **kwargs): - super().initial(request, *args, **kwargs) - if request.auth is None: raise NotAuthenticated @@ -127,27 +117,19 @@ class BaseTenantViewset(BaseViewSet): raise NotAuthenticated("Tenant ID is not present in token") user_id = str(request.user.id) - - self._rls_cm = rls_transaction(value=user_id, parameter=POSTGRES_USER_VAR) - self._rls_cm.__enter__() - - def finalize_response(self, request, response, *args, **kwargs): - response = super().finalize_response(request, response, *args, **kwargs) - - if hasattr(self, "_rls_cm"): - self._rls_cm.__exit__(None, None, None) - del self._rls_cm - - return response + with rls_transaction(value=user_id, parameter=POSTGRES_USER_VAR): + return super().initial(request, *args, **kwargs) class BaseUserViewset(BaseViewSet): - def initial(self, request, *args, **kwargs): - super().initial(request, *args, **kwargs) + def dispatch(self, request, *args, **kwargs): + with transaction.atomic(): + return super().dispatch(request, *args, **kwargs) + def initial(self, request, *args, **kwargs): # TODO refactor after improving RLS on users if request.stream is not None and request.stream.method == "POST": - return + return super().initial(request, *args, **kwargs) if request.auth is None: raise NotAuthenticated @@ -155,16 +137,6 @@ class BaseUserViewset(BaseViewSet): if tenant_id is None: raise NotAuthenticated("Tenant ID is not present in token") - self.request.tenant_id = tenant_id - - self._rls_cm = rls_transaction(tenant_id) - self._rls_cm.__enter__() - - def finalize_response(self, request, response, *args, **kwargs): - response = super().finalize_response(request, response, *args, **kwargs) - - if hasattr(self, "_rls_cm"): - self._rls_cm.__exit__(None, None, None) - del self._rls_cm - - return response + with rls_transaction(tenant_id): + self.request.tenant_id = tenant_id + return super().initial(request, *args, **kwargs) diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index 9b45f284ce..d2f071f627 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -1,7 +1,7 @@ openapi: 3.0.3 info: title: Prowler API - version: 1.8.3 + version: 1.8.4 description: |- Prowler API specification. diff --git a/api/src/backend/api/v1/views.py b/api/src/backend/api/v1/views.py index 74664f9402..78fcdff87b 100644 --- a/api/src/backend/api/v1/views.py +++ b/api/src/backend/api/v1/views.py @@ -260,7 +260,7 @@ class SchemaView(SpectacularAPIView): def get(self, request, *args, **kwargs): spectacular_settings.TITLE = "Prowler API" - spectacular_settings.VERSION = "1.8.3" + spectacular_settings.VERSION = "1.8.4" spectacular_settings.DESCRIPTION = ( "Prowler API specification.\n\nThis file is auto-generated." ) diff --git a/api/src/backend/config/django/base.py b/api/src/backend/config/django/base.py index 92e7da0a99..995e2b946d 100644 --- a/api/src/backend/config/django/base.py +++ b/api/src/backend/config/django/base.py @@ -127,7 +127,6 @@ DJANGO_GUID = { } DATABASE_ROUTERS = ["api.db_router.MainRouter"] -POSTGRES_EXTRA_DB_BACKEND_BASE = "database_backend" # Password validation diff --git a/api/src/backend/database_backend/__init__.py b/api/src/backend/database_backend/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/api/src/backend/database_backend/base.py b/api/src/backend/database_backend/base.py deleted file mode 100644 index 69fee7df4b..0000000000 --- a/api/src/backend/database_backend/base.py +++ /dev/null @@ -1,15 +0,0 @@ -import django.db -from django.db.backends.postgresql.base import ( - DatabaseWrapper as BuiltinPostgresDatabaseWrapper, -) -from psycopg2 import InterfaceError - - -class DatabaseWrapper(BuiltinPostgresDatabaseWrapper): - def create_cursor(self, name=None): - try: - return super().create_cursor(name=name) - except InterfaceError: - django.db.close_old_connections() - django.db.connection.connect() - return super().create_cursor(name=name)