diff --git a/src/sentry/issues/endpoints/project_event_details.py b/src/sentry/issues/endpoints/project_event_details.py index b3c1650db7f8f9..bac1a81054126a 100644 --- a/src/sentry/issues/endpoints/project_event_details.py +++ b/src/sentry/issues/endpoints/project_event_details.py @@ -1,6 +1,7 @@ from datetime import datetime from typing import Any +import sentry_sdk from rest_framework.request import Request from rest_framework.response import Response @@ -130,4 +131,19 @@ def get(self, request: Request, project, event_id) -> Response: if isinstance(event_dict["datetime"], datetime): event_dict["datetime"] = event_dict["datetime"].isoformat() + try: + scrub_ip_addresses = project.organization.get_option( + "sentry:require_scrub_ip_address", False + ) or project.get_option("sentry:scrub_ip_address", False) + + if scrub_ip_addresses: + if "spans" in event_dict: + for span in event_dict["spans"]: + if "sentry_tags" not in span: + continue + if "user.ip" in span["sentry_tags"]: + del span["sentry_tags"]["user.ip"] + except Exception as e: + sentry_sdk.capture_exception(e) + return Response(event_dict, status=200) diff --git a/tests/snuba/api/endpoints/test_project_event_details.py b/tests/snuba/api/endpoints/test_project_event_details.py index fe9f54f365acb3..8c2c155fefb5f1 100644 --- a/tests/snuba/api/endpoints/test_project_event_details.py +++ b/tests/snuba/api/endpoints/test_project_event_details.py @@ -385,3 +385,47 @@ def test_project_not_associated_with_event(self): response = self.client.get(url, format="json") assert response.status_code == 404, response.content assert response.data == {"detail": "Event not found"} + + +class ProjectEventDetailsTransactionTestScrubbed(APITestCase, SnubaTestCase): + def setUp(self): + super().setUp() + self.login_as(user=self.user) + data = load_data("transaction") + for span in data["spans"]: + span["sentry_tags"]["user.ip"] = "127.0.0.1" + self.event = self.store_event(data=data, project_id=self.project.id) + + self.url = reverse( + "sentry-api-0-event-json", + kwargs={ + "organization_id_or_slug": self.organization.slug, + "project_id_or_slug": self.project.slug, + "event_id": self.event.event_id, + }, + ) + + def test_no_scrubbed(self): + response = self.client.get(self.url, format="json") + assert response.status_code == 200, response.content + assert len(response.data["spans"]) > 0 + for span in response.data["spans"]: + assert "user.ip" in span["sentry_tags"] + + def test_scrubbed_project(self): + self.project.update_option("sentry:scrub_ip_address", True) + + response = self.client.get(self.url, format="json") + assert response.status_code == 200, response.content + assert len(response.data["spans"]) > 0 + for span in response.data["spans"]: + assert "user.ip" not in span["sentry_tags"] + + def test_scrubbed_organization(self): + self.organization.update_option("sentry:require_scrub_ip_address", True) + + response = self.client.get(self.url, format="json") + assert response.status_code == 200, response.content + assert len(response.data["spans"]) > 0 + for span in response.data["spans"]: + assert "user.ip" not in span["sentry_tags"]