Spec 432: Exchange PowerShell production runner boundary and runtime gate. Validation: php artisan test --filter=Spec432 --compact; ./vendor/bin/pint --dirty --test --format agent; git diff --check. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #499
82 lines
3.7 KiB
PHP
82 lines
3.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\TenantConfiguration;
|
|
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\ManagedEnvironmentPermission;
|
|
use App\Models\ProviderConnection;
|
|
use App\Support\Providers\ProviderReasonCodes;
|
|
|
|
final class ExchangePowerShellPermissionEvidenceEvaluator
|
|
{
|
|
private const string PERMISSION_KEY = 'Exchange.ManageAsApp';
|
|
|
|
public function evaluate(ManagedEnvironment $environment, ProviderConnection $connection): ExchangePowerShellGateResult
|
|
{
|
|
$permission = ManagedEnvironmentPermission::query()
|
|
->where('workspace_id', (int) $environment->workspace_id)
|
|
->where('managed_environment_id', (int) $environment->getKey())
|
|
->where('permission_key', self::PERMISSION_KEY)
|
|
->orderByDesc('last_checked_at')
|
|
->orderByDesc('id')
|
|
->first();
|
|
|
|
if (! $permission instanceof ManagedEnvironmentPermission) {
|
|
return $this->blocked('permission_evidence_blocked_missing', 'permission_evidence_state', 'missing');
|
|
}
|
|
|
|
$details = is_array($permission->details) ? $permission->details : [];
|
|
|
|
if ((string) $permission->status !== 'granted') {
|
|
return $this->blocked('permission_evidence_blocked_unvalidated', 'permission_evidence_state', 'unvalidated', $permission);
|
|
}
|
|
|
|
if (! $permission->last_checked_at || $permission->last_checked_at->lt(now()->subDays(30))) {
|
|
return $this->blocked('permission_evidence_blocked_stale', 'permission_evidence_state', 'stale', $permission);
|
|
}
|
|
|
|
if ((int) ($details['workspace_id'] ?? 0) !== (int) $connection->workspace_id) {
|
|
return $this->blocked('permission_evidence_blocked_wrong_workspace', 'permission_evidence_state', 'wrong_workspace', $permission);
|
|
}
|
|
|
|
if ((int) ($details['managed_environment_id'] ?? 0) !== (int) $connection->managed_environment_id) {
|
|
return $this->blocked('permission_evidence_blocked_wrong_environment', 'permission_evidence_state', 'wrong_environment', $permission);
|
|
}
|
|
|
|
if ((string) ($details['provider'] ?? '') !== (string) $connection->provider) {
|
|
return $this->blocked('permission_evidence_blocked_unsupported_provider', 'permission_evidence_state', 'unsupported_provider', $permission);
|
|
}
|
|
|
|
if ((int) ($details['provider_connection_id'] ?? 0) !== (int) $connection->getKey()) {
|
|
return $this->blocked('permission_evidence_blocked_wrong_provider_connection', 'permission_evidence_state', 'wrong_provider_connection', $permission);
|
|
}
|
|
|
|
return ExchangePowerShellGateResult::allowed([
|
|
'permission_evidence_state' => 'verified',
|
|
'permission_key' => self::PERMISSION_KEY,
|
|
'permission_evidence_id' => (int) $permission->getKey(),
|
|
'last_checked_at' => $permission->last_checked_at?->toJSON(),
|
|
]);
|
|
}
|
|
|
|
private function blocked(
|
|
string $failureCode,
|
|
string $stateKey,
|
|
string $state,
|
|
?ManagedEnvironmentPermission $permission = null,
|
|
): ExchangePowerShellGateResult {
|
|
return ExchangePowerShellGateResult::blocked(
|
|
reasonCode: ProviderReasonCodes::ProviderPermissionMissing,
|
|
failureCode: $failureCode,
|
|
message: 'Verified Exchange PowerShell permission evidence is required.',
|
|
context: array_filter([
|
|
$stateKey => $state,
|
|
'permission_key' => self::PERMISSION_KEY,
|
|
'permission_evidence_id' => $permission instanceof ManagedEnvironmentPermission ? (int) $permission->getKey() : null,
|
|
], static fn (mixed $value): bool => $value !== null && $value !== ''),
|
|
);
|
|
}
|
|
}
|