Skip to content

feat(seer-infra-telemetry): PAT modal builder + submission handler for monitoring providers#118607

Draft
shashjar wants to merge 2 commits into
masterfrom
shashjar/pat-modal-builder-and-submission-handler-for-monitoring-providers
Draft

feat(seer-infra-telemetry): PAT modal builder + submission handler for monitoring providers#118607
shashjar wants to merge 2 commits into
masterfrom
shashjar/pat-modal-builder-and-submission-handler-for-monitoring-providers

Conversation

@shashjar

Copy link
Copy Markdown
Member

Resolves CW-1549.

Adds a Slack modal for PAT-based monitoring provider connection (org selector, site dropdown, token input) opened from button click. The view_submission handler validates the token via the provider's API, creates the necessary identity-linked objects via the link_provider_identity() helper, clears any prior decline, and sends an ephemeral success message.

The new Slack actions are: CONNECT_MONITORING_PROVIDER, SKIP_MONITORING_PROVIDER, and DECLINE_MONITORING_PROVIDER. SKIP_MONITORING_PROVIDER skips the provider connection prompt for the rest of this run/thread, while DECLINE_MONITORING_PROVIDER prevents showing the provider connection prompt to the same user (based on Slack identity) permanently.

All monitoring provider functionality is gated behind the organizations:seer-infra-telemetry feature flag.

https://claude.ai/code/artifact/f54a82fa-73ca-49ef-a331-6f57cf26508d

@linear-code

linear-code Bot commented Jun 26, 2026

Copy link
Copy Markdown

CW-1549

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Jun 26, 2026
@shashjar

Copy link
Copy Markdown
Member Author

bugbot run

MONITORING_PROVIDERS: dict[str, dict[str, Any]] = {
"datadog": {"name": "Datadog"},
"datadog_pat": {"name": "Datadog (Personal Access Token)"},
"datadog_pat": {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Lmk what y'all think about this structure for storing provider-specific configuration for Slack flows. Alternatively we could just add some branching in the Slack message builder to handle providers separately (for the blocks that are different)

Comment thread src/sentry/integrations/slack/webhooks/monitoring_provider.py
Comment thread src/sentry/integrations/slack/webhooks/monitoring_provider.py Outdated
Comment thread src/sentry/integrations/slack/webhooks/monitoring_provider.py
"datadog_pat": {"name": "Datadog (Personal Access Token)"},
"datadog_pat": {
"name": "Datadog (Personal Access Token)",
"pat_hint": "Create one at Organization Settings → Access → API Keys in Datadog.",

@shashjar shashjar Jun 26, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We'll eventually want more instruction/detail than this (and probably displayed in a more readable/understandable way). e.g. we'll want to indicate which scopes/expiration to set for the token (all read scopes, max of 1 year). I'm thinking this is okay for now for testing.

@shashjar

Copy link
Copy Markdown
Member Author

bugbot run

@cursor cursor Bot left a comment

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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d46e6f8. Configure here.

build_data["site"] = site

try:
identity_data = provider_type.build_identity(build_data)

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.

OAuth provider submission uncaught error

High Severity

handle_monitoring_provider_submission calls build_identity for any key in MONITORING_PROVIDERS without rejecting OAuth providers, unlike open_monitoring_provider_modal. A crafted modal submission with provider_key datadog passes validation but triggers an uncaught KeyError inside OAuth build_identity, returning 500 instead of a modal error.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d46e6f8. Configure here.

@@ -756,6 +762,24 @@ def post(self, request: Request) -> Response:
if action_option in NOTIFICATION_SETTINGS_ACTION_OPTIONS:

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.

User-submitted PAT logged to application logs via slack.action.request

The monitoring-provider modal submits a third-party personal access token in view.state.values.token_block.token_input.value, which is part of slack_request.data. The post() handler logs the entire slack_request.data at INFO level (slack.action.request) before dispatching the new view_submission handler, so every PAT submission is written to application logs in cleartext. Redact the token field before logging.

Evidence
  • post() in action.py logs extra={... 'request_data': slack_request.data} at INFO unconditionally (line ~719) before any action dispatch.
  • The new view_submission intercept for MONITORING_PROVIDER_CALLBACK_ID runs after this log, so the payload is already logged.
  • monitoring_provider.py:246 reads the PAT from state_values.token_block.token_input.value, the same value present in the logged slack_request.data.
  • No redaction or field exclusion is applied to request_data, exposing users' third-party tokens to anyone with log access.

Identified by Warden security-review · L2P-KS2

Comment on lines +324 to +327
slack_client.chat_postEphemeral(
channel=channel_id,
user=user_id,
text=f"Connected {provider_name}. Seer can now query {provider_name} data in this org.",

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.

SlackApiError from chat_postEphemeral propagates after successful identity link

If chat_postEphemeral raises SlackApiError (e.g. channel_not_found, user_not_in_channel), the exception propagates out of handle_monitoring_provider_submission after link_provider_identity has already committed — the user sees a modal error but is permanently linked, so any retry hits "This account is already connected". Wrap the call in a try/except SlackApiError and log the failure instead.

Evidence
  • SlackSdkClient.wrapper in sdk_client.py re-raises SlackApiError after logging, so all SDK calls including chat_postEphemeral can raise.
  • workspace.py line 158 wraps the identical chat_postEphemeral call in try/except SlackApiError, confirming it is a known failure mode.
  • link_provider_identity at line 271 succeeds and commits the DB change before _send_success_ephemeral is called at line 286.
  • _send_success_ephemeral has no exception handling; SlackApiError propagates all the way out of handle_monitoring_provider_submission.
  • A subsequent retry by the user then hits the IntegrityError guard at line 280 and returns "This account is already connected".

Identified by Warden sentry-backend-bugs · ZBR-37R

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