<#1014 Fix node-scoped alert creation, and make th...
# osctrl
g
#1014 Fix node-scoped alert creation, and make the resulting rule visible Pull request opened by javuto Fix node-scoped alert creation, and make the resulting rule visible Problem Creating an alert from a node's detail page failed with
POST /api/v1/alerts/rules 500 (Internal Server Error)
and no usable message. Root cause:
ValidateRule
required
node_uuid
to parse as an RFC-4122 UUID. A node's UUID is osquery's
host_identifier
uppercased (
cmd/tls/handlers/post.go
), so it is a hostname, instance id, or vendor serial under every
--host_identifier
except
uuid
— legitimate nodes were rejected outright. The resulting error then fell through
respondAlertsErr
to the
default:
branch, so operator input came back as a 500 whose body was just
"error"
, logged only at debug level.
pkg/alerts/node_scope_test.go
already exercised matching with
WATCH-U9
-style scopes, so validation contradicted the matcher in the same package. Changes
pkg/alerts/validate.go
•
node_uuid
is now bounded to its column width (
MaxNodeUUIDLen = 64
) instead of being parsed as a UUID. • New
ErrInvalidRule
sentinel wraps every
ValidateRule
failure, so callers can tell bad input from a server fault.
cmd/api/handlers/alerts.go
•
respondAlertsErr
answers 400 with the actual reason for
ErrInvalidRule
. • Genuine 500s log at error level (previously debug-only, i.e. invisible in a normally-configured deployment).
frontend/src/features/alerts/AlertsPage.tsx
• The env filter's default option was labeled "Global (all environments)" but sent
?env=0
, which the server filters as
environment_id = 0
. A rule created from a node lives in that node's environment, so it was invisible in the default view. Added an
ALL_ENVS
sentinel that omits the
env
param entirely (server returns every environment) and made it the default; the two meanings are now distinct options: All environments / Global rules only / per-env. Applies to channels too. • Column titles on the rules and channels tables via one sticky
TableHeader
, matching the
<th>
style used on the other admin pages. Each table's grid template is now a shared const, so header and rows cannot drift out of alignment.
frontend/src/features/nodes/NodeAlertModal.tsx
• Invalidate
['alert-rules']
on create, not only on apply, so the new rule shows up even if the operator chooses "Apply later". Tests •
TestAlertRuleCreateNodeScoped
— hostname-style node scope → 201, scope round-trips. •
TestAlertRuleCreateInvalidIs400
— blank name → 400 containing "rule name is required". •
TestValidateRuleNodeUUID
— rewritten: accepts uuid/hostname/instance-id/empty scopes, rejects over-column-width, asserts failures wrap
ErrInvalidRule
. • Frontend: env filter sends no filter by default,
{env: 5}
/
{env: 0}
when chosen; both tables' column titles asserted.
go test ./pkg/alerts/ ./cmd/api/handlers/
and 228 frontend tests pass;
tsc --noEmit
clean. Deploy note Requires an
osctrl-api
restart to pick up the validation change. jmpsec/osctrl