Browse Source

fix(security): hide integrations code from members (#70128)

This change hides `code` field from integration details for members.
This is to prevent from misusing integration code by member-level users.
Alexander Tarasov 9 months ago
parent
commit
8c78f1b5d0

+ 3 - 1
src/sentry/api/endpoints/integrations/sentry_apps/installation/details.py

@@ -27,7 +27,9 @@ class SentryAppInstallationDetailsEndpoint(SentryAppInstallationBaseEndpoint):
     }
 
     def get(self, request: Request, installation) -> Response:
-        return Response(serialize(SentryAppInstallation.objects.get(id=installation.id)))
+        return Response(
+            serialize(SentryAppInstallation.objects.get(id=installation.id), access=request.access)
+        )
 
     def delete(self, request: Request, installation) -> Response:
         installation = SentryAppInstallation.objects.get(id=installation.id)

+ 1 - 1
src/sentry/api/endpoints/integrations/sentry_apps/installation/index.py

@@ -39,7 +39,7 @@ class SentryAppInstallationsEndpoint(SentryAppInstallationsBaseEndpoint):
             queryset=queryset,
             order_by="-date_added",
             paginator_cls=OffsetPaginator,
-            on_results=lambda x: serialize(x, request.user),
+            on_results=lambda x: serialize(x, request.user, access=request.access),
         )
 
     def post(self, request: Request, organization) -> Response:

+ 2 - 2
src/sentry/api/serializers/models/sentry_app_installation.py

@@ -36,7 +36,7 @@ class SentryAppInstallationSerializer(Serializer):
             }
         return result
 
-    def serialize(self, install, attrs, user):
+    def serialize(self, install, attrs, user, access=None):
         data = {
             "app": {"uuid": attrs["sentry_app"].uuid, "slug": attrs["sentry_app"].slug},
             "organization": {"slug": attrs["organization"].slug},
@@ -44,7 +44,7 @@ class SentryAppInstallationSerializer(Serializer):
             "status": SentryAppInstallationStatus.as_str(install.status),
         }
 
-        if install.api_grant:
+        if install.api_grant and access and access.has_scope("org:integrations"):
             data["code"] = install.api_grant.code
 
         return data

+ 20 - 2
tests/sentry/api/endpoints/test_organization_sentry_app_installation_details.py

@@ -58,8 +58,26 @@ class SentryAppInstallationDetailsTest(APITestCase):
 
 @control_silo_test
 class GetSentryAppInstallationDetailsTest(SentryAppInstallationDetailsTest):
-    def test_access_within_installs_organization(self):
-        self.login_as(user=self.user)
+    def test_access_within_installs_organization_by_member(self):
+        member_user = self.create_user("member@example.com")
+        self.create_member(organization=self.org, user=member_user, role="member")
+        self.login_as(member_user)
+
+        response = self.client.get(self.url, format="json")
+
+        assert response.status_code == 200, response.content
+        assert response.data == {
+            "app": {"uuid": self.unpublished_app.uuid, "slug": self.unpublished_app.slug},
+            "organization": {"slug": self.org.slug},
+            "uuid": self.installation2.uuid,
+            "status": "pending",
+        }
+
+    def test_access_within_installs_organization_by_manager(self):
+        manager_user = self.create_user("manager@example.com")
+        self.create_member(organization=self.org, user=manager_user, role="manager")
+        self.login_as(manager_user)
+
         response = self.client.get(self.url, format="json")
 
         assert response.status_code == 200, response.content

+ 0 - 2
tests/sentry/mediators/sentry_app_installations/test_installation_notifier.py

@@ -56,7 +56,6 @@ class TestInstallationNotifier(TestCase):
                     "app": {"uuid": self.sentry_app.uuid, "slug": self.sentry_app.slug},
                     "organization": {"slug": self.organization.slug},
                     "uuid": self.install.uuid,
-                    "code": self.install.api_grant.code,
                     "status": "installed",
                 }
             },
@@ -85,7 +84,6 @@ class TestInstallationNotifier(TestCase):
                     "app": {"uuid": self.sentry_app.uuid, "slug": self.sentry_app.slug},
                     "organization": {"slug": self.organization.slug},
                     "uuid": self.install.uuid,
-                    "code": self.install.api_grant.code,
                     "status": "installed",
                 }
             },