feat: #7 S6a — device-group scope enforcement on device + device-group handlers#339
feat: #7 S6a — device-group scope enforcement on device + device-group handlers#339PaulDotterer wants to merge 2 commits into
Conversation
…up handlers (#7 S6a) First slice of #7's enforcement-consuming half — the scope primitives from S2b now have real call sites. - storeScopeResolver: the concrete auth.ScopeResolver over the device-group / user-group membership projections (auth stays store-independent). - EnforceDeviceGroupScope: authorizes group-keyed handlers by a FIRST-CLASS match of the group id against the caller's scope groups (a scoped admin may act on the groups in their scope) — no membership lookup needed. - Per-item device handlers (GetDevice, DeleteDevice, SetDeviceSyncInterval) call EnforceDeviceScope. They compose with the existing :self/:assigned tier via the ownerScope == nil gate: device-group scope applies ONLY to the unrestricted base-permission holder; :assigned self-service users stay owner-filtered, untouched. Checked before the read, so an out-of-scope id is denied, not leaked via NotFound-vs-PermissionDenied. - All six group-keyed device-group handlers (GetDeviceGroup, Rename, UpdateDescription, Delete, SetSyncInterval, SetMaintenanceWindow) call EnforceDeviceGroupScope. An unscoped admin is globally scoped (DeviceScopeFilterFor.Global), so every existing call path is unchanged. Tests: EnforceDeviceGroupScope units (global / first-class match / cross-kind / no-grant); handler integration for in-scope allow, out-of-scope deny, no-existence-oracle, unscoped-sees-all, across the per-item and group-keyed handlers. Full Device suite green. Follow-ups (#7): S6b — dispatch / executions / compliance / osquery / logs / terminal (some derive the device id from the row or session token); S6c — list narrowing (ListDevices, ListDeviceGroups, ListExecutions, ListActiveTerminalSessions). Refs #7.
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR implements device-group scope enforcement for device and device-group API handlers. New authorization logic enforces scope restrictions, a store-backed resolver provides membership data, and handlers apply these checks before performing operations. Comprehensive tests verify scoped and unscoped access patterns. CI timeouts are extended to accommodate the test suite. ChangesDevice-Group Scope Enforcement
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Closing — wrong consumer for V1. Per the authoritative call (2026-06-10), V1 server scope enforcement targets the StartTerminal / TerminalAdmin path ONLY, not generic device / device-group handlers. The enforcement primitives (S2b) and authoring (S5) stand; this slice enforced on the wrong handlers (GetDevice/DeleteDevice/device-group management). Rebuilding S6 against StartTerminal + the TerminalAdmin per-scope reconciler. The broad-curated-table enforcement is deferred to V2 (if ever). |
First slice of #7's enforcement-consuming half — the scope primitives from S2b (#335) now have real call sites on the device and device-group handlers. Purely additive: an unscoped admin is globally scoped, so every existing call path is unchanged.
Builds on the design decisions settled for S6:
RenameDeviceGroupscoped to group X may act on X directly (no member enumeration).:assignedcomposition — device-group scope applies ONLY to the unrestricted base-permission tier;:assignedself-service users stay owner-filtered, untouched.What's wired
storeScopeResolver— the concreteauth.ScopeResolverover the device-group / user-group membership projections (DeviceGroupRepo.ListForDevice/UserGroupRepo.ListForUser). Theauthpackage stays store-independent.EnforceDeviceGroupScope(new auth helper) — first-class group-id match for group-keyed handlers; no resolver/membership lookup needed.GetDevice,DeleteDevice,SetDeviceSyncIntervalcallEnforceDeviceScope, gated onuserFilterID(...) == nil(the unrestricted tier). Checked before the read so an out-of-scope id is denied, not leaked viaNotFound-vs-PermissionDenied.GetDeviceGroup,RenameDeviceGroup,UpdateDeviceGroupDescription,DeleteDeviceGroup,SetDeviceGroupSyncInterval,SetDeviceGroupMaintenanceWindowcallEnforceDeviceGroupScope.CI guard
Separate commit bumps the Integration Tests
-timeout20m→30m (interim, #338) so S6a's added tests don't tip the job over while the durable container-reuse fix is pending.Tests
EnforceDeviceGroupScopeunits: global / first-class match / cross-kind / no-grant / unauthenticated.go vet ./...,gofmt, full Device suite green. Local CodeRabbit: no findings.Follow-ups (#7)
ListDevices,ListDeviceGroups,ListExecutions,ListActiveTerminalSessions).Closes part of #7.
Summary by CodeRabbit
Release Notes
New Features
Tests