Выполнение шага 5:
• Updated Plan
└ Продолжаю итерацию 5 как отдельный рабочий срез поверх текущих SSH credentials.
□ Добавить модель/миграцию/repository для host_scans и покрыть repository тестами
□ Добавить SSH command runner и LinuxHostScanner с whitelist read-only команд
□ Подключить controller/routes/UI для запуска deep scan и просмотра результата
□ Прогнать проверки и зафиксировать ограничения Docker-верификации
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domovoy\Controllers;
|
||||
|
||||
use Domovoy\Models\Credential;
|
||||
use Domovoy\Repositories\CredentialRepository;
|
||||
use Domovoy\Services\Inventory\DeviceService;
|
||||
use Domovoy\Services\Security\CredentialVault;
|
||||
use Domovoy\Services\Ssh\SshCredentialTester;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class CredentialController
|
||||
{
|
||||
public function __construct(
|
||||
private DeviceService $deviceService,
|
||||
private CredentialRepository $credentialRepository,
|
||||
private CredentialVault $vault,
|
||||
private SshCredentialTester $sshCredentialTester
|
||||
) {
|
||||
}
|
||||
|
||||
public function create(ServerRequestInterface $request, ResponseInterface $response, array $args): ResponseInterface
|
||||
{
|
||||
$deviceId = (int)$args['id'];
|
||||
if ($this->deviceService->getDevice($deviceId) === null) {
|
||||
$response->getBody()->write('Device not found');
|
||||
return $response->withStatus(404);
|
||||
}
|
||||
|
||||
$data = $request->getParsedBody();
|
||||
$authMethod = ($data['auth_method'] ?? 'password') === 'private_key' ? 'private_key' : 'password';
|
||||
$credential = new Credential();
|
||||
$credential->deviceId = $deviceId;
|
||||
$credential->type = 'ssh';
|
||||
$credential->name = trim($data['name'] ?? '') ?: 'SSH';
|
||||
$credential->username = trim($data['username'] ?? '');
|
||||
$credential->port = max(1, min(65535, (int)($data['port'] ?? 22)));
|
||||
$credential->authMethod = $authMethod;
|
||||
|
||||
if ($authMethod === 'private_key') {
|
||||
$privateKey = trim($data['private_key'] ?? '');
|
||||
if ($privateKey !== '') {
|
||||
$credential->encryptedPrivateKey = $this->vault->encrypt($privateKey);
|
||||
}
|
||||
} else {
|
||||
$secret = (string)($data['secret'] ?? '');
|
||||
if ($secret !== '') {
|
||||
$credential->encryptedSecret = $this->vault->encrypt($secret);
|
||||
}
|
||||
}
|
||||
|
||||
if ($credential->username === '') {
|
||||
return $response
|
||||
->withHeader('Location', '/devices/' . $deviceId)
|
||||
->withStatus(302);
|
||||
}
|
||||
|
||||
$this->credentialRepository->save($credential);
|
||||
|
||||
return $response
|
||||
->withHeader('Location', '/devices/' . $deviceId)
|
||||
->withStatus(302);
|
||||
}
|
||||
|
||||
public function test(ServerRequestInterface $request, ResponseInterface $response, array $args): ResponseInterface
|
||||
{
|
||||
$deviceId = (int)$args['deviceId'];
|
||||
$credential = $this->credentialRepository->findById((int)$args['id']);
|
||||
$device = $this->deviceService->getDevice($deviceId);
|
||||
|
||||
if ($credential === null || $device === null || $credential->deviceId !== $deviceId) {
|
||||
$response->getBody()->write('Credential not found');
|
||||
return $response->withStatus(404);
|
||||
}
|
||||
|
||||
$host = $device->primaryIp ?: ($device->hostname ?? '');
|
||||
$result = $this->sshCredentialTester->test($credential, $host);
|
||||
$this->credentialRepository->updateTestResult((int)$credential->id, $result['status']);
|
||||
|
||||
return $response
|
||||
->withHeader('Location', '/devices/' . $deviceId)
|
||||
->withStatus(302);
|
||||
}
|
||||
|
||||
public function delete(ServerRequestInterface $request, ResponseInterface $response, array $args): ResponseInterface
|
||||
{
|
||||
$deviceId = (int)$args['deviceId'];
|
||||
$this->credentialRepository->deleteForDevice((int)$args['id'], $deviceId);
|
||||
|
||||
return $response
|
||||
->withHeader('Location', '/devices/' . $deviceId)
|
||||
->withStatus(302);
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,16 @@ class DeviceController
|
||||
{
|
||||
private \Domovoy\Services\Inventory\DeviceService $deviceService;
|
||||
private \Domovoy\Repositories\DiscoveredHostRepository $discoveredHostRepository;
|
||||
private \Domovoy\Repositories\CredentialRepository $credentialRepository;
|
||||
|
||||
public function __construct(
|
||||
\Domovoy\Services\Inventory\DeviceService $deviceService,
|
||||
\Domovoy\Repositories\DiscoveredHostRepository $discoveredHostRepository
|
||||
\Domovoy\Repositories\DiscoveredHostRepository $discoveredHostRepository,
|
||||
\Domovoy\Repositories\CredentialRepository $credentialRepository
|
||||
) {
|
||||
$this->deviceService = $deviceService;
|
||||
$this->discoveredHostRepository = $discoveredHostRepository;
|
||||
$this->credentialRepository = $credentialRepository;
|
||||
}
|
||||
|
||||
public function index(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||
@@ -82,6 +85,7 @@ class DeviceController
|
||||
$username = $_SESSION['username'] ?? 'User';
|
||||
$types = Device::$types;
|
||||
$importances = Device::$importances;
|
||||
$credentials = $this->credentialRepository->findByDevice($id);
|
||||
require dirname(__DIR__, 2) . '/templates/devices/show.php';
|
||||
$body = ob_get_clean();
|
||||
$response->getBody()->write($body);
|
||||
|
||||
Reference in New Issue
Block a user