- Created docs/PERMISSIONS.md with complete permission requirements - Added logging for 403 errors in ScopeTagResolver - Updated README with link to permissions documentation Issue: Scope tags show 'Unknown (ID: 0)' due to missing permission Required: DeviceManagementRBAC.Read.All with admin consent User must: 1. Go to Azure Portal → App Registration 2. Add DeviceManagementRBAC.Read.All permission 3. Grant admin consent 4. Wait 5-10 min for propagation 5. Clear cache: php artisan cache:clear
155 lines
5.8 KiB
Markdown
155 lines
5.8 KiB
Markdown
# Microsoft Graph API Permissions
|
|
|
|
This document lists all required Microsoft Graph API permissions for TenantPilot to function correctly.
|
|
|
|
## Required Permissions
|
|
|
|
The Azure AD / Entra ID **App Registration** used by TenantPilot requires the following **Application Permissions** (not Delegated):
|
|
|
|
### Core Policy Management (Required)
|
|
- `DeviceManagementConfiguration.Read.All` - Read Intune device configuration policies
|
|
- `DeviceManagementConfiguration.ReadWrite.All` - Write/restore Intune policies
|
|
- `DeviceManagementApps.Read.All` - Read app configuration policies
|
|
- `DeviceManagementApps.ReadWrite.All` - Write app policies
|
|
|
|
### Scope Tags (Feature 004 - Required for Phase 3)
|
|
- **`DeviceManagementRBAC.Read.All`** - Read scope tags and RBAC settings
|
|
- **Purpose**: Resolve scope tag IDs to display names (e.g., "0" → "Default")
|
|
- **Missing**: Backup items will show "Unknown (ID: 0)" instead of scope tag names
|
|
- **Impact**: Metadata display only - backups still work without this permission
|
|
|
|
### Group Resolution (Feature 004 - Required for Phase 2)
|
|
- `Group.Read.All` - Resolve group IDs to names for assignments
|
|
- `Directory.Read.All` - Batch resolve directory objects (groups, users, devices)
|
|
|
|
## How to Add Permissions
|
|
|
|
### Azure Portal (Entra ID)
|
|
|
|
1. Go to **Azure Portal** → **Entra ID** (Azure Active Directory)
|
|
2. Navigate to **App registrations** → Select your TenantPilot app
|
|
3. Click **API permissions** in the left menu
|
|
4. Click **+ Add a permission**
|
|
5. Select **Microsoft Graph** → **Application permissions**
|
|
6. Search for and select the required permissions:
|
|
- `DeviceManagementRBAC.Read.All`
|
|
- (Add others as needed)
|
|
7. Click **Add permissions**
|
|
8. **IMPORTANT**: Click **Grant admin consent for [Your Organization]**
|
|
- ⚠️ Without admin consent, the permissions won't be active!
|
|
|
|
### PowerShell (Alternative)
|
|
|
|
```powershell
|
|
# Connect to Microsoft Graph
|
|
Connect-MgGraph -Scopes "Application.ReadWrite.All"
|
|
|
|
# Get your app registration
|
|
$appId = "YOUR-APP-CLIENT-ID"
|
|
$app = Get-MgApplication -Filter "appId eq '$appId'"
|
|
|
|
# Add DeviceManagementRBAC.Read.All permission
|
|
$graphServicePrincipal = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
|
|
$rbacPermission = $graphServicePrincipal.AppRoles | Where-Object {$_.Value -eq "DeviceManagementRBAC.Read.All"}
|
|
|
|
$requiredResourceAccess = @{
|
|
ResourceAppId = "00000003-0000-0000-c000-000000000000"
|
|
ResourceAccess = @(
|
|
@{
|
|
Id = $rbacPermission.Id
|
|
Type = "Role"
|
|
}
|
|
)
|
|
}
|
|
|
|
Update-MgApplication -ApplicationId $app.Id -RequiredResourceAccess $requiredResourceAccess
|
|
|
|
# Grant admin consent
|
|
# (Must be done manually or via Graph API with RoleManagement.ReadWrite.Directory scope)
|
|
```
|
|
|
|
## Verification
|
|
|
|
After adding permissions and granting admin consent:
|
|
|
|
1. Go to **App registrations** → Your app → **API permissions**
|
|
2. Verify status shows **Granted for [Your Organization]** with a green checkmark ✅
|
|
3. Clear cache in TenantPilot:
|
|
```bash
|
|
php artisan cache:clear
|
|
```
|
|
4. Test scope tag resolution:
|
|
```bash
|
|
php artisan tinker
|
|
>>> use App\Services\Graph\ScopeTagResolver;
|
|
>>> use App\Models\Tenant;
|
|
>>> $tenant = Tenant::first();
|
|
>>> $resolver = app(ScopeTagResolver::class);
|
|
>>> $tags = $resolver->resolve(['0'], $tenant);
|
|
>>> dd($tags);
|
|
```
|
|
Expected output:
|
|
```php
|
|
[
|
|
[
|
|
"id" => "0",
|
|
"displayName" => "Default"
|
|
]
|
|
]
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Error: "Application is not authorized to perform this operation"
|
|
|
|
**Symptoms:**
|
|
- Backup items show "Unknown (ID: 0)" for scope tags
|
|
- Logs contain: `Application must have one of the following scopes: DeviceManagementRBAC.Read.All`
|
|
|
|
**Solution:**
|
|
1. Add `DeviceManagementRBAC.Read.All` permission (see above)
|
|
2. **Grant admin consent** (critical step!)
|
|
3. Wait 5-10 minutes for Azure to propagate permissions
|
|
4. Clear cache: `php artisan cache:clear`
|
|
5. Test again
|
|
|
|
### Error: "Insufficient privileges to complete the operation"
|
|
|
|
**Cause:** The user account used to grant admin consent doesn't have sufficient permissions.
|
|
|
|
**Solution:**
|
|
- Use an account with **Global Administrator** or **Privileged Role Administrator** role
|
|
- Or have the IT admin grant consent for the organization
|
|
|
|
### Permissions showing but still getting 403
|
|
|
|
**Possible causes:**
|
|
1. Admin consent not granted (click the button!)
|
|
2. Permissions not yet propagated (wait 5-10 minutes)
|
|
3. Wrong tenant (check tenant ID in app config)
|
|
4. Cached token needs refresh (clear cache + restart)
|
|
|
|
## Feature Impact Matrix
|
|
|
|
| Feature | Required Permissions | Without Permission | Impact Level |
|
|
|---------|---------------------|-------------------|--------------|
|
|
| Basic Policy Backup | `DeviceManagementConfiguration.Read.All` | Cannot backup | 🔴 Critical |
|
|
| Policy Restore | `DeviceManagementConfiguration.ReadWrite.All` | Cannot restore | 🔴 Critical |
|
|
| Scope Tag Names (004) | `DeviceManagementRBAC.Read.All` | Shows "Unknown (ID: X)" | 🟡 Medium |
|
|
| Assignment Names (004) | `Group.Read.All` + `Directory.Read.All` | Shows group IDs only | 🟡 Medium |
|
|
| Group Mapping (004) | `Group.Read.All` | Manual ID mapping required | 🟡 Medium |
|
|
|
|
## Security Notes
|
|
|
|
- All permissions are **Application Permissions** (app-level, not user-level)
|
|
- Requires **admin consent** from Global Administrator
|
|
- Use **least privilege principle**: Only add permissions for features you use
|
|
- Consider creating separate app registrations for different environments (dev/staging/prod)
|
|
- Rotate client secrets regularly (recommended: every 6 months)
|
|
|
|
## References
|
|
|
|
- [Microsoft Graph API Permissions](https://learn.microsoft.com/en-us/graph/permissions-reference)
|
|
- [Intune Graph API Overview](https://learn.microsoft.com/en-us/graph/api/resources/intune-graph-overview)
|
|
- [App Registration Best Practices](https://learn.microsoft.com/en-us/azure/active-directory/develop/security-best-practices-for-app-registration)
|