Added a resolver/validation flow that fetches endpoint security template definitions and enforces them before CREATE/PATCH so we don’t call Graph with invalid settings. Hardened restore endpoint resolution (built-in fallback to deviceManagement/configurationPolicies, clearer error metadata, preview-only fallback when metadata is missing) and exposed Graph path/method in restore UI details. Stripped read-only fields when PATCHing endpointSecurityIntent so the request no longer fails with “properties not patchable”. Added regression tests covering endpoint security restore, intent sanitization, unknown type safety, Graph error metadata, and endpoint resolution behavior. Testing GraphClientEndpointResolutionTest.php ./vendor/bin/pint --dirty Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local> Reviewed-on: #25
101 lines
3.4 KiB
PHP
101 lines
3.4 KiB
PHP
<?php
|
|
|
|
use App\Services\Graph\GraphContractRegistry;
|
|
use App\Services\Graph\GraphLogger;
|
|
use App\Services\Graph\MicrosoftGraphClient;
|
|
use Illuminate\Http\Client\Request;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Tests\TestCase;
|
|
|
|
uses(TestCase::class);
|
|
|
|
beforeEach(function () {
|
|
config()->set('graph.base_url', 'https://graph.microsoft.com');
|
|
config()->set('graph.version', 'beta');
|
|
config()->set('graph.tenant_id', 'tenant');
|
|
config()->set('graph.client_id', 'client');
|
|
config()->set('graph.client_secret', 'secret');
|
|
config()->set('graph.scope', 'https://graph.microsoft.com/.default');
|
|
|
|
// Ensure we don't accidentally resolve via supported_policy_types
|
|
config()->set('tenantpilot.supported_policy_types', []);
|
|
});
|
|
|
|
it('uses graph contract resource path for applyPolicy', function () {
|
|
config()->set('graph_contracts.types.mamAppConfiguration', [
|
|
'resource' => 'deviceAppManagement/targetedManagedAppConfigurations',
|
|
'allowed_select' => ['id', 'displayName'],
|
|
'allowed_expand' => [],
|
|
'type_family' => ['#microsoft.graph.targetedManagedAppConfiguration'],
|
|
'create_method' => 'POST',
|
|
'update_method' => 'PATCH',
|
|
'id_field' => 'id',
|
|
'hydration' => 'properties',
|
|
]);
|
|
|
|
Http::fake([
|
|
'https://login.microsoftonline.com/*' => Http::response([
|
|
'access_token' => 'fake-token',
|
|
'expires_in' => 3600,
|
|
], 200),
|
|
'https://graph.microsoft.com/*' => Http::response(['id' => 'A_1'], 200),
|
|
]);
|
|
|
|
$client = new MicrosoftGraphClient(
|
|
logger: app(GraphLogger::class),
|
|
contracts: app(GraphContractRegistry::class),
|
|
);
|
|
|
|
$client->applyPolicy(
|
|
policyType: 'mamAppConfiguration',
|
|
policyId: 'A_1',
|
|
payload: ['displayName' => 'Test'],
|
|
options: ['tenant' => 'tenant', 'client_id' => 'client', 'client_secret' => 'secret'],
|
|
);
|
|
|
|
Http::assertSent(function (Request $request) {
|
|
if (! str_contains($request->url(), 'graph.microsoft.com')) {
|
|
return false;
|
|
}
|
|
|
|
return str_contains($request->url(), '/beta/deviceAppManagement/targetedManagedAppConfigurations/A_1');
|
|
});
|
|
});
|
|
|
|
it('uses built-in endpoint mapping for endpoint security policies when config is missing', function () {
|
|
config()->set('graph_contracts.types.endpointSecurityPolicy', []);
|
|
config()->set('tenantpilot.foundation_types', []);
|
|
|
|
Http::fake([
|
|
'https://login.microsoftonline.com/*' => Http::response([
|
|
'access_token' => 'fake-token',
|
|
'expires_in' => 3600,
|
|
], 200),
|
|
'https://graph.microsoft.com/*' => Http::response(['id' => 'E_1'], 200),
|
|
]);
|
|
|
|
$client = new MicrosoftGraphClient(
|
|
logger: app(GraphLogger::class),
|
|
contracts: app(GraphContractRegistry::class),
|
|
);
|
|
|
|
$client->applyPolicy(
|
|
policyType: 'endpointSecurityPolicy',
|
|
policyId: 'E_1',
|
|
payload: ['name' => 'Test'],
|
|
options: ['tenant' => 'tenant', 'client_id' => 'client', 'client_secret' => 'secret'],
|
|
);
|
|
|
|
Http::assertSent(function (Request $request) {
|
|
if (! str_contains($request->url(), 'graph.microsoft.com')) {
|
|
return false;
|
|
}
|
|
|
|
if (! str_contains($request->url(), '/beta/deviceManagement/configurationPolicies/E_1')) {
|
|
return false;
|
|
}
|
|
|
|
return ! str_contains($request->url(), '/beta/deviceManagement/endpointSecurityPolicy/E_1');
|
|
});
|
|
});
|