fix: classify ESP separately from enrollment restrictions

This commit is contained in:
Ahmed Darrazi 2026-01-01 23:46:13 +01:00
parent 70f8622171
commit fd3a71d698
3 changed files with 175 additions and 10 deletions

View File

@ -0,0 +1,104 @@
<?php
namespace App\Console\Commands;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\Tenant;
use Illuminate\Console\Command;
class ReclassifyEnrollmentConfigurations extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'intune:reclassify-enrollment-configurations {--tenant=} {--write : Write changes (default is dry-run)}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Reclassify enrollment configuration items (e.g. ESP) that were synced under the wrong policy type.';
/**
* Execute the console command.
*/
public function handle(): int
{
$tenant = $this->resolveTenantOrNull();
$dryRun = ! (bool) $this->option('write');
$query = PolicyVersion::query()
->with('policy')
->where('policy_type', 'enrollmentRestriction');
if ($tenant) {
$query->where('tenant_id', $tenant->id);
}
$candidates = $query->get();
$changedVersions = 0;
$changedPolicies = 0;
foreach ($candidates as $version) {
$snapshot = is_array($version->snapshot) ? $version->snapshot : [];
$odataType = $snapshot['@odata.type'] ?? null;
$configurationType = $snapshot['deviceEnrollmentConfigurationType'] ?? null;
$isEsp = (is_string($odataType) && strcasecmp($odataType, '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration') === 0)
|| (is_string($configurationType) && $configurationType === 'windows10EnrollmentCompletionPageConfiguration');
if (! $isEsp) {
continue;
}
$this->line(sprintf(
'ESP detected: policy_version=%s policy=%s tenant_id=%s',
(string) $version->getKey(),
$version->policy_id ? (string) $version->policy_id : 'n/a',
(string) $version->tenant_id,
));
if ($dryRun) {
continue;
}
$version->forceFill([
'policy_type' => 'windowsEnrollmentStatusPage',
'platform' => $version->platform ?: 'all',
])->save();
$changedVersions++;
if ($version->policy instanceof Policy && $version->policy->policy_type === 'enrollmentRestriction') {
$version->policy->forceFill([
'policy_type' => 'windowsEnrollmentStatusPage',
])->save();
$changedPolicies++;
}
}
$this->info('Done.');
$this->info('PolicyVersions changed: '.$changedVersions);
$this->info('Policies changed: '.$changedPolicies);
$this->info('Mode: '.($dryRun ? 'dry-run' : 'write'));
return Command::SUCCESS;
}
private function resolveTenantOrNull(): ?Tenant
{
$tenantOption = $this->option('tenant');
if (! $tenantOption) {
return null;
}
return Tenant::query()
->forTenant($tenantOption)
->firstOrFail();
}
}

View File

@ -124,16 +124,6 @@
'restore' => 'enabled', 'restore' => 'enabled',
'risk' => 'medium', 'risk' => 'medium',
], ],
[
'type' => 'enrollmentRestriction',
'label' => 'Enrollment Restrictions',
'category' => 'Enrollment',
'platform' => 'all',
'endpoint' => 'deviceManagement/deviceEnrollmentConfigurations',
'backup' => 'full',
'restore' => 'preview-only',
'risk' => 'high',
],
[ [
'type' => 'windowsAutopilotDeploymentProfile', 'type' => 'windowsAutopilotDeploymentProfile',
'label' => 'Windows Autopilot Profiles', 'label' => 'Windows Autopilot Profiles',
@ -155,6 +145,16 @@
'restore' => 'enabled', 'restore' => 'enabled',
'risk' => 'medium', 'risk' => 'medium',
], ],
[
'type' => 'enrollmentRestriction',
'label' => 'Enrollment Restrictions',
'category' => 'Enrollment',
'platform' => 'all',
'endpoint' => 'deviceManagement/deviceEnrollmentConfigurations',
'backup' => 'full',
'restore' => 'preview-only',
'risk' => 'high',
],
[ [
'type' => 'endpointSecurityIntent', 'type' => 'endpointSecurityIntent',
'label' => 'Endpoint Security Intents', 'label' => 'Endpoint Security Intents',

View File

@ -0,0 +1,61 @@
<?php
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\Tenant;
use Carbon\CarbonImmutable;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('reclassify command moves ESP versions out of enrollmentRestriction', function () {
$tenant = Tenant::create([
'tenant_id' => 'tenant-reclassify',
'name' => 'Tenant Reclassify',
'metadata' => [],
'is_current' => true,
]);
$tenant->makeCurrent();
$policy = Policy::create([
'tenant_id' => $tenant->id,
'external_id' => 'esp-1',
'policy_type' => 'enrollmentRestriction',
'display_name' => 'ESP Misclassified',
'platform' => 'all',
]);
$version = PolicyVersion::create([
'tenant_id' => $tenant->id,
'policy_id' => $policy->id,
'version_number' => 1,
'policy_type' => 'enrollmentRestriction',
'platform' => 'all',
'created_by' => 'tester@example.com',
'captured_at' => CarbonImmutable::now(),
'snapshot' => [
'@odata.type' => '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration',
'deviceEnrollmentConfigurationType' => 'windows10EnrollmentCompletionPageConfiguration',
'displayName' => 'ESP Misclassified',
],
]);
$this->artisan('intune:reclassify-enrollment-configurations', ['--tenant' => $tenant->tenant_id])
->assertSuccessful();
$version->refresh();
$policy->refresh();
expect($version->policy_type)->toBe('enrollmentRestriction');
expect($policy->policy_type)->toBe('enrollmentRestriction');
$this->artisan('intune:reclassify-enrollment-configurations', ['--tenant' => $tenant->tenant_id, '--write' => true])
->assertSuccessful();
$version->refresh();
$policy->refresh();
expect($version->policy_type)->toBe('windowsEnrollmentStatusPage');
expect($policy->policy_type)->toBe('windowsEnrollmentStatusPage');
});