resolveConnection($credential); if (! $connection instanceof ProviderConnection) { return; } $tenant = $connection->tenant; if (! $tenant instanceof Tenant) { return; } $this->audit( tenant: $tenant, connection: $connection, action: 'provider_connection.credentials_created', changedFields: ['type', 'client_id', 'client_secret'], ); } public function updated(ProviderCredential $credential): void { $connection = $this->resolveConnection($credential); if (! $connection instanceof ProviderConnection) { return; } $tenant = $connection->tenant; if (! $tenant instanceof Tenant) { return; } $changedFields = $this->changedFields($credential); if ($changedFields === []) { return; } $action = in_array('client_secret', $changedFields, true) ? 'provider_connection.credentials_rotated' : 'provider_connection.credentials_updated'; $this->audit( tenant: $tenant, connection: $connection, action: $action, changedFields: $changedFields, ); } private function resolveConnection(ProviderCredential $credential): ?ProviderConnection { $credential->loadMissing('providerConnection.tenant'); return $credential->providerConnection; } /** * @return array */ private function changedFields(ProviderCredential $credential): array { $fields = []; if ($credential->isDirty('type') || $credential->wasChanged('type')) { $fields[] = 'type'; } $previousPayload = $credential->getOriginal('payload'); $currentPayload = $credential->payload; $previousPayload = is_array($previousPayload) ? $previousPayload : []; $currentPayload = is_array($currentPayload) ? $currentPayload : []; $previousClientId = trim((string) ($previousPayload['client_id'] ?? '')); $currentClientId = trim((string) ($currentPayload['client_id'] ?? '')); if ($previousClientId !== $currentClientId) { $fields[] = 'client_id'; } $previousClientSecret = trim((string) ($previousPayload['client_secret'] ?? '')); $currentClientSecret = trim((string) ($currentPayload['client_secret'] ?? '')); if ($previousClientSecret !== $currentClientSecret) { $fields[] = 'client_secret'; } return array_values(array_unique($fields)); } /** * @param array $changedFields */ private function audit( Tenant $tenant, ProviderConnection $connection, string $action, array $changedFields, ): void { $user = auth()->user(); $actorId = $user instanceof User ? (int) $user->getKey() : null; $actorEmail = $user instanceof User ? $user->email : null; $actorName = $user instanceof User ? $user->name : null; app(AuditLogger::class)->log( tenant: $tenant, action: $action, context: [ 'metadata' => [ 'provider_connection_id' => (int) $connection->getKey(), 'provider' => (string) $connection->provider, 'entra_tenant_id' => (string) $connection->entra_tenant_id, 'credential_type' => (string) $connection->credential?->type, 'changed_fields' => $changedFields, 'redacted_fields' => ['client_secret'], ], ], actorId: $actorId, actorEmail: $actorEmail, actorName: $actorName, resourceType: 'provider_connection', resourceId: (string) $connection->getKey(), status: 'success', ); } }