sentry icon indicating copy to clipboard operation
sentry copied to clipboard

feat(dev-toolbar): Add organization derived API applications

Open cmanallen opened this issue 1 year ago • 11 comments
trafficstars

Overview

To enable the dev-toolbar feature we want to allow public, third-party applications (think "Login with CodeCov" but self-serve and for all organizations) to fetch Sentry data on behalf of a Sentry user. To accommodate this I've:

  • [x] Added a "scoping_organization_id" column to the ApiToken model and replica.
  • [x] Added a "organization_id" column to the ApiApplication model.
  • [x] Updated the oauth flow to set the "scoping_organization_id" on the ApiToken when an "organization_id" is present on the ApiApplication.
  • [x] Updated the middleware responsible for gating access.
  • [x] Added a resource for managing organization ApiApplication instances.

Goal

The goal is to allow customers to authenticate with Sentry from a third-party origin.

How It Works

  1. A customer defines an ApiApplication instance tied to their organization.
  2. This ApiApplication contains the valid origin and redirect locations for an authorization request for that organization.
  3. The ApiApplication generates a client-id value. This value is public and is passed to the Javascript SDK's initializer (e.g. sdk.init(..., client_id=xyz).
  4. The SDK reads this client-id and initiates Sentry's oauth flow (/oauth/authorize/) either through a hard-redirect or a pop-up window. Making sure to specify the client-id in the request parameters.
  5. Sentry appends a url fragment containing the access token and redierects back to the requester's application.
  6. The token is now accessible by the third-party program and can be used to make API requests to Sentry.

CORS

To manage CORS issues, the login flow will be initiated from an iframe with a sentry.io origin.

Supporting Documentation

PRD: https://www.notion.so/sentry/FY-25-Q2-Dev-Toolbar-e2a259c063634f93a6c3d89584e812d8

Security

Public clients present two problems:

  1. First there is a phishing risk where a malicious third-party is given an access_token and uses that token to extract sensitive data from Sentry servers.
  2. Second there is a risk that a legitimate third-party provider may use an access_token to read data from other organizations.

To address these issues I've done two things:

  1. ApiApplications will only generate credentials if the user is a member of the organization.
  2. ApiTokens will be scoped to the ApiApplication's organization_id. a. Requests for data outside of the organization will be denied.

cmanallen avatar Jul 19 '24 21:07 cmanallen

This PR has a migration; here is the generated SQL for src/sentry/hybridcloud/migrations/0017_add_public_api_applications.py src/sentry/migrations/0744_add_public_api_applications.py ()

--
-- Add field organization_id to apiapplication
--
ALTER TABLE "sentry_apiapplication" ADD COLUMN "organization_id" bigint NULL;
--
-- Add field scoping_organization_id to apitoken
--
ALTER TABLE "sentry_apitoken" ADD COLUMN "scoping_organization_id" bigint NULL;
CREATE UNIQUE INDEX CONCURRENTLY "sentry_apiapplication_organization_id_aade894f_uniq" ON "sentry_apiapplication" ("organization_id");
ALTER TABLE "sentry_apiapplication" ADD CONSTRAINT "sentry_apiapplication_organization_id_aade894f_uniq" UNIQUE USING INDEX "sentry_apiapplication_organization_id_aade894f_uniq";
CREATE INDEX CONCURRENTLY "sentry_apitoken_scoping_organization_id_b0d65472" ON "sentry_apitoken" ("scoping_organization_id");

github-actions[bot] avatar Jul 22 '24 20:07 github-actions[bot]

Codecov Report

Attention: Patch coverage is 91.91919% with 8 lines in your changes missing coverage. Please review.

:white_check_mark: All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ntry/api/endpoints/organization_api_application.py 94.36% 2 Missing and 2 partials :warning:
src/sentry/api/serializers/models/group.py 42.85% 2 Missing and 2 partials :warning:
Additional details and impacted files

:loudspeaker: Thoughts on this report? Let us know!

codecov[bot] avatar Jul 22 '24 20:07 codecov[bot]

This PR has a migration; here is the generated SQL for src/sentry/migrations/0745_add_public_api_applications.py ()

--
-- Add field organization_id to apiapplication
--
ALTER TABLE "sentry_apiapplication" ADD COLUMN "organization_id" bigint NULL;
--
-- Add field scoping_organization_id to apitoken
--
ALTER TABLE "sentry_apitoken" ADD COLUMN "scoping_organization_id" bigint NULL;
CREATE UNIQUE INDEX CONCURRENTLY "sentry_apiapplication_organization_id_aade894f_uniq" ON "sentry_apiapplication" ("organization_id");
ALTER TABLE "sentry_apiapplication" ADD CONSTRAINT "sentry_apiapplication_organization_id_aade894f_uniq" UNIQUE USING INDEX "sentry_apiapplication_organization_id_aade894f_uniq";
CREATE INDEX CONCURRENTLY "sentry_apitoken_scoping_organization_id_b0d65472" ON "sentry_apitoken" ("scoping_organization_id");

github-actions[bot] avatar Jul 23 '24 15:07 github-actions[bot]

I'd be more comfortable if we put this behind a feature flag limiting it to specific organizations until we're sure the authn/authz flow is ready for production.

mdtro avatar Jul 25 '24 17:07 mdtro

In a scenario where a user knows their access token has been compromised, what options do they have?

mdtro avatar Jul 25 '24 17:07 mdtro

@mdtro They're supposed to be able to revoke the token with a logout request. I'll have to find exactly where that happens.

cmanallen avatar Jul 25 '24 17:07 cmanallen

This PR has a migration; here is the generated SQL for src/sentry/migrations/0747_add_public_api_applications.py ()

--
-- Add field organization_id to apiapplication
--
ALTER TABLE "sentry_apiapplication" ADD COLUMN "organization_id" bigint NULL;
--
-- Add field scoping_organization_id to apitoken
--
ALTER TABLE "sentry_apitoken" ADD COLUMN "scoping_organization_id" bigint NULL;
CREATE UNIQUE INDEX CONCURRENTLY "sentry_apiapplication_organization_id_aade894f_uniq" ON "sentry_apiapplication" ("organization_id");
ALTER TABLE "sentry_apiapplication" ADD CONSTRAINT "sentry_apiapplication_organization_id_aade894f_uniq" UNIQUE USING INDEX "sentry_apiapplication_organization_id_aade894f_uniq";
CREATE INDEX CONCURRENTLY "sentry_apitoken_scoping_organization_id_b0d65472" ON "sentry_apitoken" ("scoping_organization_id");

github-actions[bot] avatar Jul 29 '24 18:07 github-actions[bot]

🚨 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[bot] avatar Jul 29 '24 18:07 github-actions[bot]

@evanpurkhiser @nhsiehgit @JoshFerge Ya'll worked on the enterprise team right? Do you have any opinions on this auth flow?

cmanallen avatar Aug 06 '24 19:08 cmanallen

This PR has a migration; here is the generated SQL for src/sentry/migrations/0748_add_public_api_applications.py ()

--
-- Add field organization_id to apiapplication
--
ALTER TABLE "sentry_apiapplication" ADD COLUMN "organization_id" bigint NULL;
--
-- Add field scoping_organization_id to apitoken
--
ALTER TABLE "sentry_apitoken" ADD COLUMN "scoping_organization_id" bigint NULL;
CREATE UNIQUE INDEX CONCURRENTLY "sentry_apiapplication_organization_id_aade894f_uniq" ON "sentry_apiapplication" ("organization_id");
ALTER TABLE "sentry_apiapplication" ADD CONSTRAINT "sentry_apiapplication_organization_id_aade894f_uniq" UNIQUE USING INDEX "sentry_apiapplication_organization_id_aade894f_uniq";
CREATE INDEX CONCURRENTLY "sentry_apitoken_scoping_organization_id_b0d65472" ON "sentry_apitoken" ("scoping_organization_id");

github-actions[bot] avatar Aug 09 '24 14:08 github-actions[bot]

Bundle Report

Changes will increase total bundle size by 259 bytes :arrow_up:

Bundle name Size Change
app-webpack-bundle-array-push 28.69MB 259 bytes :arrow_up:

codecov[bot] avatar Aug 09 '24 14:08 codecov[bot]

This pull request has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you add the label WIP, I will leave it alone unless WIP is removed ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

getsantry[bot] avatar Aug 31 '24 07:08 getsantry[bot]