fix(iam): close authorization gaps in core controllers - #278
Merged
Merged
Conversation
- Organization settings: any member could update the company, including owner_uuid (take ownership) and billing/lifecycle fields, and change the organization 2FA policy. Updates and the 2FA policy now require the owner, the Administrator role or a system admin; owner, Stripe ids, plan, status, trial and type are ignored for non-admin updates (ownership keeps its transfer endpoint). - System-wide 2FA policy save is restricted to system admins. - Admin platform metrics are restricted to system admins; IAM and developer metrics require iam list user / developers list api-key. - Reports resolved to the "fleetbase" service, so no permission ever matched and every report endpoint was open. ReportController now uses the iam service, and direct query execution/export/download require iam execute/export report. - API credentials, webhooks, API events and request logs resolved to resource names (api-credential, webhook-endpoint, ...) that no permission uses, leaving them unguarded. Controllers can now declare $permissionResource, used by Auth when resolving permissions; these map to the Developers schema resources (api-key, webhook, event, log). - Auth::cannotUnlessAdmin() for explicit checks outside AuthorizationGuard.
This was referenced Sep 27, 2026
Merged
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
An authorization audit found several core endpoints that skip permission checks or resolve to permission names that don't exist, so
AuthorizationGuardlet every user through.PUT companies/{id})owner_uuid(verified locally: a dispatcher made themselves owner), Stripe ids, plan and statusAdministratorrole or a system admin.owner_uuid, Stripe ids,plan,status,trial_ends_atandtypeare ignored for non-admin updates; ownership still moves through the transfer endpointAdministratorrole or system adminPOST two-fa/config)iam list user/developers list api-keyReportControllerresolved to thefleetbaseservice, so no permission matched and every report endpoint was openiamservice. Direct query execution requiresiam execute report; export and download requireiam export reportapi-credential,webhook-endpoint, … which no permission uses, so they were unguarded (any user could list and create API keys)$permissionResource(api-key,webhook,event,log), matching the Developers schema and the dev consoleHow
HasApiControllerBehavior::getPermissionResourceName()andAuth::getPermissionResourceFromController()let a controller name the schema resource its permissions use. They default to the model's singular name, so nothing else changes.Auth::cannotUnlessAdmin()supports explicit checks outside the guard.->only(), so behaviour through the router changes and existing unit tests that call methods directly still exercise the endpoint logic.Behaviour changes to note
iam … reportpermissions to use reports. The Fleet-Ops reports screens now check the same names ((fix(permissions): enforce Fleet-Ops permissions across the API and console fleetops#345)).Test plan
cannotUnlessAdmin; organization-manager middleware (member refused; owner, Administrator role and system admin allowed);owner_uuid/statusignored on update; 2FA and report middleware registration and refusal.tests/Unit: 1831 passed. One failure,UtilsTest › utils reads composer package keywords, also fails onmainlocally.PUT companies/{id}; a dispatcher gets 401 onGET api-credentials.