canonicalControlResolutionForFinding($finding); $evidence = is_array($finding->evidence_jsonb) ? $finding->evidence_jsonb : []; $targetIdentifier = $this->firstString([ $finding->subject_external_id, Arr::get($evidence, 'policy_id'), Arr::get($evidence, 'policy_external_id'), Arr::get($evidence, 'external_id'), Arr::get($evidence, 'id'), ]); return new ArtifactSourceDescriptor( workspaceId: (int) $finding->workspace_id, tenantId: (int) $finding->managed_environment_id, managedEnvironmentId: (int) $finding->managed_environment_id, sourceFamily: ArtifactSourceTaxonomy::SOURCE_FAMILY_FINDING, sourceKind: ArtifactSourceTaxonomy::SOURCE_KIND_MODEL_SUMMARY, providerKey: $this->providerKey($evidence), providerConnectionId: $this->providerConnectionId($finding->tenant, $evidence), sourceTargetKind: $targetIdentifier !== null ? ArtifactSourceTaxonomy::SOURCE_TARGET_GOVERNED_SUBJECT : ArtifactSourceTaxonomy::SOURCE_TARGET_MANAGED_ENVIRONMENT, sourceTargetIdentifier: $targetIdentifier ?? (string) $finding->managed_environment_id, detectorKey: $this->findingDetectorKey($finding), controlKey: $this->controlKeyFromResolution($controlResolution), ); } public function providerDetailForFinding(Finding $finding): ArtifactProviderDetail { $evidence = is_array($finding->evidence_jsonb) ? $finding->evidence_jsonb : []; $policyType = $this->firstString([ Arr::get($evidence, 'policy_type'), Arr::get($evidence, 'provider_object_type'), ]); $typeDescriptor = InventoryPolicyTypeMeta::typeDescriptorFor($policyType, $evidence); return new ArtifactProviderDetail( legacyFindingType: $this->nullableString($finding->finding_type), legacyPolicyType: $policyType, providerObjectType: $typeDescriptor['provider_object_type'] ?? $policyType ?? $this->nullableString($finding->finding_type), providerDisplayType: $typeDescriptor['provider_display_type'] ?? Str::headline((string) $finding->finding_type), detectorDetail: $this->findingDetectorKey($finding), ); } public function forStoredReport(StoredReport $report): ArtifactSourceDescriptor { $payload = is_array($report->payload) ? $report->payload : []; $detectorKey = $this->storedReportDetectorKey((string) $report->report_type); return new ArtifactSourceDescriptor( workspaceId: (int) $report->workspace_id, tenantId: (int) $report->managed_environment_id, managedEnvironmentId: (int) $report->managed_environment_id, sourceFamily: ArtifactSourceTaxonomy::SOURCE_FAMILY_STORED_REPORT, sourceKind: ArtifactSourceTaxonomy::SOURCE_KIND_STORED_REPORT, providerKey: $this->providerKey($payload), providerConnectionId: $this->providerConnectionId($report->tenant, $payload), sourceTargetKind: ArtifactSourceTaxonomy::SOURCE_TARGET_MANAGED_ENVIRONMENT, sourceTargetIdentifier: (string) $report->managed_environment_id, detectorKey: $detectorKey, controlKey: $this->controlKeyForReport((string) $report->report_type), ); } public function providerDetailForStoredReport(StoredReport $report): ArtifactProviderDetail { return new ArtifactProviderDetail( legacyReportType: $this->nullableString($report->report_type), providerObjectType: $this->nullableString($report->report_type), providerDisplayType: Str::headline(str_replace('.', '_', (string) $report->report_type)), detectorDetail: $this->storedReportDetectorKey((string) $report->report_type), ); } public function forInventoryItem(InventoryItem $item): ArtifactSourceDescriptor { $metadata = is_array($item->meta_jsonb) ? $item->meta_jsonb : []; $typeDescriptor = InventoryPolicyTypeMeta::typeDescriptorFor($this->nullableString($item->policy_type), $metadata); $detectorKey = 'inventory.'.($typeDescriptor['provider_object_type'] ?? $item->policy_type ?? 'unknown'); return new ArtifactSourceDescriptor( workspaceId: (int) $item->workspace_id, tenantId: (int) $item->managed_environment_id, managedEnvironmentId: (int) $item->managed_environment_id, sourceFamily: ArtifactSourceTaxonomy::SOURCE_FAMILY_INVENTORY, sourceKind: ArtifactSourceTaxonomy::SOURCE_KIND_INVENTORY_PROJECTION, providerKey: $this->providerKey($metadata), providerConnectionId: $this->providerConnectionId($item->tenant, $metadata), sourceTargetKind: ArtifactSourceTaxonomy::SOURCE_TARGET_GOVERNED_SUBJECT, sourceTargetIdentifier: $this->firstString([$item->external_id, $item->getKey() !== null ? (string) $item->getKey() : null]), detectorKey: $detectorKey, controlKey: $this->controlKeyForInventoryPolicyType($this->nullableString($item->policy_type)), ); } public function providerDetailForInventoryItem(InventoryItem $item): ArtifactProviderDetail { $metadata = is_array($item->meta_jsonb) ? $item->meta_jsonb : []; $typeDescriptor = InventoryPolicyTypeMeta::typeDescriptorFor($this->nullableString($item->policy_type), $metadata); return new ArtifactProviderDetail( legacyPolicyType: $typeDescriptor['legacy_policy_type'] ?? null, providerObjectType: $typeDescriptor['provider_object_type'] ?? null, providerDisplayType: $typeDescriptor['provider_display_type'] ?? null, detectorDetail: 'inventory.'.($typeDescriptor['provider_object_type'] ?? 'unknown'), ); } public function forEvidenceSnapshotItem(EvidenceSnapshotItem $item): ArtifactSourceDescriptor { $payload = is_array($item->summary_payload) ? $item->summary_payload : []; $descriptor = $payload['source_descriptor'] ?? null; if (is_array($descriptor)) { return ArtifactSourceDescriptor::fromArray($descriptor); } $tenant = $item->tenant; return $this->forEvidenceProviderPayload( $tenant instanceof ManagedEnvironment ? $tenant : null, [ 'dimension_key' => $item->dimension_key, 'source_kind' => $item->source_kind, 'source_record_type' => $item->source_record_type, 'source_record_id' => $item->source_record_id, 'summary_payload' => $payload, ], workspaceId: (int) $item->workspace_id, managedEnvironmentId: (int) $item->managed_environment_id, ); } /** * @param array $item */ public function forEvidenceProviderPayload(?ManagedEnvironment $tenant, array $item, ?int $workspaceId = null, ?int $managedEnvironmentId = null): ArtifactSourceDescriptor { $sourceKind = $this->sourceKind($item['source_kind'] ?? null); $dimensionKey = $this->nullableString($item['dimension_key'] ?? null); $sourceRecordType = $this->nullableString($item['source_record_type'] ?? null); $sourceRecordId = $this->nullableString($item['source_record_id'] ?? null); $summaryPayload = is_array($item['summary_payload'] ?? null) ? $item['summary_payload'] : []; $sourceTargetKind = $this->sourceTargetKindForEvidenceItem($sourceKind, $sourceRecordType); $workspaceId ??= (int) $tenant?->workspace_id; $managedEnvironmentId ??= (int) $tenant?->getKey(); return new ArtifactSourceDescriptor( workspaceId: $workspaceId, tenantId: $managedEnvironmentId, managedEnvironmentId: $managedEnvironmentId, sourceFamily: $this->sourceFamilyForEvidenceItem($sourceKind, $sourceRecordType, $dimensionKey), sourceKind: $sourceKind, providerKey: $this->providerKey($summaryPayload), providerConnectionId: $this->providerConnectionId($tenant, $summaryPayload), sourceTargetKind: $sourceTargetKind, sourceTargetIdentifier: $this->sourceTargetIdentifier($sourceTargetKind, $sourceRecordId, $managedEnvironmentId), detectorKey: $dimensionKey, controlKey: $this->controlKeyForEvidenceDimension($dimensionKey, $summaryPayload), ); } /** * @param array $item */ public function providerDetailForEvidenceProviderPayload(array $item): ArtifactProviderDetail { $sourceKind = $this->sourceKind($item['source_kind'] ?? null); $dimensionKey = $this->nullableString($item['dimension_key'] ?? null); $sourceRecordType = $this->nullableString($item['source_record_type'] ?? null); $sourceRecordId = $this->nullableString($item['source_record_id'] ?? null); if (($sourceKind === ArtifactSourceTaxonomy::SOURCE_KIND_STORED_REPORT || $sourceRecordType === StoredReport::class) && is_numeric($sourceRecordId)) { $report = StoredReport::query()->find((int) $sourceRecordId); if ($report instanceof StoredReport) { return $this->providerDetailForStoredReport($report); } } return match ($this->sourceFamilyForEvidenceItem($sourceKind, $sourceRecordType, $dimensionKey)) { ArtifactSourceTaxonomy::SOURCE_FAMILY_FINDING => new ArtifactProviderDetail( legacyFindingType: $dimensionKey, providerObjectType: $sourceRecordType, providerDisplayType: 'Findings summary', detectorDetail: $dimensionKey, ), ArtifactSourceTaxonomy::SOURCE_FAMILY_OPERATION_RUN => new ArtifactProviderDetail( providerObjectType: OperationRun::class, providerDisplayType: 'Operation run', detectorDetail: $dimensionKey, ), ArtifactSourceTaxonomy::SOURCE_FAMILY_INVENTORY => new ArtifactProviderDetail( providerObjectType: InventoryItem::class, providerDisplayType: 'Inventory projection', detectorDetail: $dimensionKey, ), default => new ArtifactProviderDetail( providerObjectType: $sourceRecordType, providerDisplayType: $dimensionKey !== null ? Str::headline($dimensionKey) : null, detectorDetail: $dimensionKey, ), }; } public function canonicalControlResolutionForFinding(Finding $finding): array { return $this->canonicalControlResolver ->resolve($this->resolutionRequestForFinding($finding)) ->toArray(); } public function resolutionRequestForFinding(Finding $finding): CanonicalControlResolutionRequest { $evidence = is_array($finding->evidence_jsonb) ? $finding->evidence_jsonb : []; $findingType = (string) $finding->finding_type; if ($findingType === Finding::FINDING_TYPE_PERMISSION_POSTURE) { return new CanonicalControlResolutionRequest( provider: $this->providerKey($evidence), consumerContext: 'evidence', subjectFamilyKey: 'permission_posture', workload: 'entra', signalKey: 'permission_posture.required_graph_permission', ); } if ($findingType === Finding::FINDING_TYPE_ENTRA_ADMIN_ROLES) { $roleTemplateId = (string) ($evidence['role_template_id'] ?? ''); return new CanonicalControlResolutionRequest( provider: $this->providerKey($evidence), consumerContext: 'evidence', subjectFamilyKey: 'entra_admin_roles', workload: 'entra', signalKey: $roleTemplateId === '62e90394-69f5-4237-9190-012177145e10' ? 'entra_admin_roles.global_admin_assignment' : 'entra_admin_roles.privileged_role_assignment', ); } if ($findingType === Finding::FINDING_TYPE_DRIFT) { $policyType = $this->firstString([ $evidence['policy_type'] ?? null, 'drift', ]) ?? 'drift'; return new CanonicalControlResolutionRequest( provider: $this->providerKey($evidence), consumerContext: 'evidence', subjectFamilyKey: $policyType, workload: 'intune', signalKey: match ($policyType) { 'deviceCompliancePolicy' => 'intune.device_compliance_policy', 'drift' => 'finding.drift', default => 'intune.device_configuration_drift', }, ); } return new CanonicalControlResolutionRequest( provider: $this->providerKey($evidence), consumerContext: 'evidence', subjectFamilyKey: $findingType, ); } /** * @param array $resolution */ private function controlKeyFromResolution(array $resolution): ?string { return $this->nullableString(Arr::get($resolution, 'control.control_key')); } private function findingDetectorKey(Finding $finding): ?string { $evidence = is_array($finding->evidence_jsonb) ? $finding->evidence_jsonb : []; $findingType = (string) $finding->finding_type; if ($findingType === Finding::FINDING_TYPE_PERMISSION_POSTURE) { return 'permission_posture.required_graph_permission'; } if ($findingType === Finding::FINDING_TYPE_ENTRA_ADMIN_ROLES) { $roleTemplateId = (string) ($evidence['role_template_id'] ?? ''); return $roleTemplateId === '62e90394-69f5-4237-9190-012177145e10' ? 'entra_admin_roles.global_admin_assignment' : 'entra_admin_roles.privileged_role_assignment'; } if ($findingType === Finding::FINDING_TYPE_DRIFT) { $policyType = $this->nullableString($evidence['policy_type'] ?? null) ?? 'drift'; return match ($policyType) { 'deviceCompliancePolicy' => 'intune.device_compliance_policy', 'drift' => 'finding.drift', default => 'intune.device_configuration_drift', }; } return $findingType !== '' ? $findingType : null; } private function storedReportDetectorKey(string $reportType): ?string { return match ($reportType) { StoredReport::REPORT_TYPE_PERMISSION_POSTURE => 'permission_posture.required_graph_permission', StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES => 'entra_admin_roles.privileged_role_assignment', default => $this->nullableString($reportType), }; } private function controlKeyForReport(string $reportType): ?string { $request = match ($reportType) { StoredReport::REPORT_TYPE_PERMISSION_POSTURE => new CanonicalControlResolutionRequest( provider: 'microsoft', consumerContext: 'report', subjectFamilyKey: 'permission_posture', workload: 'entra', signalKey: 'permission_posture.required_graph_permission', ), StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES => new CanonicalControlResolutionRequest( provider: 'microsoft', consumerContext: 'report', subjectFamilyKey: 'entra_admin_roles', workload: 'entra', signalKey: 'entra_admin_roles.privileged_role_assignment', ), default => new CanonicalControlResolutionRequest( provider: 'microsoft', consumerContext: 'report', subjectFamilyKey: $reportType, ), }; return $this->controlKeyFromResolution($this->canonicalControlResolver->resolve($request)->toArray()); } private function controlKeyForInventoryPolicyType(?string $policyType): ?string { if ($policyType === null) { return null; } $request = new CanonicalControlResolutionRequest( provider: 'microsoft', consumerContext: 'evidence', subjectFamilyKey: $policyType, workload: str_contains($policyType, 'conditionalAccess') ? 'entra' : 'intune', signalKey: match ($policyType) { 'deviceCompliancePolicy' => 'intune.device_compliance_policy', 'conditionalAccessPolicy' => 'conditional_access.policy_state', default => 'intune.device_configuration_drift', }, ); return $this->controlKeyFromResolution($this->canonicalControlResolver->resolve($request)->toArray()); } /** * @param array $summaryPayload */ private function controlKeyForEvidenceDimension(?string $dimensionKey, array $summaryPayload): ?string { $direct = $this->nullableString(Arr::get($summaryPayload, 'source_descriptor.control_key')) ?? $this->nullableString(Arr::get($summaryPayload, 'control_key')); if ($direct !== null) { return $direct; } $control = collect(Arr::wrap($summaryPayload['canonical_controls'] ?? [])) ->first(static fn (mixed $item): bool => is_array($item) && filled($item['control_key'] ?? null)); if (is_array($control)) { return $this->nullableString($control['control_key'] ?? null); } return match ($dimensionKey) { 'permission_posture' => $this->controlKeyForReport(StoredReport::REPORT_TYPE_PERMISSION_POSTURE), 'entra_admin_roles' => $this->controlKeyForReport(StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES), default => null, }; } private function sourceKind(mixed $value): string { if (is_string($value) && ArtifactSourceTaxonomy::isSourceKind($value)) { return $value; } return ArtifactSourceTaxonomy::SOURCE_KIND_MODEL_SUMMARY; } private function sourceFamilyForEvidenceItem(string $sourceKind, ?string $sourceRecordType, ?string $dimensionKey): string { if ($sourceKind === ArtifactSourceTaxonomy::SOURCE_KIND_STORED_REPORT || $sourceRecordType === StoredReport::class || $sourceRecordType === 'stored_report') { return ArtifactSourceTaxonomy::SOURCE_FAMILY_STORED_REPORT; } if ($sourceKind === ArtifactSourceTaxonomy::SOURCE_KIND_OPERATION_ROLLUP || $sourceRecordType === OperationRun::class || $sourceRecordType === 'operation_run') { return ArtifactSourceTaxonomy::SOURCE_FAMILY_OPERATION_RUN; } if ($sourceKind === ArtifactSourceTaxonomy::SOURCE_KIND_INVENTORY_PROJECTION || $sourceRecordType === InventoryItem::class || $sourceRecordType === 'inventory_item') { return ArtifactSourceTaxonomy::SOURCE_FAMILY_INVENTORY; } if ($sourceRecordType === Finding::class || $sourceRecordType === 'finding' || in_array($dimensionKey, ['findings_summary', 'baseline_drift_posture'], true)) { return ArtifactSourceTaxonomy::SOURCE_FAMILY_FINDING; } return ArtifactSourceTaxonomy::SOURCE_FAMILY_EVIDENCE_SNAPSHOT; } private function sourceTargetKindForEvidenceItem(string $sourceKind, ?string $sourceRecordType): string { if ($sourceKind === ArtifactSourceTaxonomy::SOURCE_KIND_OPERATION_ROLLUP || $sourceRecordType === OperationRun::class || $sourceRecordType === 'operation_run') { return ArtifactSourceTaxonomy::SOURCE_TARGET_OPERATION_RUN; } if ($sourceRecordType === ProviderConnection::class || $sourceRecordType === 'provider_connection') { return ArtifactSourceTaxonomy::SOURCE_TARGET_PROVIDER_CONNECTION; } return ArtifactSourceTaxonomy::SOURCE_TARGET_MANAGED_ENVIRONMENT; } private function sourceTargetIdentifier(string $sourceTargetKind, ?string $sourceRecordId, int $managedEnvironmentId): ?string { return match ($sourceTargetKind) { ArtifactSourceTaxonomy::SOURCE_TARGET_OPERATION_RUN, ArtifactSourceTaxonomy::SOURCE_TARGET_PROVIDER_CONNECTION, ArtifactSourceTaxonomy::SOURCE_TARGET_GOVERNED_SUBJECT => $sourceRecordId, default => (string) $managedEnvironmentId, }; } /** * @param array $payload */ private function providerKey(array $payload): string { return $this->firstString([ Arr::get($payload, 'source_descriptor.provider_key'), Arr::get($payload, 'provider_key'), Arr::get($payload, 'provider'), ]) ?? 'microsoft'; } /** * @param array $payload */ private function providerConnectionId(?ManagedEnvironment $tenant, array $payload): ?int { $value = Arr::get($payload, 'source_descriptor.provider_connection_id') ?? Arr::get($payload, 'provider_connection_id') ?? Arr::get($payload, 'providerConnectionId') ?? Arr::get($payload, 'provider_connection.id'); if (is_numeric($value)) { return (int) $value; } if (! $tenant instanceof ManagedEnvironment || ! $tenant->exists) { return null; } $connectionId = $tenant->providerConnections() ->where('provider', $this->providerKey($payload)) ->where('is_default', true) ->value('id'); return is_numeric($connectionId) ? (int) $connectionId : null; } /** * @param list $values */ private function firstString(array $values): ?string { foreach ($values as $value) { $string = $this->nullableString($value); if ($string !== null) { return $string; } } return null; } private function nullableString(mixed $value): ?string { if ($value instanceof Model && $value->getKey() !== null) { return (string) $value->getKey(); } if (! is_scalar($value)) { return null; } $value = trim((string) $value); return $value === '' ? null : $value; } }