$settings */ public function __construct( private CredentialVault $vault, ?callable $clientFactory = null, private array $settings = [] ) { $this->clientFactory = $clientFactory ?? static fn (string $host, int $port, int $timeout): SSH2 => new SSH2($host, $port, $timeout); } /** @return array{status: string, message: string} */ public function test(Credential $credential, string $host): array { if ($host === '') { return ['status' => 'failed', 'message' => 'У устройства не указан IP или hostname']; } try { $client = ($this->clientFactory)( $host, $credential->port, (int)($this->settings['connect_timeout'] ?? 5) ); $auth = $this->buildAuth($credential); $ok = $client->login($credential->username, $auth); if ($ok) { return ['status' => 'ok', 'message' => 'Подключение успешно']; } return ['status' => 'failed', 'message' => 'SSH-аутентификация не прошла']; } catch (\Throwable $e) { return ['status' => 'failed', 'message' => 'Ошибка SSH: ' . $e->getMessage()]; } } private function buildAuth(Credential $credential): mixed { if ($credential->authMethod === 'private_key') { if ($credential->encryptedPrivateKey === null) { throw new \RuntimeException('Private key is empty'); } return PublicKeyLoader::loadPrivateKey($this->vault->decrypt($credential->encryptedPrivateKey)); } if ($credential->encryptedSecret === null) { throw new \RuntimeException('Password is empty'); } return $this->vault->decrypt($credential->encryptedSecret); } }