Implements RBAC-based write gating for Intune restore flows, UI affordances, and audit logging; adds tests and specs.
3.4 KiB
3.4 KiB
Research — Provider Access Hardening v1 (Intune Write Gate)
Repository Reality Check (existing implementation surfaces)
Write start surfaces
- Restore execution start (wizard submit / create path):
App\Filament\Resources\RestoreRunResource::createRestoreRun()- Creates a queued
RestoreRunand a correspondingOperationRunof typerestore.execute. - Dispatches
App\Jobs\ExecuteRestoreRunJobwith theOperationRuninstance.
- Creates a queued
- Restore rerun path (action path inside
RestoreRunResource): also enqueuesrestore.executeand dispatchesExecuteRestoreRunJob.
Job execution layer (defense-in-depth insertion points)
App\Jobs\ExecuteRestoreRunJob::handle()- Calls
RestoreService::executeForRun(...)(this is the Graph-mutation path).
- Calls
App\Jobs\RestoreAssignmentsJob::handle()- Calls
AssignmentRestoreService::restore(...)(Graph-mutation path for assignments).
- Calls
Tenant view RBAC UX surfaces
- Tenant view page:
App\Filament\Resources\TenantResource::infolist()currently renders a full "RBAC" section with many raw fields. - Tenant view header actions:
App\Filament\Resources\TenantResource\Pages\ViewTenant::getHeaderActions()includesTenantResource::rbacAction(). - RBAC setup surface already exists:
App\Filament\Resources\TenantResource::rbacAction()creates the "Setup Intune RBAC" action (no new wizard page required).
Existing gating and observability primitives
- Operation dedupe + provider connection blocking:
App\Services\Providers\ProviderOperationStartGate(existing pattern for start surfaces). - Long-running work visibility:
OperationRunis the canonical monitoring primitive. - Audit logging:
App\Models\AuditLogexists andTenantalready relates to it.
Decisions (resolved clarifications)
Gate evaluation during health check
- Decision: Gate evaluates persisted Tenant state only; an in-progress health check has no special effect.
- Rationale: Keeps the gate DB-only and deterministic; avoids introducing locks/sentinels.
- Alternatives considered:
- Block all writes while health check is running (safer but adds operational friction and requires tracking “running” state).
"Setup Intune RBAC" CTA destination
- Decision: CTA deep-links to the existing Tenant view RBAC section / surfaces (no new wizard page in this feature).
- Rationale: Minimizes scope and leverages
TenantResource::rbacAction()which already exists. - Alternatives considered:
- Build a dedicated setup wizard page for RBAC (adds navigation, testing, and more UX requirements).
Audit logging for blocked attempts
- Decision: Use existing
AuditLogmodel for UI-level blocked write attempts (P3), in addition to OperationRun failures. - Rationale: Meets compliance intent without introducing new schema.
- Alternatives considered:
- Create a new audit log table (unnecessary; model already exists).
Config toggle behavior
- Decision:
tenantpilot.hardening.intune_write_gate.enabled=falsecauses writes to proceed, but logs a warning per evaluation that the gate is bypassed. - Rationale: Rollback safety without silent loss of protection.
- Alternatives considered:
- Silent bypass (bad observability).
- Startup-only warning (can be missed; per-evaluation warning is explicit).
Key constraints reaffirmed
- No synchronous Graph calls in the gate.
- Start surface must block before job enqueue.
- Job-level must block before any Graph mutation call.
- Reason codes are stable and sanitized.