Skip to content

feat(preprod): Add objectstore auth tokens for frontend image requests#113030

Draft
lcian wants to merge 2 commits intolcian/preprod-remove-image-proxy-endpointfrom
lcian/preprod-objectstore-auth
Draft

feat(preprod): Add objectstore auth tokens for frontend image requests#113030
lcian wants to merge 2 commits intolcian/preprod-remove-image-proxy-endpointfrom
lcian/preprod-objectstore-auth

Conversation

@lcian
Copy link
Copy Markdown
Member

@lcian lcian commented Apr 15, 2026

#112469 modified frontend components that render images for snapshots to fetch directly from Objectstore.
As Objectstore will soon enforce auth, we need a way for those requests coming from the browser to carry auth information.

This adds an optional objectstore_token field to responses returned by OrganizationPreprodSnapshotEndpoint and ProjectPreprodBuildDetailsEndpoint.
The token is a short-lived token with read-only permissions, scoped down to the appropriate usecase/org/proj.
That token is passed to the frontend and threaded down to components such as AppIcon and DiffImageDisplay, which include it in image URL via the X-Os-Auth query parameter.

Mint short-lived, read-only objectstore tokens in the build-details and
snapshot-details API responses. The frontend appends these as
`X-Os-Auth` query params on objectstore image URLs, which the proxy
forwards to objectstore for authentication.

The token generator uses `Permission.OBJECT_READ` only and a 5-minute
expiry to minimize the blast radius of any leaked token.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added Scope: Frontend Automatically applied to PRs that change frontend components Scope: Backend Automatically applied to PRs that change backend components labels Apr 15, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.

@github-actions
Copy link
Copy Markdown
Contributor

Backend Test Failures

Failures on 9ee468a in this run:

tests/sentry/preprod/api/endpoints/test_builds.py::BuildsEndpointTest::test_one_buildlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/preprod/api/endpoints/test_builds.py:73: in test_one_build
    assert response.json() == [
E   AssertionError: assert [{'app_info':...e, ...}, ...}] == [{'app_info':...e, ...}, ...}]
E     
E     At index 0 diff: {'id': '79', 'state': 3, 'app_info': {'app_id': 'com.example.app', 'name': None, 'version': None, 'build_number': None, 'date_added': '2026-04-15T09:28:13.153789+00:00', 'date_built': None, 'artifact_type': 2, 'platform': 'android', 'build_configuration': None, 'app_icon_id': None, 'apple_app_info': None, 'android_app_info': {'has_proguard_mapping': True}}, 'vcs_info': {'head_sha': None, 'base_sha': None, 'provider': None, 'head_repo_name': None, 'base_repo_name': None, 'head_ref': None, 'base_ref': None, 'pr_number': None}, 'project_id': 4557971366150176, 'project_slug': 'bar', 'distribution_info': {'is_installable': False, 'download_count': 0, 'release_notes': None, 'error_code': None, 'error_message': None}, 'size_info': None, 'posted_status_checks': None, 'base_artifact_id': None, 'base_build_info': None, 'objectstore_token': None} != {'id': <ANY>, 'state': 3, 'app_info': {'app_id': 'com.example.app', 'name': None, 'version': None, 'build_number': None, 'date_added': <ANY>, 'date_built': None, 'artifact_type': 2, 'platform': 'android', 'build_configuration': None, 'app_icon_id': None, 'apple_app_info': None, 'android_app_info': {'has_proguard_mapping': True}}, 'base_artifact_id': None, 'base_build_info': None, 'distribution_info': {'download_count': 0, 'is_installable': False, 'release_notes': None, 'error_code': None, 'error_message': None}, 'vcs_info': {'head_sha': None, 'base_sha': None, 'provider': None, 'head_repo_name': None, 'base_repo_name': None, 'head_ref': None, 'base_ref': None, 'pr_number': None}, 'project_id': <ANY>, 'posted_status_checks': None, 'project_slug': 'bar', 'size_info': None}
E     
E     Full diff:
E       [
E           {
E               'app_info': {
E                   'android_app_info': {
E                       'has_proguard_mapping': True,
E                   },
E                   'app_icon_id': None,
E                   'app_id': 'com.example.app',
E                   'apple_app_info': None,
E                   'artifact_type': 2,
E                   'build_configuration': None,
E                   'build_number': None,
E     -             'date_added': <ANY>,
E     +             'date_added': '2026-04-15T09:28:13.153789+00:00',
E                   'date_built': None,
E                   'name': None,
E                   'platform': 'android',
E                   'version': None,
E               },
E               'base_artifact_id': None,
E               'base_build_info': None,
E               'distribution_info': {
E                   'download_count': 0,
E                   'error_code': None,
E                   'error_message': None,
E                   'is_installable': False,
E                   'release_notes': None,
E               },
E     -         'id': <ANY>,
E     ?               ^^^^^
E     +         'id': '79',
E     ?               ^^^^
E     +         'objectstore_token': None,
E               'posted_status_checks': None,
E     -         'project_id': <ANY>,
E     +         'project_id': 4557971366150176,
E               'project_slug': 'bar',
E               'size_info': None,
E               'state': 3,
E               'vcs_info': {
E                   'base_ref': None,
E                   'base_repo_name': None,
... (9 more lines)

@sentry
Copy link
Copy Markdown
Contributor

sentry bot commented Apr 15, 2026

Sentry Snapshot Testing

Name Added Removed Modified Renamed Unchanged Status
sentry-frontend
sentry-frontend
0 0 0 0 204 ✅ Unchanged

The test_one_build test does an exact JSON match on the response and
was missing the new objectstore_token field.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant