Skip to content

feat(seer-infra-telemetry): Implement per-customer SA generation & deletion for GCP integrations#120266

Draft
shashjar wants to merge 5 commits into
masterfrom
shashjar/implement-per-customer-service-account-generation-and-deletion-gcp-integration
Draft

feat(seer-infra-telemetry): Implement per-customer SA generation & deletion for GCP integrations#120266
shashjar wants to merge 5 commits into
masterfrom
shashjar/implement-per-customer-service-account-generation-and-deletion-gcp-integration

Conversation

@shashjar

@shashjar shashjar commented Jul 21, 2026

Copy link
Copy Markdown
Member

PR 4/4 for CW-1691

Implements the GCP IAM API calls necessary for creating and deleting per-customer service accounts in the sentry-connectors GCP project, as part of the GCP MCP org-level integration setup and teardown logic. The SA email, when generated, is stored in OrganizationIntegration.config upon integration installation so that Seer can use it for SA impersonation.

https://app.notion.com/p/sentry/GCP-MCP-Org-Level-Integration-39f8b10e4b5d8030ba01cd62373641df

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Jul 21, 2026
@shashjar
shashjar changed the base branch from master to shashjar/implement-GcpOrgMonitoringProvider July 21, 2026 21:56
@shashjar shashjar changed the title Implement GcpOrgMonitoringProvider feat(seer-infra-telemetry): Implement per-customer SA generation & deletion for GCP integrations Jul 21, 2026
Comment thread src/sentry/integrations/gcp/client.py
Comment thread src/sentry/integrations/gcp/integration.py Outdated
Comment thread src/sentry/integrations/gcp/client.py
Base automatically changed from shashjar/implement-GcpOrgMonitoringProvider to master July 22, 2026 01:03
@shashjar
shashjar force-pushed the shashjar/implement-per-customer-service-account-generation-and-deletion-gcp-integration branch from f777b71 to 238a54c Compare July 22, 2026 16:30
Comment thread src/sentry/integrations/gcp/integration.py
…count-generation-and-deletion-gcp-integration
…count-generation-and-deletion-gcp-integration
Comment thread src/sentry/integrations/gcp/client.py
shashjar added a commit that referenced this pull request Jul 24, 2026
…g per-org service accounts (#120499)

PR 3/4 for
[CW-1691](https://linear.app/getsentry/issue/CW-1691/set-up-sentry-connectors-gcp-project-per-customer-sa-creation-and)

Adds a new `GcpServiceAccount` model to track GCP service accounts
created in the `sentry-connectors` project for the GCP MCP org-level
integration. Each Sentry org gets at most one SA, stored in this model
so it can be reused across setup attempts and prevent orphaned SAs from
accumulating as a result of abandoned integration flows.

This PR is the model-creation migration only; the model will be used in
the follow-up PR — #120266.


https://app.notion.com/p/sentry/GCP-MCP-Org-Level-Integration-39f8b10e4b5d8030ba01cd62373641df
Christinarlong pushed a commit that referenced this pull request Jul 24, 2026
…g per-org service accounts (#120499)

PR 3/4 for
[CW-1691](https://linear.app/getsentry/issue/CW-1691/set-up-sentry-connectors-gcp-project-per-customer-sa-creation-and)

Adds a new `GcpServiceAccount` model to track GCP service accounts
created in the `sentry-connectors` project for the GCP MCP org-level
integration. Each Sentry org gets at most one SA, stored in this model
so it can be reused across setup attempts and prevent orphaned SAs from
accumulating as a result of abandoned integration flows.

This PR is the model-creation migration only; the model will be used in
the follow-up PR — #120266.


https://app.notion.com/p/sentry/GCP-MCP-Org-Level-Integration-39f8b10e4b5d8030ba01cd62373641df
…count-generation-and-deletion-gcp-integration
Comment on lines +30 to +33
GcpServiceAccount.objects.create(
organization_id=org_id,
service_account_email=sa_email,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Race condition in GCP service account creation causes IntegrityError

GcpServiceAccount.objects.create() is vulnerable to a race condition: concurrent pipeline requests for the same org will crash with IntegrityError due to unique=True on organization_id, and may leave orphaned GCP service accounts.

Evidence
  • GcpServiceAccount.organization_id has unique=True in the model definition.
  • generate_sentry_sa checks filter(...).first() for an existing record, then calls the external GCP IAM API to create a service account, then calls .create().
  • The gap between the filter check and the .create() is not atomic, so concurrent pipeline requests for the same organization can both pass the existence check.
  • The second .create() raises IntegrityError, and because IntegrityError is not caught by the existing except IntegrationError / except RequestException blocks, it propagates uncaught.
  • The GCP service account created by the losing request becomes orphaned since it has no corresponding database record.

Identified by Warden · sentry-backend-bugs · WGJ-SRT

generate_sentry_sa,
validate_gcp_project_id,
)
from sentry.integrations.gcp.client import delete_sentry_sa, generate_sentry_sa

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete_sentry_sa removes DB record even when GCP delete fails

When the GCP IAM API returns a non-404 error, delete_sentry_sa logs the failure but still deletes the local GcpServiceAccount record, leaking the service account in GCP because Sentry no longer tracks it.

Evidence
  • delete_sentry_sa in client.py calls session.delete(url) against the GCP IAM API.
  • For 404 responses it logs a warning; for any other non-ok response it logs an error.
  • After the if/elif block, execution falls through and unconditionally calls GcpServiceAccount.objects.filter(organization_id=org_id).delete().
  • If GCP returns 500, 429, or 403, the SA still exists in GCP but Sentry's record is removed.
  • On re-installation generate_sentry_sa finds no existing record and creates a new SA, leaving the old one orphaned in GCP.

Identified by Warden · sentry-backend-bugs · ELX-43G

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant