Replaced legacy tenant and environment bindings in the BaselineDriftEngine with the new ProviderResourceIdentity framework as defined in Spec 382. This ensures cross-environment compatibility and deterministic baseline matching. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #453
222 lines
8.7 KiB
PHP
222 lines
8.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Jobs\CompareBaselineToTenantJob;
|
|
use App\Models\BaselineProfile;
|
|
use App\Models\BaselineSnapshot;
|
|
use App\Models\BaselineSnapshotItem;
|
|
use App\Models\Finding;
|
|
use App\Models\InventoryItem;
|
|
use App\Models\ProviderResourceBinding;
|
|
use App\Services\Baselines\BaselineSnapshotIdentity;
|
|
use App\Services\Intune\AuditLogger;
|
|
use App\Services\OperationRunService;
|
|
use App\Support\Baselines\BaselineSubjectKey;
|
|
use App\Support\Baselines\SubjectClass;
|
|
use App\Support\OperationRunOutcome;
|
|
use App\Support\OperationRunType;
|
|
use App\Support\Resources\ProviderResourceResolutionMode;
|
|
use App\Support\Resources\ResourceIdentity;
|
|
|
|
it('consumes active provider resource bindings before canonical identity matching during baseline compare', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
$identity = ResourceIdentity::providerResource('fake-provider', 'policy', 'bound-policy-2');
|
|
$displayName = 'Duplicate Provider Policy';
|
|
$canonicalSubjectKey = spec382CompareSubjectKey($identity);
|
|
$currentMeta = spec382CompareMeta($identity, $displayName, 'etag-bound-policy-2');
|
|
|
|
[$profile, $snapshot] = spec382CompareProfileAndSnapshot($tenant);
|
|
|
|
ProviderResourceBinding::factory()
|
|
->providerResource($identity)
|
|
->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'canonical_subject_key' => $canonicalSubjectKey,
|
|
'display_label' => $displayName,
|
|
'resolution_mode' => ProviderResourceResolutionMode::ManualBinding->value,
|
|
]);
|
|
|
|
BaselineSnapshotItem::factory()->create([
|
|
'baseline_snapshot_id' => (int) $snapshot->getKey(),
|
|
'subject_type' => 'policy',
|
|
'subject_external_id' => BaselineSubjectKey::workspaceSafeSubjectExternalId('deviceConfiguration', $canonicalSubjectKey),
|
|
'subject_key' => $canonicalSubjectKey,
|
|
'policy_type' => 'deviceConfiguration',
|
|
'baseline_hash' => app(BaselineSnapshotIdentity::class)->hashItemContent('deviceConfiguration', 'bound-policy-2', $currentMeta),
|
|
'meta_jsonb' => $currentMeta,
|
|
]);
|
|
|
|
$inventorySyncRun = createInventorySyncOperationRunWithCoverage(
|
|
tenant: $tenant,
|
|
statusByType: ['deviceConfiguration' => 'succeeded'],
|
|
);
|
|
|
|
spec382CompareInventoryItem(
|
|
tenant: $tenant,
|
|
identity: ResourceIdentity::providerResource('fake-provider', 'policy', 'bound-policy-1'),
|
|
externalId: 'bound-policy-1',
|
|
displayName: $displayName,
|
|
etag: 'etag-bound-policy-1',
|
|
inventorySyncRunId: (int) $inventorySyncRun->getKey(),
|
|
);
|
|
spec382CompareInventoryItem(
|
|
tenant: $tenant,
|
|
identity: $identity,
|
|
externalId: 'bound-policy-2',
|
|
displayName: $displayName,
|
|
etag: 'etag-bound-policy-2',
|
|
inventorySyncRunId: (int) $inventorySyncRun->getKey(),
|
|
);
|
|
|
|
$run = spec382RunCompare($tenant, $user, $profile, $snapshot);
|
|
|
|
$run->refresh();
|
|
$context = is_array($run->context) ? $run->context : [];
|
|
|
|
expect($run->outcome)->toBe(OperationRunOutcome::Succeeded->value)
|
|
->and(data_get($context, 'baseline_compare.matching.active_bindings_considered'))->toBe(1)
|
|
->and(data_get($context, 'baseline_compare.matching.by_reason.active_provider_resource_binding'))->toBe(1)
|
|
->and(data_get($context, 'baseline_compare.evidence_gaps.by_reason.ambiguous_match'))->toBeNull()
|
|
->and(data_get($context, 'baseline_compare.evidence_gaps.by_reason.identity_required'))->toBeNull()
|
|
->and(Finding::query()
|
|
->where('managed_environment_id', (int) $tenant->getKey())
|
|
->where('source', 'baseline.compare')
|
|
->where('subject_external_id', 'bound-policy-2')
|
|
->exists())->toBeFalse();
|
|
});
|
|
|
|
it('turns old subject-key and display-only baseline subjects into identity-required gaps', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
$displayName = 'Display Only Match Policy';
|
|
[$profile, $snapshot] = spec382CompareProfileAndSnapshot($tenant);
|
|
|
|
$meta = [
|
|
'display_name' => $displayName,
|
|
'etag' => 'display-only-etag',
|
|
];
|
|
|
|
BaselineSnapshotItem::factory()->create([
|
|
'baseline_snapshot_id' => (int) $snapshot->getKey(),
|
|
'subject_type' => 'policy',
|
|
'subject_external_id' => BaselineSubjectKey::workspaceSafeSubjectExternalId('deviceConfiguration', 'old-display-subject-key'),
|
|
'subject_key' => 'old-display-subject-key',
|
|
'policy_type' => 'deviceConfiguration',
|
|
'baseline_hash' => app(BaselineSnapshotIdentity::class)->hashItemContent('deviceConfiguration', 'display-only-policy', $meta),
|
|
'meta_jsonb' => $meta,
|
|
]);
|
|
|
|
$inventorySyncRun = createInventorySyncOperationRunWithCoverage(
|
|
tenant: $tenant,
|
|
statusByType: ['deviceConfiguration' => 'succeeded'],
|
|
);
|
|
|
|
InventoryItem::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'external_id' => 'display-only-policy',
|
|
'policy_type' => 'deviceConfiguration',
|
|
'display_name' => $displayName,
|
|
'meta_jsonb' => $meta,
|
|
'last_seen_operation_run_id' => (int) $inventorySyncRun->getKey(),
|
|
'last_seen_at' => now(),
|
|
]);
|
|
|
|
$run = spec382RunCompare($tenant, $user, $profile, $snapshot);
|
|
|
|
$run->refresh();
|
|
$context = is_array($run->context) ? $run->context : [];
|
|
|
|
expect($run->outcome)->toBe(OperationRunOutcome::PartiallySucceeded->value)
|
|
->and(data_get($context, 'baseline_compare.matching.by_reason.identity_required'))->toBe(1)
|
|
->and(data_get($context, 'baseline_compare.evidence_gaps.by_reason.identity_required'))->toBe(1)
|
|
->and(data_get($context, 'baseline_compare.matching.by_reason.canonical_subject_key'))->toBeNull();
|
|
});
|
|
|
|
function spec382CompareProfileAndSnapshot($tenant): array
|
|
{
|
|
$profile = BaselineProfile::factory()->active()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'scope_jsonb' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []],
|
|
]);
|
|
$snapshot = BaselineSnapshot::factory()->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
'captured_at' => now()->subMinute(),
|
|
]);
|
|
$profile->update(['active_snapshot_id' => (int) $snapshot->getKey()]);
|
|
|
|
return [$profile, $snapshot];
|
|
}
|
|
|
|
function spec382CompareSubjectKey(ResourceIdentity $identity): string
|
|
{
|
|
$subjectKey = BaselineSubjectKey::forProviderResourceIdentity(
|
|
subjectDomain: 'baseline',
|
|
subjectClass: SubjectClass::PolicyBacked,
|
|
subjectTypeKey: 'deviceConfiguration',
|
|
identity: $identity,
|
|
);
|
|
|
|
expect($subjectKey)->not->toBeNull();
|
|
|
|
return (string) $subjectKey;
|
|
}
|
|
|
|
function spec382CompareMeta(ResourceIdentity $identity, string $displayName, string $etag): array
|
|
{
|
|
return [
|
|
'display_name' => $displayName,
|
|
'provider_key' => $identity->providerKey,
|
|
'provider_resource_identity' => $identity->toArray(),
|
|
'provider_resource_fingerprint' => $identity->fingerprint(),
|
|
'odata_type' => 'fake.policy',
|
|
'etag' => $etag,
|
|
];
|
|
}
|
|
|
|
function spec382CompareInventoryItem(
|
|
$tenant,
|
|
ResourceIdentity $identity,
|
|
string $externalId,
|
|
string $displayName,
|
|
string $etag,
|
|
int $inventorySyncRunId,
|
|
): InventoryItem {
|
|
return InventoryItem::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'external_id' => $externalId,
|
|
'policy_type' => 'deviceConfiguration',
|
|
'display_name' => $displayName,
|
|
'meta_jsonb' => spec382CompareMeta($identity, $displayName, $etag),
|
|
'last_seen_operation_run_id' => $inventorySyncRunId,
|
|
'last_seen_at' => now(),
|
|
]);
|
|
}
|
|
|
|
function spec382RunCompare($tenant, $user, BaselineProfile $profile, BaselineSnapshot $snapshot)
|
|
{
|
|
$operationRunService = app(OperationRunService::class);
|
|
$run = $operationRunService->ensureRunWithIdentity(
|
|
tenant: $tenant,
|
|
type: OperationRunType::BaselineCompare->value,
|
|
identityInputs: ['baseline_profile_id' => (int) $profile->getKey()],
|
|
context: [
|
|
'baseline_profile_id' => (int) $profile->getKey(),
|
|
'baseline_snapshot_id' => (int) $snapshot->getKey(),
|
|
'effective_scope' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []],
|
|
],
|
|
initiator: $user,
|
|
);
|
|
|
|
(new CompareBaselineToTenantJob($run))->handle(
|
|
app(BaselineSnapshotIdentity::class),
|
|
app(AuditLogger::class),
|
|
$operationRunService,
|
|
);
|
|
|
|
return $run;
|
|
}
|