QueryProxy
Documentation menu

Slack integration

Approve and reject query requests from Slack with interactive buttons, verified end-to-end with HMAC-SHA256 signatures.

Updated:

With the Slack integration, new query requests are announced in a channel with Approve / Reject buttons, and decisions flow back into QueryProxy — with the same rules as the web (role checks, no self-approval), cryptographically verified.

Setup

  1. Create a Slack app for your workspace at api.slack.com/apps.

  2. Enable Incoming Webhooks and add a webhook for your approvals channel (e.g. #db-approvals).

  3. Enable Interactivity and set the request URL to:

    https://your-queryproxy-host/webhooks/slack/interactions
  4. In QueryProxy, open ChatOps (as DBA) and paste the webhook URL and the app’s signing secret. Both are stored encrypted.

  5. In Admin → Users, fill each reviewer’s Slack member ID (e.g. U0123ABC — visible in a Slack profile under Copy member ID). This maps Slack clicks to QueryProxy users.

What it looks like

When a request is submitted, QueryProxy posts a message with the requester, the connection, a SQL preview and three actions: Approve, Reject and Open in QueryProxy. After a decision the message is updated in place — buttons disappear and the outcome is shown, so a request can’t be decided twice from a stale message.

Rejections from Slack record the generic reason “Rejected via Slack by <name>”. For a written justification, reject from the web UI.

Security

Every callback from Slack is verified before anything happens:

  • Signature — the X-Slack-Signature header must match v0=HMAC_SHA256("v0:{timestamp}:{raw_body}", signing_secret), compared in constant time.
  • Replay protection — requests older than ±5 minutes (per X-Slack-Request-Timestamp) are rejected.
  • Identity — the clicking Slack user must be mapped to a QueryProxy user with the DBA role in the request’s team. Unmapped or unauthorized users get a private error message and nothing changes.
  • Rules — self-approval is blocked in Slack exactly as on the web.

A forged or stale callback returns 401 and changes no state. The webhook endpoint is also rate-limited.

Arrow keys to move, Enter to open.