Slack integration
Approve and reject query requests from Slack with interactive buttons, verified end-to-end with HMAC-SHA256 signatures and single-use action tokens.
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
-
Create a Slack app for your workspace at api.slack.com/apps.
-
Enable Incoming Webhooks and add a webhook for your approvals channel (e.g.
#db-approvals). -
Enable Interactivity and set the request URL to:
https://your-queryproxy-host/webhooks/slack/interactions -
In QueryProxy, open ChatOps. A DBA sets the webhook URL and the enabled flag; the app’s signing secret can only be entered by a system administrator. Both are stored encrypted. An integration cannot be saved without a secret, so the first save is an administrator’s. The webhook URL must be
https://and its host must be on the allowlist (hooks.slack.com,*.webhook.office.comand*.logic.azure.comby default; the list is shared across chat providers; extend it withQUERYPROXY_CHAT_WEBHOOK_ALLOWED_HOSTS). -
As a system administrator, open Teams & Users → Manage users and 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.
Breaking change — the signing secret is administrator-only. From this version a DBA can no longer enter or rotate it, and rotating an existing secret requires proving the current one. The reason is what an HMAC can and cannot say: it proves the caller knows the secret, never that a particular person approved. Anyone who could choose the secret could sign a callback approving their own request in a colleague’s name — and the audit trail would record the colleague. If a DBA configured ChatOps on an existing install, they already know the current value: rotate it once, as an administrator, after upgrading.
Removing an integration is administrator-only for the same reason: putting it back needs a signing secret, which only an administrator can set, so a delete would be a one-way door out of ChatOps for the whole team. The DBA’s day-to-day control is the Enabled flag — untick it and save to switch the integration off, with everything else kept.
What it looks like
When a request is submitted, QueryProxy posts a message with the requester,
the connection, a SQL preview (cut at 400 characters; turn it off with
QUERYPROXY_CHAT_INCLUDE_SQL=false) 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.
Breaking change — buttons in messages posted before this version no longer work. They carry no action token, so their callbacks are refused. Decide those requests in the web UI; every message posted from this version onwards behaves as described below.
Security
Every callback from Slack is verified before anything happens:
- Signature — the
X-Slack-Signatureheader must matchv0=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. - Single-use action token — each Approve / Reject button carries a token bound to that one request, valid for 24 hours and spent on the first decision. So a callback can only answer a message QueryProxy actually posted, and only once: knowing the signing secret is no longer enough to forge a decision or replay a captured one. The token is burned only once the decision is actually recorded, so a click turned away by authorization does not use it up.
- Identity — the clicking Slack user must be mapped to a QueryProxy user who belongs to the integration’s team and holds the DBA role there — or is a system admin. Unmapped or unauthorized users get a private error message and nothing changes.
- Rules — self-approval is blocked in Slack exactly as on the web. As on the web, an admin may override the DBA-role rule and the self-approval block, and an admin’s approval that does so is flagged in the audit log.
A forged or stale callback returns 401 and changes no state. The webhook
endpoint is also rate-limited.