<#1192 Santa: user approval requests from blocked ...
# osctrl
g
#1192 Santa: user approval requests from blocked executions Pull request opened by javuto Santa: user approval requests from blocked executions Closes #1168 Problem When Santa blocks a binary, the user has no way to ask for it. They see the block dialog and have to reach an admin out of band, and the admin has to find the matching event by hand. Change • Setting: a new per-environment Approval request URL (
approval_url
) in Santa Settings and
PUT /api/v1/santa/{env}/config
. It must be an https URL without userinfo, query, fragment or
%
. Empty means the feature is off, which is the default. • Block dialog link: when the URL is set, preflight sends
event_detail_url
and
event_detail_text
. The URL is
{approval_url}/santa/request/{env uuid}?sha256=%file_sha%&machine_id=%machine_id%
, and Santa fills in the placeholders. • Request page: a standalone page at
/santa/request/$env
, outside the app shell. It shows the file hash and machine from the link, takes a justification, and lists the caller's own requests with their status. A signed-out user is sent to login and returned to the request afterwards, SSO included. • Storage: a new
santa_requests
table (
AutoMigrate
) with statuses
pending
,
approved
,
denied
and
expired
. A request copies the file name, path, signing ID, team ID and executing user from the blocked event. • Routes (all behind
handlerAuthCheck
, registered only when Santa is enabled): •
POST /api/v1/santa/{env}/requests
creates a request. Any signed-in account. •
GET /api/v1/santa/{env}/requests/mine
lists the caller's requests. Any signed-in account. •
GET /api/v1/santa/{env}/requests?status=
lists all requests. Environment admins. • Expiry: the existing daily prune loop marks pending requests older than 30 days as
expired
. • Docs and strings: a new "Approval requests" section in
pkg/santa/README.md
, regenerated OpenAPI, and UI strings in all 20 locales. Identity model A requester is an ordinary osctrl account with no permissions, created at first SSO login when the provider has JIT provisioning on, or by hand. There is no new role. The two requester routes check authentication only, not environment permission. Security and operational impact • Off by default. With no approval URL, preflight is unchanged and the request routes answer 404. • A stored block is required. A request is accepted only when osctrl holds a
BLOCK*
event for that hash on that machine in that environment, so a requester cannot create rows for arbitrary files. • One 404 for every refusal. Unknown environment, approval turned off and no matching block all return the same 404. It still tells a signed-in account whether a given file was blocked on a given machine. • Limits. Justification is 1 to 1000 characters. A pending request for the same file and machine is returned instead of a second one. One account can hold 20 pending requests per environment (429 beyond that). • What a requester reads back. Hash, machine ID, status and date. The justification is returned only to the account that wrote it. • Login return. The redirect after login stores only the environment, hash and machine ID in
sessionStorage
, never a URL. • Audit. Creating a request writes an audit log entry with the hash and machine. • Requester is not bound to the machine. osctrl does not check that the person signing in is the user of the Mac in the link. • Requester accounts are still accounts. A permissionless account can open the rest of the UI and see what any such account sees today (empty environment list, own profile, osquery table schema). "No other osctrl data" holds for the request routes and page, not for the account as a whole. • Duplicate race. Two simultaneous submissions for the same file and machine can both insert a pending row (check-then-insert, marked with a
ponytail:
comment). • Schema. One new table and one new column on the Santa environment config, both added by
AutoMigrate
at startup. Not included • Approving or denying a request, automatic rule creation and the admin queue in the UI (#1169). Nothing sets
approved
or
denied
yet. • Notifications (#1170), voting (#1171) and temporary MONITOR mode (#1172). • A dedicated requester role that locks an account to the request page. Validation •
go test ./pkg/santa/... ./cmd/api/... ./cmd/tls/... ./pkg/mcp/... ./pkg/apiclient/... ./cmd/cli/... -count=1
•
go vet
and
gofmt -l cmd pkg
•
make openapi
and
make openapi-check
•
npm --prefix frontend run check
•
npm --prefix frontend test
(84 files, 799 tests) •
golangci-lint run ./...
reports two
errcheck
issues in
cmd/tls/handlers/carves.go
, which this change does not touch. New tests cover approval URL validation, the preflight link, request creation, merging and the pending cap, the API refusals and config round trip, the request page, and the login-return storage. Not verified • A real Santa client: the placeholder names
%file_sha%
and
%machine_id%
and the dialog button were not exercised. • A live SSO login round trip back to the request page. • Playwright was not run, although this adds a route and a post-login redirect. • PostgreSQL and MySQL; the tests use SQLite. • The 19 non-English translations are machine-written and unreviewed. jmpsec/osctrl